Skip to content
Black BoxPersonalization

Last updated

Collect

Paid and social measurement

Paid and social measurement. One conversion, named once, then read by every pixel and every server API. This page builds the plan, the links, and the payloads. It sends nothing and stores nothing.

  1. 1Business KPI
  2. 2Conversion event
  3. 3Shared taxonomy
  4. 4Tags and server
  5. 5QA

Start with the measurement plan

Write the business number first. Revenue, qualified leads, or activated accounts. Then name the conversion that proves it. Then freeze the event names. Pixels come after that sheet exists.

The taxonomy is the only vocabulary. Every platform maps to it. Parameters that travel with every event: event_id, value, currency, and the item id when there is a catalog. event_id is shared by the browser tag and the server call so the platform can drop the duplicate.

Canonical names on this page are page_view, view_item, lead, sign_up, add_to_cart, begin_checkout, and purchase. GA4 recommended events use generate_lead for the lead. The sheet records that alias. People do not invent a second lead name in one tag.

CanonicalWhen it fires
page_viewA landing page or other key page loads.
view_itemA product or offer is viewed.
leadA form or demo request is submitted.
sign_upAn account is created.
add_to_cartAn item is added to the cart.
begin_checkoutCheckout starts.
purchaseAn order is paid.

Names on each platform

Google Ads, Microsoft UET, and X identify conversions by an id you create in the ad account. The cell says so. The other cells are the standard event names those platforms publish. LinkedIn still needs the conversion rule id even when the category has a standard word.

CanonicalGA4Google AdsMetaLinkedInTikTokPinterestSnapchatXMicrosoftReddit
page_viewpage_viewConversion you namePageViewKEY_PAGE_VIEWViewContentPageVisitPAGE_VIEWEvent id you createGoal you namePageVisit
view_itemview_itemConversion you nameViewContentRule you nameViewContentPageVisitVIEW_CONTENTEvent id you createGoal you nameViewContent
leadgenerate_leadConversion you nameLeadLEADLeadLeadCustom, or SIGN_UPEvent id you createGoal you nameLead
sign_upsign_upConversion you nameCompleteRegistrationSIGN_UPCompleteRegistrationSignupSIGN_UPEvent id you createGoal you nameSignUp
add_to_cartadd_to_cartConversion you nameAddToCartADD_TO_CARTAddToCartAddToCartADD_CARTEvent id you createGoal you nameAddToCart
begin_checkoutbegin_checkoutConversion you nameInitiateCheckoutSTART_CHECKOUTInitiateCheckoutCustom event you nameSTART_CHECKOUTEvent id you createGoal you nameCustom event you name
purchasepurchaseConversion you name, with order idPurchasePURCHASEPurchaseCheckoutPURCHASEEvent id you createRevenue goal you namePurchase
  • GA4. Recommended events. transaction_id on purchase is the order id.
  • Google Ads. A conversion action you create, often imported from the GA4 event.
  • Meta. Standard Pixel events. The same event_name goes to the Conversions API.
  • LinkedIn. Category on the conversion rule. The API call sends that rule id.
  • TikTok. Current standard names. CompletePayment still arrives, Purchase is the name to use.
  • Pinterest. Checkout is the purchase event. There is no standard begin-checkout name.
  • Snapchat. Standard event names are uppercase. A lead that is not a sign-up is a custom event.
  • X. The event id comes from Ads Manager. The pixel and the API share it.
  • Microsoft. A UET goal or custom event you name. Revenue goals take value and currency.
  • Reddit. Standard pixel events. Begin checkout has no standard name.

Campaign links and click ids

utm_source is the place. utm_medium is the channel. utm_campaign is the effort, shared by every ad in it. utm_content is the creative. utm_term is the keyword. Lowercase, hyphens, no spaces, no email addresses.

Click ids are not UTMs. They are case-sensitive and they expire on the platform clock. Persist them in a first-party cookie or on the server session, first touch and last touch, and send the one the platform documents. Do not hash them. This page does not set that cookie.

ChannelMediumSourceClick ids
Paid searchcpcgoogle, bing, microsoftgclid, gbraid, wbraid, msclkid
Paid socialpaid-socialfacebook, instagram, tiktok, linkedin, pinterest, snapchat, reddit, xfbclid, ttclid, li_fat_id, epik, ScCid, twclid, rdt_cid
Displaydisplaythe network namethe click id that network documents
Emailemailthe list or product namenone
Affiliatesaffiliatethe partner slugthe partner click id, if they send one
ParameterPlatformHow to keep it
gclidGoogle AdsFirst-party cookie or the server session. The value is case-sensitive.
gbraidGoogle Ads, app to webStore it with gclid. It is the iOS app-to-web click.
wbraidGoogle Ads, web to appStore it with gclid. It is the iOS web-to-app click.
fbclidMetaThe browser tag turns it into _fbc. Do not hash fbc or fbclid.
ttclidTikTokFirst-party. Send it on the Events API call.
li_fat_idLinkedInFirst-party ad tracking id. Send it with the conversion.
msclkidMicrosoft AdsFirst-party. UET attribution needs it.
ScCidSnapchatKeep this spelling. Do not lowercase the parameter name.
twclidXFirst-party click id for the X pixel and the conversions API.
epikPinterestFirst-party. The tag may also set a cookie named _epik.
rdt_cidRedditFirst-party click id for the Reddit Conversions API.

UTM builder and linter

Source, medium, and campaign are required. Values are lowercased. Spaces fail the check. The UTM builder is the same naming rule. This one also flags a medium that disagrees with the source.

Channel group: Unassigned

Fix the required fields to build the link.

Click id detector

Paste a landing URL, or read the URL of this page. The detector looks only at the query string. It does not read cookies and it does not store the values.

ParameterPlatformOn this URL
gclidGoogle Adsabsent
gbraidGoogle Ads, app to webabsent
wbraidGoogle Ads, web to appabsent
fbclidMetaabsent
ttclidTikTokabsent
li_fat_idLinkedInabsent
msclkidMicrosoft Adsabsent
ScCidSnapchatabsent
twclidXabsent
epikPinterestabsent
rdt_cidRedditabsent

One data layer

The page pushes one object. Every tag reads it. The dataLayer lab shows that queue for this site. Hash email before it is placed on the object. Leave the raw address out.

Purchase push

The same event_id is the GA4 transaction id and the dedup key for the ad platforms.

dataLayer.push({
  event: "purchase",
  event_id: "order-1001",
  ecommerce: {
    transaction_id: "order-1001",
    value: 42.5,
    currency: "USD",
    items: [{ item_id: "sku-1", item_name: "Notebook", price: 42.5, quantity: 1 }]
  },
  user_data: {
    sha256_email_address: "<sha256 of the trimmed lowercase email>"
  },
  campaign: {
    source: "google",
    medium: "cpc",
    campaign: "spring-shoes",
    content: "static-offer",
    term: "running-shoes",
    click_ids: { gclid: "<from the landing url>" }
  },
  consent: { analytics_storage: "granted", ad_storage: "granted" }
});

Tag manager architecture

Google Tag Manager: a data layer variable for each field, one trigger for the event name, one tag per platform. Consent is a tag setting, not a second trigger someone forgets. Firing order does not matter when every tag reads the same push.

Adobe Experience Platform Tags, still called Launch: a data element per field, one rule, one action per platform, and a condition for consent. Event Forwarding sends the server copy from the edge with the same event id. Adobe Target may swap the headline. It should read the campaign object, not invent a new event name.

Google Tag Manager

Variables, one trigger, one tag per platform, consent on the tag.

// One data layer push. Tags only read it.
// Variables: DLV - event_id, DLV - ecommerce.value, DLV - ecommerce.currency, DLV - campaign.source
// Trigger: Custom Event, event name equals purchase
// Tags, each with its own consent setting:
//   GA4 event purchase          requires analytics_storage
//   Google Ads conversion       requires ad_storage and ad_user_data
//   Meta Pixel Purchase         requires ad_storage, eventID = {{DLV - event_id}}
//   One more tag per platform, same trigger, same event id
// Do not chain tags so that tag 2 reads a variable tag 1 invented.
// Server container: the same event id is forwarded. It is not a second purchase.

Adobe tags and Target

Data elements and one rule. Event Forwarding is the server copy.

// Adobe Experience Platform Tags (Launch)
// Data element: event_id, from the data layer path event_id
// Data element: order_value, from ecommerce.value
// Rule: Event equals purchase
//   Condition: consent ad_storage equals granted
//   Action: one action per platform, each reading the same data elements
// Event Forwarding rule: same event, same event_id, sent from the edge
// Adobe Target reads campaign.source and campaign.content. It does not invent a second name.

Tag alignment matrix

Purchase is the example. The same columns apply to every canonical event. Swap the pixel name from the mapping table.

PlatformClient tagServer APIDedup keyConsent
GA4gtag eventMeasurement Protocoltransaction_id, or event_idAnalytics
Google AdsGoogle tag conversionEnhanced conversions and offline importorder id or transaction_idAds
Metafbq trackConversions APIevent_id and event_nameAds
LinkedInInsight TagConversions APIevent id on the conversion ruleAds
TikTokttq trackEvents APIevent_idAds
Pinterestpintrk trackAPI for Conversionsevent_idAds
Snapchatsnaptr trackConversions APIclient_dedup_idAds
Xtwq eventConversions APIconversion_idAds
MicrosoftUET tagOffline and enhanced conversionsmsclkid plus conversion time, or the order idAds
Redditrdt trackConversions APIconversion_idAds

event_id …

canonical

purchase

One event. Each card is a tag that would read it. Nothing is sent.

Server events

The browser tag misses people. The server that already recorded the order can send the same event. Share the dedup key. Hash email and phone once, after trim and lowercase for email, and digits plus country code for phone. Do not hash click ids, IP addresses, or user agents. The CAPI lab shows the Meta rules in the browser. The offline conversions lab is the Measurement Protocol shape.

A server-side GTM container can forward one incoming event to these APIs. It is still one event id. It is not a second conversion.

  • GA4. Measurement Protocol. Related lab
  • Google Ads. Enhanced conversions, plus offline import. Related lab
  • Meta. Conversions API. Related lab
  • LinkedIn. Conversions API.
  • TikTok. Events API.
  • Pinterest. API for Conversions.
  • Snapchat. Conversions API.
  • X. Conversions API.
  • Microsoft. UET offline and enhanced conversions.
  • Reddit. Conversions API.

Google Consent Mode v2 has four signals: analytics_storage, ad_storage, ad_user_data, and ad_personalization. A consent management platform should set them before tags run. Denied means the ads tags do not fire. Advanced mode can let Google tags send a cookieless ping. That ping is still a Google feature you choose. It is not a silent exception.

Meta limited data use is a data-processing option for regional limits. It does not replace a consent choice. GDPR and ePrivacy expect a choice before non-essential cookies. CPRA is an opt-out of sale or share. Global Privacy Control is a signal to honor, not a banner to ignore.

On this site, Google Analytics waits for Accept, and Global Privacy Control forces measurement off. The dry runs follow the same idea: consent off omits the payload. The consent lab is the control itself.

Attribution and reconciliation

The ad platform, GA4, and the CRM will not print the same total. Windows differ, and they are set in each account. View-through counts a conversion after an impression. Modeled conversions fill gaps the platform estimates. Read the window and the model flag in the interface before you compare a number.

Compare order ids, not dashboard totals. A purchase in the platform and a purchase in GA4 with the same id is a match even when the credit splits differently. The attribution lab scores one journey six ways so you can see the split.

Incrementality is a holdout or a geo test, not a column in the ads report. Media mix models use spend and outcomes over weeks. They sit beside multi-touch, they do not replace the order-id check.

  • Same order id in the ad platform, GA4, and the CRM.
  • event_id present on both the pixel and the server call.
  • Click window and view window written down for each platform.
  • Modeled conversions labeled, and left out of a raw reconciliation.
  • Time zone and currency the same on every export.
  • Consent denied counted as not sent, not as a lost sale.
  • A lift test planned before you treat a platform lift number as causal.

QA and monitoring

Use the helper the platform ships. A passing helper and a missing order id is still a failed launch.

  1. The taxonomy sheet names every event, parameter, value, currency, and event id.
  2. A campaign link is lowercase and uses the channel medium in the table above.
  3. The data layer push is the only input. No tag builds its own event name.
  4. Each platform has one client tag and, where you use it, one server call, sharing the dedup key.
  5. Consent denied fires no ads tag. Analytics waits for the choice this site already uses.
  6. DebugView, Tag Assistant, and each platform helper show the same event id.
  7. A test order is excluded from bidding, with a test event code where the platform has one.
  8. The order id appears once in the ad platform and once in GA4. The totals are not required to match.

After launch, alert when volume drops, when event_id is empty, or when the server count and the pixel count diverge. The data quality lab and the anomalies lab are the checks this site runs on its own events.

Advanced measurement setups

These are the systems around the tag. Each row is a pattern and a boundary. Official links are at the bottom of the page. Closed loop, from the click to the CRM and back:

  1. 1 Click
  2. 2 Lead
  3. 3 Opportunity
  4. 4 Revenue
  5. 5 Ad platform
SetupWhat to do
Server-side taggingA server container on Cloud Run or App Engine, a first-party subdomain such as metrics.example.com, and the web container forwarding there. Adobe Event Forwarding is the same job on the Adobe edge.
Cookie durabilitySafari ITP limits JavaScript cookies. A server-set first-party cookie on your domain lasts longer than a third-party cookie. Do not work around the browser. Say what you store and why.
Google Ads leadsEnhanced conversions for leads hashes the email from the form. Offline import sends the closed deal later, with the gclid or the order id. A conversion adjustment restates the value when the CRM changes.
Value and profitValue-based bidding needs a value on the conversion. Send revenue, or profit, or a predicted lifetime value your model produced. Label the number. Do not pretend the ad platform calculated the margin.
Meta valueOffline events can use the Conversions API with action_source system_generated. Value optimization needs value and currency on the event. A predicted lifetime value is your number, sent as the value.
Clean roomsAds Data Hub, Amazon Marketing Cloud, Meta Advanced Analytics, and a LiveRamp or Snowflake clean room join ad exposure to your data without handing either side the raw rows.
IncrementalityGeo-lift, conversion lift, and a holdout are experiments. Meta publishes GeoLift. Robyn and Google Meridian are media-mix models. A platform-reported conversion is not a lift result.
MMM and MTAMix models use spend and outcomes over time. Multi-touch uses user paths. They answer different questions. Neither replaces a holdout.
WarehouseExport GA4 to BigQuery. Land ad platform tables with the official API or a loader such as Fivetran. Model them with dbt. Join on the order id, not on a platform total.
Reverse ETLSend hashed audiences back to Customer Match and custom audiences. Consent still applies. A suppressed customer should be in the exclusion list.
Cross-domainOne first-party measurement id across domains you own, plus a linker parameter. The cross-domain lab shows the toy version.
App and webFirebase for the app stream. SKAdNetwork and AdAttributionKit for iOS. An MMP such as AppsFlyer or Branch when the app store is the conversion. The app tracking lab is the webview case.
Closed loopLead, then opportunity, then revenue. Each stage is a named conversion. The revenue row goes back with the original click id or order id.
ObservabilityAlert when a tag stops, when event_id is missing, or when server volume diverges from the pixel. A data contract names the required parameters. The data quality and anomalies labs are the same idea for this site.

Salesforce offline row

A display sample for Google Ads offline import. This site does not upload it.

{
  "Google Click ID": "<gclid from the lead>",
  "Conversion Name": "Closed Won",
  "Conversion Time": "2026-10-10 15:04:00+0000",
  "Conversion Value": 1800,
  "Conversion Currency": "USD",
  "Order ID": "opp-440"
}

Conversion value adjustment

Use this when the closed value changes. The order id is the join.

{
  "Order ID": "opp-440",
  "Adjustment Time": "2026-10-12 09:00:00+0000",
  "Adjusted Value": 1400,
  "Currency": "USD",
  "Reason": "Restatement"
}

Cross-domain details are in the cross-domain lab. App events and a webview are in the app tracking lab. A server you call yourself is the server-side lab and the webhooks lab.

Campaign-driven personalization

The same campaign object can change the page. Message match uses utm_term and utm_content. A click id says which platform paid for the visit. A campaign name can pick a landing variant. Referrer and source name the social platform. Geo, weather, and hour are context. Device, new or returning, and first touch versus last touch are persistence choices. Account-based tools such as Demandbase, 6sense, or Clearbit add a company. This demo uses a labeled company instead of calling one.

CRM audiences and lifecycle stage change the call to action. A retargeting sequence should continue, not restart. A promo code in the ad should be the code on the page. Locale picks a landing. Cart or browse history continues the visit. An intent score can swap a soft button for a direct one. A converted visitor should not see the acquisition offer.

Measure the swap. Hold out a share of the campaign, or run the experiment the experiments lab describes, and attribute the experience back to the campaign name. A higher click rate on the variant is not lift until the holdout says so.

Implement it once. The page writes campaign_context. Google Tag Manager and Adobe Target read it. The lightweight client below is enough when you do not want a testing tool to own the headline. The segments lab, the source lab, the personas lab, and the weather lab are the live versions of those signals on this site.

Lightweight client

The page picks the variant. The tag manager measures it. This sample does not run here.

// Lightweight client. The page decides the variant. Tags only measure.
const params = new URLSearchParams(location.search)
const clickIds = ["gclid", "fbclid", "ttclid", "li_fat_id", "msclkid", "ScCid", "twclid", "epik", "rdt_cid"].filter((key) => params.get(key))
dataLayer.push({
  event: "campaign_context",
  campaign: {
    source: (params.get("utm_source") || "").toLowerCase(),
    medium: (params.get("utm_medium") || "").toLowerCase(),
    campaign: (params.get("utm_campaign") || "").toLowerCase(),
    content: (params.get("utm_content") || "").toLowerCase(),
    term: (params.get("utm_term") || "").toLowerCase(),
    click_ids: Object.fromEntries(clickIds.map((key) => [key, params.get(key)]))
  }
})
// Render the headline from those fields, then let the tag manager fire.

Landing context

Click ids on this landing

First touch is held in this tab only. Refresh clears it. Nothing is written to storage.

Dry-run landing

Default page, consent off

The campaign rule is ready, and it is withheld. This site treats personalization and measurement as the same choice.

Accept to preview the variant

Offer: Withheld

Consent withheld the variant

No campaign rule matched, so the page stays on the generic offer.

  • skip converted
  • skip promo
  • skip click
  • skip term
  • skip creative
  • skip retarget
  • skip company
  • skip lifecycle
  • skip source
  • skip weather
  • skip hour
  • skip device
  • skip returning
  • skip intent
  • skip locale

The preview stays in this tab. It does not call an ad platform, a firmographic vendor, or the weather service. Consent off keeps the default page. The rule that would have fired is still listed.

Official docs

Why these picks

Reading path transitions…

Questions this lab answers

What belongs in an ad measurement plan?

The business result, the conversion that proves it, and one event name for every platform. Value, currency, and a shared event id travel with that name.

How do a pixel and a server event stay one conversion?

Send the same event id from both. Meta also matches the event name. Google Ads and GA4 use the order id. The alignment table names the key for each platform.

How should campaign links be written?

Lowercase source, medium, and campaign. Hyphens instead of spaces. Medium cpc for paid search and paid-social for paid social. Click ids stay case-sensitive and are stored first-party.

What changes when consent is denied?

Ads tags do not fire, and the server payloads in the dry run are omitted. On this site, analytics also waits for Accept. Global Privacy Control forces that off.

Does this lab send events to ad platforms?

No. The builder, the click id detector, the tag fan-out, and the landing preview stay in the browser. Nothing is stored, and the page works with no database.

Related reading

  • Meta Conversions API explained

    Meta Conversions API explained: a server event beside the Pixel, SHA-256 email and phone, a shared event id, and a free dry run that sends nothing to Meta.

  • What are webhooks used for

    What are webhooks used for: a signed POST when something happens, how to verify the signature, and a live delivery log for events from this site. Free to try.

  • Consent Mode and Global Privacy

    Consent Mode and Global Privacy Control on this site: what is sent before Accept, what changes after, and how a GPC signal keeps measurement off.

  • Traffic source, referrer decoded

    Traffic source, referrer decoded: campaign parameters first, then the referrer host for search, social, another site, this site, or direct. Free to read.

  • Browser and server-side

    Browser and server-side collection of the same test event, from gtag and from a first-party endpoint, and what blockers drop. Free to send both.

  • Live audience segments

    Live audience segments from signals already in this browser, plus an anonymous count of consented visitors. Rules you can read, with no third-party profile.

  • Same page, five people

    Same page, five people, plus you. Each card names the signals and the rule that changed the hero, the offer, and the notes. Tweaks stay in this browser.

  • Weather and time of day

    Weather and time of day pick the hero, the theme, and a suggested read from a city-level forecast and the local hour. Free, and the Open-Meteo request is shown.

  • What a beacon actually sends

    The body of one page view, the gate it has to pass, and the record that comes back.