User Acquisition is one of the hardest challenge that a company faces. It's really important to get the proper level of reporting in order to take the proper marketing decisions and identify the best acquisition lever and their unit economics.
Most generally, Business wants to bridge their Marketing efforts (Ads, Partnerships, Referrals) with the associated Sales impacts (revenue, MRR, etc.).
In order to track such a wide funnel, many sources must be blend together, this post will help you to understand how to track your:
Marketing Spend
New Marketing Qualified Leads
New Sales Qualified Leads
New Customers
New Revenue
MQL -> SQL Conversion rate
SQL -> Customer conversion rate
Return on Ad Spent (ROAS)
and see it breakdown per:
Date
Acquisition Channel (Paid Ads, Social Ads, Referral, Partnerships, Organic, etc.)
We'll consolidate those events into a "Funnel table" to get a complete view
We'll create an Exploration and create our metrics to track our Conversion rate, etc.
We'll build our Dashboard to share with our stakeholders and make better decisions!
Pre-requisites
This guides assume that you have imported all the data sources of your Marketing Funnel into your Data Warehouse. Whaly offers you a number of connectors that is making this task really easy. More specifically, you'll need:
a. Your Ads sources (Google Ads, Facebook Ads, LinkedIn Ads, a Google Sheets linked to Zapier or Supermetrics for other sources)
b. Your CRM (Hubspot, Salesforce, Pipedrive)
c. (Optionally) The financial tool in which you track your revenue (Stripe, Brex, Quickbooks, Qonto, etc.)
Event models and Funnel tables
In order to track your Marketing Funnel, we'll use the "Event Models - Funnel Tables" paradigm. This pattern is very powerful as it will be very easy to add new Data Sources and define Events as your marketing stack evolves and your Funnel becomes more complex.
It means that we'll create:
Event Models
Each time that something occurs in your Marketing Funnel, we'll create an "Event". Each event has:
an Event Date
an Event Name ("Marketing Spend" / "MQL Created" / "Customer Created") - This taxonomy should be customised based on your Marketing Funnel + Sales Pipeline processes.
Optional attributes. Main ones are:
Channel: The name of the Marketing Channel that this event should be linked to. Ex. Paid Ads / Social Ads / Referral
Source: The name of the marketing source related to the event. Ex. Google Ads, Facebook Ads, ...
Campaign: The name of the campaign related to the campaign.
Object IDs: If there is any related object to the event, a column to hold the IDs of the related object should be added (ex. a Facebook Campaign, a Salesforce Opportunity, a Stripe Customer). Those will be used to combine the Events with the associated objects to get insights later.
Revenue: If there is any revenue related to the event.
Spend: If there is any spent related to the event.
For revenue and spend columns, it's better to suffix those columns name with the currency in which they are tracked. Ex revenue_usd / spend_eur / revenue_eur_cents.
Otherwise, you might have discrepancy later when combining the events.
Funnel tables
Once we have properly defined and create each of the "Event Models", we'll create "Funnel Tables" that will consolidate those Events into a single table.
Those Funnel Tables can either import all your Events Models or only selected ones, depending on the reporting that you need to do.
It's often recommended to create a complete Funnel table with all the events, and more specific Funnel tables to zoom in the top or the bottom of your Funnel.
Generating Events from the different steps of your Marketing Funnel is a very great idea as those could be shared in the future to others teams of your Company such as your Data Scientist that will be able to turn them into recommendations to boost the performance of your Marketing Campaigns!
We'll create a SQL Model called "Marketing Spend - Google Ads", this model will be in charge of:
Removed things that are Ads specific or uninteresting for our Marketing Funnel (at least at this stage), like the device, the ad_network_type
Keep only a Daily campaign spend
with the following query:
WITH ad_spend_info AS ( -- Reading only what we need from the DataWarehouseSELECTdate, campaign_id, costFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"Google Ads"."Campaign Stats"), daily_spend AS ( -- Needed step to remove the device & ad_network_type granularitySELECTdate, campaign_id,sum(cost) as costFROM ad_spend_infoGROUP BY1, 2), event_info AS ( -- Enrich Google Ads data to create a proper EventSELECT"Marketing Spend"as event_name,dateas event_date,"Search Ads"as channel,"Google Ads"as source, campaign_id, cost as spendFROM daily_spend)SELECT*FROM event_info
We now have a proper event table that is looking like:
Like for Google Ads, our model is quite easy to write:
WITH ad_spend_info AS ( -- Reading only what we need from the DataWarehouseSELECTdate, campaign_id, spendFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete "Facebook Ads"."Marketing Spent"), daily_spend AS ( -- Needed step to remove the ad_id granularitySELECTdate, campaign_id,sum(spend) as spendFROM ad_spend_infoGROUP BY1, 2), event_info AS ( -- Enrich Facebook Ads data to create a proper EventSELECT"Marketing Spend"as event_name,dateas event_date,"Social Ads"as channel,"Facebook Ads"as source, campaign_id, spendFROM daily_spend)SELECT*FROM event_info
Now, let's look into our CRM data to see how we can build the "MQL Created" Event Model. Let's imaging that you are using Hubspot, and that each new Lead is created as a Contact in Hubspot.
When having an Hubspot tracker on your Website that is used to create the contact when they submit a form, a lot of properties are automatically tracked by Hubspot.
The full documentation can be found here and here.
If you are using another CRM or if you have a custom way to create contacts into your CRM, get in touch with your CRM admin to see how you track the Marketing origin of your Leads.
By using UTMs properly both in your Marketing tools and in your Contact creation logic, you can track the origin of each of your Lead.
a. Properly map the values and columns from Hubspot to the taxonomy used in the Marketing Spend events
b. Map the proper date to the Event Date -> when tracking new MQL, it is common to use the contact creation date as the event date
WITH contact_info AS ( -- Reading only what we need from the DataWarehouseSELECT property_createdate as contact_creation_date, contact_id, property_hs_analytics_source as hs_origin_source, property_hs_analytics_source_data_1 as hs_origin_data1, property_hs_analytics_source_data_2 as hs_origin_data2FROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"Hubspot"."Contact"), cleaned_contact AS ( -- Needed step to map Hubspot generated value with our events taxonomy for source and channelSELECT contact_creation_date, contact_id,CASEWHEN hs_origin_source ="PAID_SOCIAL"THEN"Social Ads"WHEN hs_origin_source ="PAID_SEARCH"THEN"Search Ads"ELSE hs_origin_sourceENDas channel,CASEWHEN hs_origin_source ="PAID_SOCIAL"AND hs_origin_data1 ="Facebook"THEN"Facebook Ads"WHEN hs_origin_source ="PAID_SEARCH"THEN"Google Ads"ELSE"unknown"ENDas sourceFROM contact_info), event_info AS ( -- Enrich Hubspot data to create a proper EventSELECT contact_creation_date as event_date,"MQL Created"as event_name, channel, source, contact_idFROM cleaned_contact)SELECT*FROM event_info
in our example, to stay simple, we'll say that a SQL is tracked in our CRM when a contact has a "Date Quote Sent" set.
In reality, SQL are often tracked as Deals / Opportunity in the CRM, so your SQL Event Model might be based on the Deal / Opportunity object, but the logic stay the same.
If we keep the same Hubspot table as above, our Model definition would be:
WITH contact_info AS ( -- Reading only what we need from the DataWarehouseSELECT property_date_quote_sent as contact_quote_sent_date, contact_id, property_hs_analytics_source as hs_origin_source, property_hs_analytics_source_data_1 as hs_origin_data1, property_hs_analytics_source_data_2 as hs_origin_data2FROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"Hubspot"."Contact"-- This is where we only keep contact that were sent a Quote for the SQL definitionWHERE property_date_quote_sent IS NOT NULL), cleaned_contact AS ( -- Needed step to map Hubspot generated value with our events taxonomy for source and channelSELECT contact_quote_sent_date, contact_id,CASEWHEN hs_origin_source ="PAID_SOCIAL"THEN"Social Ads"WHEN hs_origin_source ="PAID_SEARCH"THEN"Search Ads"ELSE hs_origin_sourceENDas channel,CASEWHEN hs_origin_source ="PAID_SOCIAL"AND hs_origin_data1 ="Facebook"THEN"Facebook Ads"WHEN hs_origin_source ="PAID_SEARCH"THEN"Google Ads"ELSE"unknown"ENDas sourceFROM contact_info), event_info AS ( -- Enrich Hubspot data to create a proper EventSELECT contact_quote_sent_date as event_date,"SQL Created"as event_name, channel, source, contact_idFROM cleaned_contact)SELECT*FROM event_info
As you can see, the logic to convert the Hubspot "origin" columns into our Event taxonomy is duplicated in both the MQL and SQL models.
As this mapping will have to change in the future and as it's hard to deal with code duplication, a good thing would be to create a "Contact With Marketing Origin" model containing the mapping logic once and use it in both MQL Created and SQL Created Models configuration.
We'll stop here the definition of our Events, but the same logic and principles can be used to create other events of the bottom of your funnel:
Demo done
Contract Signed
Upsell done
etc.
It all depends of how your Sales Funnel is structured!
2. Build our "Funnel Table"
Now that we have our 4 Events:
Marketing Spend (Google Ads)
Marketing Spend (Facebook Ads)
MQL Created
SQL Created
We'll create a "Funnel table" that will import all those events into a consolidated timeline to do reporting and calculate conversion rates and MQL / SQL acquisition costs.
This Funnel table is once agin a Model defined as:
-- || Top of the funnel || ---- Google AdsSELECT event_date, event_name, channel, source, campaign_id, spend,'n/a'as contact_idFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"Marketing Spend Event - Google Ads"UNION ALL-- Facebook AdsSELECT event_date, event_name, channel, source, campaign_id, spend,-- We add fake values for the columns specific to the MQL/SQL Created events'n/a'as contact_idFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"Marketing Spend Event - Facebook Ads"UNION ALL-- MQL CreatedSELECT event_date, event_name, channel, source, contact_id,-- We add fake values into the columns that are specific to the Marketing Spend events'n/a'as campaign_id,0as spendFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"MQL Created"UNION ALLSELECT event_date, event_name, channel, source, contact_id,-- We add fake values into the columns that are specific to the Marketing Spend events'n/a'as campaign_id,0as spendFROM-- When copy pasting into Whaly Workbench, please erase this value -- and rewrite it to select the proper table in the auto complete"SQL Created"-- || Bottom of the funnel || --
This single table consolidate all our Marketing Funnel events into a single view, with a consolidated taxonomy 🎉
Now that we did the "hard" part, we only have to do the "nice" job to create an Exploration on top of this table!
3. Create an Exploration
Now that we have our single table, we can create an Exploration with the following configuration:
Dimensions:
event_date as Date
channel as Channel
source as Source
Metrics:
SUM(spend) | If event_name = "Marketing Spend" as Spend
COUNT | If event_name = "MQL Created" as MQLs
COUNT | If event_name = "SQL Created" as SQLs
Calculated Metrics:
SQLs / MQLs as "MQLs -> SQLs conversion rate"
Spend / MQLs as "CAC MQLs"
Spend / SQLs as "CAC SQLs"
4. Create a dashboard
Now you can chart your CACs, Conversion rate and funnel breakdown by Channel / Sources.
5. Next steps
This guide only covers a simple marketing funnel, however, there can be many differents direction to take from there:
You can add other Events in the Bottom of your funnel to have a better view of where you lose Customers and Revenue per Channel / Source
You can add events that have a "revenue" attributes (ex. Contract Signed) and create a new "revenue" column in your Funnel table. This will unlock the ROAS metric.
If you have the Campaign IDs stored in your CRM when Leads are created, you can expose it in the funnel and get a "per Campaign" view of your Funnel
You can even go one step further and build this funnel at the "Ad Group" / "Ad" level by adding the proper attribute to all the events on the chain (you probably have to tweak a bit the way your campaigns are tracked in your CRM when Leads are created to get this level of details)