Introduction — Why reconciliation matters
Affiliate networks report payouts that rarely match analytics reports out of the box. Differences arise from attribution windows, deduplication, timezone mismatches, currency rounding, refunds, and missing click identifiers. This playbook gives a pragmatic, technical approach to reconciling network payouts with Google Analytics 4 (GA4), server-to-server postbacks, and robust UTM practices so you can reduce revenue leakage and create repeatable reconciliation workflows.
What you’ll get:
- Key mapping concepts between network data and GA4 events
- Server postback best practices and deduplication strategies
- UTM naming rules and how to preserve attribution across redirects
- A reconciliation checklist and automation recommendations
Mapping network payouts to GA4 & postbacks — technical essentials
Start by identifying the authoritative keys you can use to join network records to your analytics and backend data. Common keys include:
- transaction_id / order_id — the cleanest join key when the network sends it back in postbacks.
- click_id / sub_id — network-specific click identifiers (e.g., network click ID or platform_subid) captured at click time and persisted to the user session / cookies and your order DB.
- timestamp — event time (UTC recommended) used for window alignment.
- payout_amount and currency — networks report payout; GA4 captures revenue. Reconcile using currency conversion and rounding rules.
Server postback & dedup strategy
Implement server-to-server (S2S) postbacks that include the click identifier and an authoritative order_id. Key recommendations:
- Send a unique
transaction_idwith the postback and include the original click_id (if available). - Use a deduplication key (e.g.,
transaction_id|network_id) and reject duplicate postbacks at ingestion. - Keep postbacks idempotent: store receipts and return deterministic success responses so retries don’t create duplicates on the network side.
- Record both click time and conversion time, and normalize to UTC to avoid timezone skew.
GA4 export & join logic
Export GA4 purchase events to BigQuery (or your data warehouse) and join using the best available keys. Recommended join hierarchy when multiple keys exist:
- Exact match on
transaction_id(order id) - If absent, match on
click_id(network sub_id) + conversion time within the expected attribution window - As a last resort, match on
user_pseudo_idor hashed identifiers with time proximity rules
Include tolerance rules in your SQL joins for small differences in amounts (e.g., tax or shipping) and allow configurable time windows per network (7, 14, 30 days depending on the program).
UTM Best Practices, tagging standards and reconciliation checklist
UTM tagging standards
Consistent UTM tags are the foundation for meaningful attribution. Follow these rules:
- Always capture & persist click identifiers (network click_id, subid) in addition to UTMs. UTMs are human-readable; click IDs are deterministic.
- Lowercase & use dashes — convert all UTM values to lowercase and standardize separators (recommend dash
-for readability). - Keep utm_source concise and network-specific (e.g.,
cj,impact,awin,partnername). - Use utm_medium=affiliate (or merchant-defined consistent medium) so filters are straightforward.
- Use utm_campaign for program or offer and utm_content for creative or placement id. Store the raw UTM values in order metadata for reconciliation.
- Preserve UTMs across redirects — ensure all redirect landing pages forward the click_id and UTM parameters (or set a cookie/session variable) before any cross-domain navigation.
Recommended UTM example
https://example.com/landing?utm_source=awin&utm_medium=affiliate&utm_campaign=summer-sale-2025&utm_content=banner-728x90&click_id={CLICKID}
Reconciliation checklist
- Enable GA4 BigQuery export or server-side analytics export.
- Log raw postbacks from networks into a staging table with full payload and ingestion timestamp.
- Normalize currencies and apply identical rounding logic to both sides.
- Join network payouts to warehouse GA4 purchases using the join hierarchy (transaction_id → click_id → time-based match).
- Reconcile counts and amounts by day/program and flag deltas beyond tolerance thresholds (e.g., >2% or >$X).
- Investigate common delta causes: missing postbacks, blocked cookies, multi-touch attribution differences, refunds, or mismatched currencies.
- Automate daily reconciliation report delivery and preserve an audit log of matches/unmatched items.
Sample SQL snippet (pseudocode)
-- Join by transaction_id first, then fallback to click_id within 24 hours WITH ga4_orders AS ( SELECT transaction_id, click_id, event_timestamp, revenue FROM ga4.ecommerce_orders ), network_payouts AS ( SELECT network_txn, network_click_id, payout_ts, payout_amount FROM staging.network_postbacks ) SELECT n.*, g.transaction_id, g.revenue FROM network_payouts n LEFT JOIN ga4_orders g ON n.network_txn = g.transaction_id UNION ALL SELECT n.*, g.transaction_id, g.revenue FROM network_payouts n LEFT JOIN ga4_orders g ON n.network_click_id = g.click_id AND ABS(TIMESTAMP_DIFF(n.payout_ts, g.event_timestamp, HOUR)) <= 24;
Closing notes
Reconciliation is both technical and operational. Create a cross-functional runbook that documents naming conventions, expected windows per network, refund policies, and escalation paths. Start with a daily automated reconciliation that surfaces top deltas, then iterate on instrumentation: capture click_ids reliably, implement server postbacks, and index transaction_ids across systems.
