Attribution
Pruuv links every conversion event to the ad that drove it. That linkage powers cost-per-lead reporting, AI agent recommendations, and conversion sending back to Meta, Google, and TikTok.
Attribution works in three tiers — each progressively more robust. Most clients start at Tier 1 and upgrade as their setup matures.
The three attribution tiers
Set utm_content to the platform's ad ID macro in your URL templates. Pruuv joins funnel events to ad performance data on that field. Fast to set up; breaks if the URL template is misconfigured.
If your URL structure doesn't use utm_content for the ad ID — or uses a compound value — configure a custom mapping per connection: which UTM param to read, and an optional regex to extract the ad ID from it.
Pruuv scans your connected ad accounts, assigns every ad a pruuv_aid, and generates URL templates with that ID baked in. The Pruuv Pixel captures it on landing. No platform macro dependency. Works even if platform creative IDs are inconsistent.
Tier 1 — UTM content matching
The join is: funnel_events.utm_content = ad_performance_cache.ad_id. For this to work, your ad URL templates must include the platform's ad ID macro in theutm_content parameter.
URL template setup
| Platform | URL template snippet | Notes |
|---|---|---|
| Google Ads | utm_content={creative}&utm_term={keyword} | Add to the account-level Tracking Template. {creative} = ad ID; {keyword} = matched keyword (see Google nuance below). |
| Meta Ads | utm_content={{ad.id}} | Dynamic URL parameter. Set in the ad's Website URL field or campaign-level URL parameters. |
| TikTok Ads | utm_content=__AID__ | TikTok macro. Set in the ad's Landing Page URL field. |
Google Ads — search term nuance
Google Search campaigns have a dimension below the ad: the search term that triggered the ad. The same responsive search ad (RSA) can show for hundreds of different queries depending on your match type settings. Pruuv captures this via two ValueTrack parameters:
| Parameter | What it captures | Match type behaviour |
|---|---|---|
| {creative} | The ad's unique ID — used for the spend attribution join | Same ad ID regardless of which search term triggered it |
| {keyword} | The keyword from your keyword list that matched the query | For broad match: your keyword, not the user's actual query. For exact match: identical. |
| {matchtype} | Match type: b (broad), p (phrase), e (exact) | Useful for segmenting performance by match type in reporting |
| {network} | Traffic source: g (Google search), s (search partners), d (display) | Helps filter out partner traffic that converts differently |
Recommended Google tracking template:
{lpurl}?utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_content={creative}&utm_term={keyword}&utm_matchtype={matchtype}This gives Pruuv the ad ID (for spend join), the matched keyword, and the match type — enough to power keyword-level performance breakdowns in the Data tab alongside conversion data.
{keyword} captures your keyword — not the actual search query the user typed. To see actual search queries alongside conversions, the Pruuv AI agent cross-references the Google Ads search term report (available in the agent context) with your funnel data. This is surfaced in recommendations when broad match keywords are driving low-quality or off-topic traffic.{creative}returns a creative ID that does not exactly match the ad ID returned by the Google Ads API. If you see a high unmatched rate despite correct template setup, this is the likely cause. Pruuv native attribution (Tier 3) eliminates this by using a Pruuv-owned ID that does not depend on the platform's creative ID format.Attribution match rate
In the client's Data tab, the Attribution section shows:
- —Matched events — funnel events where utm_content matched an ad in the performance cache
- —Unmatched (have content) — utm_content was present but no ad match was found. Usually means the URL template macro is wrong, or the ad is not yet synced.
- —No content — utm_content was empty. Organic traffic, email, or paid traffic without the macro configured.
Tier 2 — UTM pattern config Coming soon
If your clients have non-standard URL structures — e.g. the ad ID is embedded in utm_campaign, or utm_content contains a compound value like brand_12345 — you can configure a custom attribution mapping per connection.
Config options
| Setting | Description | Example |
|---|---|---|
| Source parameter | Which UTM param holds the ad ID | utm_campaign instead of utm_content |
| Extraction pattern | Optional regex with a named group to extract the ID from a compound value | (?<ad_id>[0-9]+) extracts 12345 from brand_12345 |
This config is stored per connection and applied automatically in attribution queries. The Connections page will show a live preview of matches against your last 7 days of events.
Tier 3 — Pruuv native attribution
Pruuv native attribution removes all dependency on platform macro configuration. Instead of relying on the platform to inject an ad ID into the URL, Pruuv builds a first-party ID layer it fully controls.
How it works
- Ad scan. Pruuv scans your connected ad account (daily, or on demand from the Connections page) and catalogues all active and paused ads. Each ad is assigned a
pruuv_aid— a UUID that Pruuv owns and controls. - URL template generation. Pruuv generates a URL template per ad with
pruuv_aidbaked in as a static query parameter. You copy this into the platform once (or download a CSV for bulk upload). - Pixel capture. The Pruuv Pixel reads
pruuv_aidfrom the URL on page load and stores it in a first-party cookie for 90 days. On conversion,pruuv_aidis included in the webhook payload. - Attribution match. Pruuv joins
funnel_events.pruuv_aidto its internal ad catalogue — a direct, exact match with no platform API ambiguity.
Click ID capture
In addition to UTM attribution, the Pruuv Pixel captures platform click IDs from the URL. These are required for conversion sending (sending matched conversions back to ad platforms) and provide a secondary attribution signal.
| Platform | Click ID parameter | Cookie | Used for |
|---|---|---|---|
| Google Ads | gclid | _pruuv_session | Conversion Upload API. Primary Google match signal. |
| Google Ads | wbraid | _pruuv_session | Web-to-app campaigns (privacy-preserving). |
| Google Ads | gbraid | _pruuv_session | App-to-web campaigns (privacy-preserving). |
| Meta Ads | fbclid → _fbc | _fbc | Meta CAPI matching. Required alongside _fbp. |
| Meta Ads | (browser ID) | _fbp | Browser-level Meta matching. Generated on first visit. |
| TikTok Ads | ttclid | _pruuv_session | TikTok Events API matching. |
| Microsoft Ads | msclkid | _pruuv_session | Bing/Microsoft Ads conversion upload. |
First touch vs last touch
Pruuv stores both first-touch and last-touch attribution:
| Model | Cookie | Behaviour |
|---|---|---|
| First touch | _pruuv_first_touch | Written once on the visitor's first tracked visit. Never overwritten. Captures the campaign that originally introduced the lead. |
| Last touch | _pruuv_session | Updated on each visit where a click ID or UTM is present. Reflects the most recent campaign before conversion. |
Pruuv uses last-touch by default for conversion sending — this aligns with the attribution models used by Meta, Google, and TikTok for their own reporting. First-touch data is stored and available for AI agent context and custom reporting.
identify() method lets you associate a known identity (email, phone) with a visitor profile before they convert. This enables cross-device attribution: if the same person clicks an ad on mobile and converts on desktop, Pruuv can merge their sessions. See the Pixel SDK docs for details.Attribution window
All cookies set by the Pruuv Pixel have a 90-day expiry. A visitor who clicks an ad and converts more than 90 days later will not have a click ID available, but their first-touch UTM data will still be present if it was captured within the window. The 90-day window aligns with the maximum attribution window supported by Meta and Google.