Campaign and ad tracking
Campaign and ad tracking captures how users arrive at your site from marketing campaigns and how they interact with advertisements.
Use campaign and ad tracking to:
- Attribute traffic to specific marketing campaigns
- Measure ad impression and click performance
- Track conversions from ad campaigns
- Analyze the effectiveness of different marketing channels
Campaign atomic event properties
The campaign attribution enrichment can automatically capture UTM parameters from URLs and populate atomic event properties for campaign analysis.
Advertisement events
Ad tracking captures impressions, clicks, and conversions from advertisements displayed on your site or elsewhere.
See also media tracking for tracking advertising content consumed within video or audio media.
This table shows the support for ad tracking across the main client-side Snowplow tracker SDKs.
| Tracker | Supported | Since version | Auto-tracking | Notes |
|---|---|---|---|---|
| Web | ✅ | 1.1.0 (directly), 3.0.0 (as plugin) | ❌ | Requires the ad tracking plugin |
| iOS | ❌ | |||
| Android | ❌ | |||
| React Native | ❌ | |||
| Flutter | ❌ | |||
| Roku | ❌ | |||
| Google Tag Manager | ✅ | v3 | ❌ |
Ad impression event
Track when an ad is displayed to a user.
ad_impression
EventExample
{
"impressionId": "67965967893",
"costModel": "cpm",
"cost": 5.5,
"targetUrl": "http://www.example.com",
"bannerId": "23",
"zoneId": "7",
"advertiserId": "201",
"campaignId": "12"
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
impressionIdstring | Optional. Identifier for the impression instance |
costModelstring | Optional. The cost model: cpa, cpc, or cpm Must be one of: cpa, cpc, cpm |
costnumber | Optional. The cost of the impression |
targetUrlstring | Optional. The destination URL |
bannerIdstring | Optional. Adserver identifier for the ad banner |
zoneIdstring | Optional. Adserver identifier for the zone |
advertiserIdstring | Optional. Adserver identifier for the advertiser |
campaignIdstring | Optional. Adserver identifier for the campaign |
{
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
"description": "Schema for an ad impression event",
"self": {
"vendor": "com.snowplowanalytics.snowplow",
"name": "ad_impression",
"format": "jsonschema",
"version": "1-0-0"
},
"type": "object",
"properties": {
"impressionId": {
"type": "string",
"description": "Identifier for the impression instance"
},
"costModel": {
"type": "string",
"enum": [
"cpa",
"cpc",
"cpm"
],
"description": "The cost model: cpa, cpc, or cpm"
},
"cost": {
"type": "number",
"description": "The cost of the impression"
},
"targetUrl": {
"type": "string",
"description": "The destination URL"
},
"bannerId": {
"type": "string",
"description": "Adserver identifier for the ad banner"
},
"zoneId": {
"type": "string",
"description": "Adserver identifier for the zone"
},
"advertiserId": {
"type": "string",
"description": "Adserver identifier for the advertiser"
},
"campaignId": {
"type": "string",
"description": "Adserver identifier for the campaign"
}
},
"additionalProperties": false
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_snowplow_ad_impression_1 ad_impression_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_impression'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_impression_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'ad_impression'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_impression_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'ad_impression'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
and unstruct_event_com_snowplowanalytics_snowplow_ad_impression_1 is not null
select
"ad_impression_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_snowplow_ad_impression_1 "ad_impression_1"
on "ad_impression_1".root_id = events.event_id and "ad_impression_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "ad_impression_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_impression'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
Ad click event
Track when a user clicks on an ad.
ad_click
EventExample
{
"targetUrl": "http://www.example.com",
"clickId": "12243253",
"costModel": "cpm",
"cost": 2.5,
"bannerId": "23",
"zoneId": "7",
"impressionId": "67965967893",
"advertiserId": "201",
"campaignId": "12"
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
targetUrlstring | Required. The destination URL |
clickIdstring | Optional. Identifier for the click instance |
costModelstring | Optional. The cost model Must be one of: cpa, cpc, cpm |
costnumber | Optional. The cost of the click |
bannerIdstring | Optional. Adserver identifier for the ad banner |
zoneIdstring | Optional. Adserver identifier for the zone |
impressionIdstring | Optional. Links click to impression |
advertiserIdstring | Optional. Adserver identifier for the advertiser |
campaignIdstring | Optional. Adserver identifier for the campaign |
{
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
"description": "Schema for an ad click event",
"self": {
"vendor": "com.snowplowanalytics.snowplow",
"name": "ad_click",
"format": "jsonschema",
"version": "1-0-0"
},
"type": "object",
"properties": {
"targetUrl": {
"type": "string",
"description": "The destination URL"
},
"clickId": {
"type": "string",
"description": "Identifier for the click instance"
},
"costModel": {
"type": "string",
"enum": [
"cpa",
"cpc",
"cpm"
],
"description": "The cost model"
},
"cost": {
"type": "number",
"description": "The cost of the click"
},
"bannerId": {
"type": "string",
"description": "Adserver identifier for the ad banner"
},
"zoneId": {
"type": "string",
"description": "Adserver identifier for the zone"
},
"impressionId": {
"type": "string",
"description": "Links click to impression"
},
"advertiserId": {
"type": "string",
"description": "Adserver identifier for the advertiser"
},
"campaignId": {
"type": "string",
"description": "Adserver identifier for the campaign"
}
},
"required": [
"targetUrl"
],
"additionalProperties": false
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_snowplow_ad_click_1 ad_click_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_click'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_click_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'ad_click'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_click_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'ad_click'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
and unstruct_event_com_snowplowanalytics_snowplow_ad_click_1 is not null
select
"ad_click_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_snowplow_ad_click_1 "ad_click_1"
on "ad_click_1".root_id = events.event_id and "ad_click_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "ad_click_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_click'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
Ad conversion event
Track when a user completes a conversion action from an ad.
ad_conversion
EventExample
{
"conversionId": "743560297",
"costModel": "cpa",
"cost": 10,
"category": "ecommerce",
"action": "purchase",
"property": "",
"initialValue": 99,
"advertiserId": "201",
"campaignId": "12"
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
conversionIdstring | Optional. Identifier for the conversion instance |
costModelstring | Optional. The cost model Must be one of: cpa, cpc, cpm |
costnumber | Optional. The cost of the conversion |
categorystring | Optional. Conversion category |
actionstring | Optional. The type of user interaction, e.g. purchase |
propertystring | Optional. Describes the object of the conversion |
initialValuenumber | Optional. How much the conversion is initially worth |
advertiserIdstring | Optional. Adserver identifier for the advertiser |
campaignIdstring | Optional. Adserver identifier for the campaign |
{
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
"description": "Schema for an ad conversion event",
"self": {
"vendor": "com.snowplowanalytics.snowplow",
"name": "ad_conversion",
"format": "jsonschema",
"version": "1-0-0"
},
"type": "object",
"properties": {
"conversionId": {
"type": "string",
"description": "Identifier for the conversion instance"
},
"costModel": {
"type": "string",
"enum": [
"cpa",
"cpc",
"cpm"
],
"description": "The cost model"
},
"cost": {
"type": "number",
"description": "The cost of the conversion"
},
"category": {
"type": "string",
"description": "Conversion category"
},
"action": {
"type": "string",
"description": "The type of user interaction, e.g. purchase"
},
"property": {
"type": "string",
"description": "Describes the object of the conversion"
},
"initialValue": {
"type": "number",
"description": "How much the conversion is initially worth"
},
"advertiserId": {
"type": "string",
"description": "Adserver identifier for the advertiser"
},
"campaignId": {
"type": "string",
"description": "Adserver identifier for the campaign"
}
},
"additionalProperties": false
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_snowplow_ad_conversion_1 ad_conversion_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_conversion'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_conversion_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'ad_conversion'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_ad_conversion_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'ad_conversion'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
and unstruct_event_com_snowplowanalytics_snowplow_ad_conversion_1 is not null
select
"ad_conversion_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_snowplow_ad_conversion_1 "ad_conversion_1"
on "ad_conversion_1".root_id = events.event_id and "ad_conversion_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "ad_conversion_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'ad_conversion'
and events.event_vendor = 'com.snowplowanalytics.snowplow'