This is a last-click (UTM-based) attribution system. We prioritize data sources that capture the customer’s most recent measurable marketing touch before purchase.
The hierarchy below ranks primary traffic sources only. MTA touches (
mta_first_touch, mta_last_touch), zero-party survey responses, and discount-code rows can appear in the signals table as supporting context, but they do not participate in the primary traffic winner ranking.Primary Attribution Source Hierarchy
The current customer-facing signals table keeps these traffic sources in preferred order:| Preferred order | Evidence source | Description |
|---|---|---|
| 1 | Shopify Custom Attributes Override | Order-level attribution set via Shopify customAttributes (Checkout / Admin GraphQL API). Treated as an explicit override (shopify_custom_attribute_override). |
| 2 | Shopify Landing Site | UTM parameters extracted from the order’s landing page URL and related Shopify order URL tags (shopify_landing_site). |
| 3 | Shopify Order Notes (Legacy) | UTM data written to order notes / note attributes by tracking tools such as Elevar or Blotout (shopify_note). |
| 4 | Website Event Tracking | First-party website events tied back to the order (website_event_tracking_purchase). |
| 5 | Google Analytics Transaction | GA4 or retained historical UA transaction data tied back to the order (google_analytics_transaction). |
| 6 | Shopify Order Referring Site UTMs | UTM parameters parsed from the order’s referring_site URL (shopify_order_referring_site_utms). |
Final source ranking is deterministic and tenant-scoped at the order level. In
fct_order_attribution_signals, the numeric field sm_utm_final_source_priority is an ordering signal, not a reusable source code system. 1 means “winner for this order,” and you may see sparse values such as 1, 3, 4, 5, 7, and 8 instead of a compact 1..6 sequence.Universal Analytics (UA) has been sunset by Google. If your organization already exported and retained historical UA data, treat it as historical-only and prefer GA4 for ongoing tracking.
Use fct_order_attribution_signals
When you need to understand why a specific order resolved the way it did or build custom order-level attribution logic, use fct_order_attribution_signals. It exposes:
- every evidence row SourceMedium kept for the order
- the per-order traffic winner via
sm_utm_final_source_priority = 1 - raw captured fields next to the canonicalized
sm_utm_*fields - zero-party and discount-code rows that provide supporting context
Google Analytics Transaction Tie Rules
Google Analytics transaction records are considered tie-eligible for order matching when the transaction ID can be safely parsed into an order-like numeric key using the following logic:transaction_idmatches^#[0-9]{4,}$(for example#6589), ortransaction_idhas a trailing numeric suffix with length>= 5.
Website Event Tracking Details
For website event tracking sources, the system uses qualifying events in a 0..90 day window relative to the order. When multiple events exist, they’re ranked by:- Days between event and order (closer to order = higher priority)
- Event timestamp (earlier
event_local_datetimewins ties) - Event ID and source system (as final tie-breakers)
referral.
Shopify Custom Attributes Override
If your Shopify order has attribution data written tocustomAttributes (Shopify Admin GraphQL API / Checkout attributes), SourceMedium treats it as an explicit override and prioritizes it ahead of the default Shopify attribution sources surfaced in the signals table (landing site, order notes, website events, and Google Analytics transactions).
This is the recommended mechanism for:
- Backfilling attribution onto historical orders
- Capturing UTMs at checkout when cookie-based tracking is unreliable (ad blockers, ITP, cross-domain, etc.)
Supported keys (allowlist)
Only a specific set of keys are extracted fromcustomAttributes to prevent accidental capture of non-attribution data.
Keys are normalized (case + delimiter + snake/camel agnostic) before matching:
utm_source,utmSource,UTM_SOURCE,utm-source→ treated as the same keysm_utmParams,smUtmParams→ treated as the same keyGE_utmParams,ge_utm_params→ treated as the same key
| Key | Purpose |
|---|---|
sm_utm_source, sm_utm_medium, sm_utm_campaign, sm_utm_content, sm_utm_term, sm_utm_id | SourceMedium override keys (recommended to avoid collisions with other apps) |
utm_source, utm_medium, utm_campaign, utm_content, utm_term, utm_id | Standard UTM keys |
sm_utmParams, utmParams, GE_utmParams | Aggregate UTM query-string fields (parsed into individual UTM keys) |
sm_referrer, referrer | Referring URL |
Conflict resolution (deterministic)
If yourcustomAttributes data is messy (duplicate keys, multiple sources provided), SourceMedium applies a deterministic waterfall to resolve each final field.
Field-level precedence
For each UTM field, the first non-empty value wins (highest → lowest):- Direct SM override key (
sm_utm_*) - Direct standard UTM key (
utm_*) - Parsed from
sm_utmParams(query string) - Parsed from
utmParams(query string) - Parsed from
GE_utmParams(query string) utm_sourceonly: click ID inference (scclid→irclickid→msclkid→ttclid→fbclid→gclid)
referrer is resolved similarly: sm_referrer → referrer.
Duplicate keys (same tier)
If the same normalized key appears multiple times at the same tier (for example bothutm_source and UTM_SOURCE, or repeated utm_source entries), SourceMedium de-dupes deterministically using MAX() (lexicographically largest value after decoding/cleaning).
To avoid surprises, only set each key once.
Click IDs are processed as a fallback (see below), but the raw click ID values are not stored as attribution fields.
Aggregate UTM fields
If you sendsm_utmParams, utmParams, or GE_utmParams as a URL query string (e.g., utm_source=google&utm_medium=cpc), SourceMedium parses it and extracts the individual UTM keys. Parsing is snake/camel agnostic (both utm_source= and utmSource= are supported) and URL-decoding is applied.
URL Handling
URL encoding insm_utmParams, utmParams, and GE_utmParams values is fully decoded:
- Percent encoding:
%XXpatterns (e.g.,%20→ space,%26→&) - Form-style encoding:
+characters are decoded as spaces (common in checkout apps)
Click ID to Channel Inference
When only a click ID is present (no explicitutm_source), the system infers a fallback utm_source value:
| Priority (highest first) | Click ID | Inferred utm_source | Platform |
|---|---|---|---|
| 1 | scclid | snapchat | Snapchat Ads |
| 2 | irclickid | impact | Impact (Affiliate) |
| 3 | msclkid | microsoft | Microsoft/Bing Ads |
| 4 | ttclid | tiktok | TikTok Ads |
| 5 | fbclid | meta | Meta (Facebook/Instagram) |
| 6 | gclid | Google Ads |
- Direct
customAttributesclick ID keys (e.g.,scclid,gclid) - Click IDs embedded inside
utmParams - Click IDs embedded inside
GE_utmParams
Click IDs are fallback only. If an explicit
utm_source exists, it takes precedence over any click ID inference.Checkout UI Extensions (recommended)
Use Shopify Checkout UI Extensions to write attribution to checkout attributes (which become ordercustomAttributes).
Checkout UI extensions are sandboxed and can’t access the browser DOM (e.g.,
document.cookie, localStorage, or window.location). Capture UTMs on the storefront and write them into cart/checkout attributes before checkout starts.Custom attributes may be used by other apps. To reduce collisions, prefer
sm_utm_* / sm_utmParams keys for explicit overrides (matching is normalized, but canonical keys reduce ambiguity).Shopify Order Notes
Order notes are a key attribution source written by server-side tracking tools like Elevar and Blotout. These tools capture UTMs at checkout and write them to Shopify order notes / note attributes.If you have control over implementation, prefer customAttributes override instead of writing attribution into notes. Notes are shared and can be overwritten by apps; custom attributes are clearer and explicitly prioritized.
Note Attributes (Legacy)
The system supports extracting attribution from legacynote_attributes patterns, including:
- Standard UTM keys like
utm_source,utm_medium,utm_campaign,utm_content,utm_term,utm_id - Tool-specific payloads (e.g.,
_elevar_visitor_info) when they contain nested UTM data
UTM Field Collapsing
After the primary source is determined, the system “collapses” supplementary UTM fields from lower-priority sources. Example: Ifshopify_custom_attribute_override provides utm_source=google but no utm_campaign, and shopify_landing_site has utm_campaign=summer_sale, the final attribution can combine:
utm_source=google(fromshopify_custom_attribute_override)utm_campaign=summer_sale(fromshopify_landing_site)
utm_source grouped channel is the same across sources—we don’t mix data from different channels.
Implementation Notes (Advanced)
- For Shopify order notes, if note-level
utm_sourceis missing, notechannelmay be used as a fallback source value. - Final
sm_utm_*fields can be completed by downstream override logic when hierarchy output is null or direct/non-actionable.
Related Resources
Attribution in SourceMedium
Overview of last-click vs. multi-touch attribution
Improve Last-Click Attribution
Tips for improving UTM tracking quality
Data Enrichment
How we enrich and standardize your data
Attribution Health
Check and improve your attribution data quality

