Skip to content

Google Ads & Meta

An ad platform integration pulls spend from the platform and joins it to the sessions the tracker already attributed to that platform. The result is cost per session, cost per conversion and ROAS that reconcile to your invoice, in one report across platforms.

Google Ads and Meta Ads are available. LinkedIn Ads and TikTok Ads are built behind a waiting list.

  1. On Property > Integrations, open the platform tile and click Connect. You authorise SnipForm at the platform (OAuth) and return.

  2. Choose the ad account. SnipForm fetches the accounts your login can see and shows a picker. For Google Ads, accounts under a manager (MCC) are listed with their manager so the right login-customer-id is used automatically; there is nothing to configure.

  3. First sync. Selecting the account queues a sync that backfills the last 90 days of spend. The drawer polls until it lands, then shows the last 7 days of spend and a link to the Ads page.

After that, spend syncs on a schedule. Every sync re-pulls the trailing 14 days because platforms restate recent spend (invalid-click credits, late attribution); rows are upserted, so restatements overwrite in place. Sync now on the tile queues an immediate pull.

Change account keeps the authorisation, wipes the account-scoped data and re-shows the picker. Disconnect revokes the grant, deletes the spend data and clears that platform’s costs off your sessions; reconnecting starts from scratch.

One row per campaign per day, in the ad account’s currency: spend, impressions, clicks. Each day is also converted to USD at that day’s rate so platforms billing in different currencies can be compared. Days are the ad account’s timezone days; a reporting window in UTC can straddle up to a day of spend at its edges.

Each campaign-day’s spend is split equally across the sessions attributed to that campaign on that day and stamped onto them as cost_usd (and the platform’s cost_source). Summing session cost for a campaign-day gives back the invoice amount; there is no pooling across days or sites, and a day with no attributed sessions keeps its spend visible as unallocated rather than smearing it elsewhere.

A session is attributed to a platform when the tracker classified its channel as that platform’s paid traffic (Channels). Attribution to a campaign needs a key both sides share:

MethodHow
Click idGoogle auto-tags every ad click with gclid (or gbraid / wbraid); Meta appends fbclid. Where the platform exposes click-level reporting, SnipForm resolves the click id to its campaign and writes ad_campaign_id onto the session once. Zero setup
UTM campaign idWhere click resolution is not available, the session’s utm_campaign is matched to the platform’s numeric campaign id. That only works if the URL carries the real id, which is what tracking templates are for

Why campaigns can show spend but no sessions

Section titled “Why campaigns can show spend but no sessions”

Spend comes from the platform and carries its campaign id (21234567890). Sessions come from your site and normally carry only utm_campaign, which is free text you typed (“spring-promo”), or nothing at all when auto-tagging added a click id instead of UTMs. Nothing in an ad click carries the link between the two names. A click id proves the visit came from the platform (so platform totals are exact) but does not name the campaign.

SnipForm does not guess by fuzzy-matching names: a guess would fail silently and unevenly, showing zero for some campaigns, which reads as “no traffic” rather than “could not be matched”. An absent column is honest; a wrong number is not.

One setting in the ad account puts the real campaign id into every landing URL, giving both sides the same key.

Account level, so every campaign inherits it: Settings > Account settings > Tracking.

{lpurl}?utm_source=google&utm_medium=cpc&utm_campaign={campaignid}

{lpurl} is your existing final URL; {campaignid} is substituted at click time. Final URLs stay as they are.

Then: click one of your own live ads, open that session in Sessions and confirm the campaign id landed on it. From the next spend sync, campaign rows fill in. This applies to clicks after you save it; historical sessions keep what they arrived with. Platform-level totals never depended on this.

Pick one of the property’s active conversions on the tile as the platform’s ROAS conversion. From then on:

  • Conversions, CPA and revenue on the Ads page count sessions attributed to the platform that completed that conversion.
  • ROAS = conversion value in USD divided by spend in USD.

ROAS is only ever a real number. With no linked conversion the column says it needs one. A conversion whose value has no currency (a unit count) gives no ROAS. If the conversion’s currency and the ad account’s currency differ, the row is flagged currency_mismatch so you know the comparison went through USD.

The linked conversion is locked while conversion sending is enabled.

Google Ads can optimise Smart Bidding on your first-party conversions without pixels or cookies. SnipForm uploads click conversions for sessions that completed the linked conversion and carried a gclid, gbraid or wbraid. Sessions without a Google click id (organic conversions) are skipped by design.

Requirements, in order: an ad account selected, a linked conversion, and the conversion-upload scope granted (reconnect if the tile asks for it).

  1. In Google Ads open Goals > Conversions and create a new conversion action.

  2. Choose Import, then Other data sources or CRMs, then Track conversions from clicks.

  3. Name it (for example “SnipForm Conversions”), set the click-through conversion window to 90 days so the backfill lands in full, and save. Set it as Primary when you want it to drive bidding.

  4. Open the new action and copy its numeric id (the ctId value in the page URL). Paste it into the tile, tick the consent attestation, and enable.

Enabling immediately uploads the last 90 days of recorded conversions, then keeps uploading. New conversions take a fast path: a managed automation named “Google Ads conversion send” is registered on the linked conversion’s final step, and completions upload within about a minute of being assessed. You can see its run log but not edit it.

Disabling keeps the action id and attestation so re-enabling is one click. Meta does not support conversion sending here yet.

Spend that does not come from a connected platform (an agency retainer, a sponsorship, an influencer fee, an offline campaign) can be entered on the Ads page:

  • Label, amount and currency.
  • A date range. The end date may be left open for an ongoing cost.
  • A session query in the same query language the rest of SnipForm uses, which decides which sessions share the cost.

A fixed entry splits its total equally across every matched session. Open entries are re-applied as new sessions arrive, so each session’s share dilutes over time. A session carries exactly one cost: if two entries’ queries match the same session, the second never overwrites the first; the overlap is counted and the entry is flagged so you can fix the queries.

Manual entries appear on sessions with cost_source: manual and their label as cost_label.

Property > Ads shows, for any period:

SectionContent
Summary per platformSpend, impressions, clicks, CPC, attributed sessions, and with a linked conversion: conversions, revenue, CPA, ROAS. Totals across platforms
Spend trendOne line per platform in its own currency. The line stops at the last day the platform has reported; a missing trailing day means “not reported yet”, not “spent nothing”
CampaignsPer-campaign spend, sessions, conversions and ROAS, populated as campaign attribution resolves
Manual costsThe entries above, with their current per-session share and any overlap warnings

The same numbers feed weekly reports, the cost_usd metric in Data Views, and the ad_performance, ad_spend and ads_doctor MCP tools. ads_doctor diagnoses a connection end to end, including Google’s raw per-account responses, when a picker comes back empty or a sync errors.