How to Track Affiliate Revenue in Google Analytics 4: Setup Guide With UTM and Event Tracking

How to Track Affiliate Revenue in Google Analytics 4: Setup Guide With UTM and Event Tracking

by | Sep 21, 2026 | Uncategorized | 0 comments

Every affiliate publisher hits the same wall. Your network dashboard says you earned $4,180 last month, GA4 says you earned $0, and nothing in either report tells you which article, keyword or traffic source actually produced the sale. That gap is the affiliate attribution blind spot, and it is the reason most bloggers scale the wrong pages.

This guide shows you exactly how to track affiliate revenue in Google Analytics (GA4), step by step: tagging outbound partner links, firing custom click events, passing a sub ID that survives the redirect, and streaming commission data back into your property so revenue sits next to the session that created it. There’s a good explainer over at partnerize.com.

Why Your Affiliate Dashboard and Google Analytics Never Match

Before touching a tag, understand what is actually breaking. GA4 is not “wrong”, it simply loses visibility the second a visitor leaves your domain.

Cause of the mismatch What happens Fix covered below
Cross-domain gap The merchant is a third-party domain, so your GA4 cookie stops at the click Sub ID bridge (Step 4)
Delayed conversions Cookie windows of 30 to 90 days mean the sale lands weeks after the session Commission import (Step 6)
Reversed and pending orders Networks show pending amounts that later get cancelled Status field + refund events
Ad blockers and consent refusals Clicks fire at the redirect layer but never reach GA4 Server-side or redirect logging
Different counting logic GA4 counts events, the network counts approved transactions Reconciliation table (Step 8)

Realistically you should target 85 to 95 percent match between GA4 and your network, not 100 percent. Anyone promising perfect parity is selling something.

google analytics dashboard laptop

The Three-Layer Framework

Affiliate tracking in GA4 only works when three layers talk to each other:

  1. Click layer: a custom event that records who clicked what, where, and on which page.
  2. Identity layer: a sub ID (also called clickref, sid, u1, afftrack) that carries your GA4 client ID and session ID into the network.
  3. Revenue layer: commission data pushed back into GA4 through the Measurement Protocol or joined in BigQuery.

Skip layer two and you will forever have clicks with no revenue. Skip layer three and you will forever have revenue with no source.

Step 1: Turn On Enhanced Measurement (And Know Its Limits)

GA4 already collects a click event for outbound links if enhanced measurement is enabled. An extended version exists for anyone curious.

  1. Go to Admin > Data streams and open your web stream.
  2. Click Enhanced measurement and enable Outbound clicks.
  3. Save.

You now get click events with the parameters link_url, link_domain, link_classes and outbound = true.

Why this is not enough:

  • It fires on every outbound link, including sources you cite and social profiles, so affiliate data is buried in noise.
  • You cannot tell whether the click came from a comparison table, a sidebar banner or an in-text mention.
  • If your links go through a cloaker such as yoursite.com/go/brand/, the click is internal and enhanced measurement ignores it completely.
  • No revenue is attached, ever.

Treat it as a baseline sanity check, then build a proper event on top.

google analytics dashboard laptop

Step 2: Mark Your Affiliate Links So They Are Machine-Readable

Consistency here saves hours later. Pick one convention and apply it site-wide:

<a href="https://www.merchant.com/product?aff=yourid"
   class="aff-link"
   data-aff-partner="merchant-name"
   data-aff-network="awin"
   data-aff-placement="comparison-table"
   rel="sponsored nofollow noopener"
   target="_blank">Check current price</a>

Three things matter:

  • A shared class (aff-link) so one trigger catches all links.
  • Data attributes for partner, network and placement. Placement is the parameter that will later tell you that your comparison tables convert four times better than your intro paragraphs.
  • rel=”sponsored” because Google requires it and because it doubles as a fallback selector.

If you use a link cloaker plugin, add the class to the plugin’s global link settings so every /go/ link inherits it automatically.

Step 3: Fire a Custom affiliate_click Event in Google Tag Manager

A generic click event is useless for analysis. Build a dedicated one.

3.1 Create the variables

In GTM, create three Data Layer or DOM Element / Custom JavaScript variables that read your attributes. The quickest method is an Auto-Event Variable of type Element Attribute:

Variable name Type Attribute
aff – partner Auto-Event Variable data-aff-partner
aff – network Auto-Event Variable data-aff-network
aff – placement Auto-Event Variable data-aff-placement

3.2 Create the trigger

Trigger type Click – Just Links, with “Wait for Tags” enabled (2000 ms) and the condition:

Click Classes  contains  aff-link

If you do not control the markup, use Click Element matches CSS selector with a[rel*="sponsored"], a[href*="/go/"].

3.3 Create the GA4 event tag

Event name: affiliate_click. Recommended parameters:

Parameter Value Why it matters
affiliate_partner {{aff – partner}} Compare merchants side by side
affiliate_network {{aff – network}} Match against network reports
affiliate_placement {{aff – placement}} Find your highest earning link positions
link_url {{Click URL}} Debugging and deep-link checks
page_location {{Page URL}} Article-level revenue attribution
aff_subid {{aff – subid}} The key that joins GA4 to your network

Publish, then verify in DebugView that the event fires once per click, not twice (a duplicate usually means both enhanced measurement and your custom tag are counted, which is fine as long as you report on affiliate_click only).

3.4 Register the custom dimensions

Parameters are invisible in reports until you declare them. Go to Admin > Custom definitions > Create custom dimension and register affiliate_partner, affiliate_network, affiliate_placement and aff_subid as Event-scoped dimensions. Data starts collecting from that moment forward, it is not retroactive, so do this first.

Finally, mark affiliate_click as a key event (the GA4 name for what used to be called a conversion) under Admin > Key events. This unlocks it in attribution reports.

Step 4: Pass a Sub ID So the Network Can Send Data Back

This is the step almost every tutorial skips, and it is the one that actually closes the loop. Nearly every network accepts a free-text tracking parameter that is echoed back in the transaction report.

Network Sub ID parameter
Awin clickref (plus clickref2 to clickref6)
Impact subId1, subId2, subId3
CJ Affiliate sid
ShareASale afftrack
Rakuten Advertising u1
Amazon Associates ascsubtag (SiteStripe tracking ID as fallback)
Digistore24 cid / tid
PartnerStack, Refersion, in-house programs Usually sub_id or ref, check the partner docs

Inject your GA4 identifiers into that parameter on click:

<script>
gtag('get', 'G-XXXXXXXXXX', 'client_id', function(clientId) {
  gtag('get', 'G-XXXXXXXXXX', 'session_id', function(sessionId) {
    var subid = clientId + '_' + sessionId;
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({ event: 'aff_subid_ready', aff_subid: subid });

    document.querySelectorAll('a.aff-link').forEach(function(link) {
      try {
        var u = new URL(link.href);
        u.searchParams.set('clickref', subid); // rename per network
        link.href = u.toString();
        link.setAttribute('data-aff-subid', subid);
      } catch (e) {}
    });
  });
});
</script>

Practical notes from real deployments:

  • Most networks cap the sub ID at 50 to 100 characters. A client ID plus session ID is around 30, so do not also append the full URL. Use a short page slug or a numeric post ID instead.
  • Avoid personal data. A client ID is a pseudonymous cookie value, an email address is not allowed.
  • Run the script after consent is granted if you operate under GDPR, and let unconsented users click a clean link.
  • If you use a cloaker, append the sub ID at the redirect level in PHP so it works even when JavaScript is blocked.
google analytics dashboard laptop

Step 5: Use UTM Tags the Right Way (Inbound, Not Outbound)

Here is where a lot of publishers hurt themselves: never put UTM parameters on your outbound affiliate links. UTMs are read by the destination site’s analytics, not yours, and merchants sometimes strip or misroute them. Use sub IDs for outbound, UTMs for inbound.

Tag every link that brings traffic to your site:

Traffic type utm_source utm_medium utm_campaign
Newsletter promo newsletter email 2026-08-vpn-roundup
Guest post or placed backlink partnersite.com referral guestpost-hosting-guide
Paid social facebook paid_social q3-review-retargeting
YouTube description youtube video unboxing-series

Rules that keep the data clean:

  • Lowercase everything. GA4 treats Email and email as two channels.
  • Stick to the standard medium values (email, referral, cpc, paid_social, affiliate) so GA4’s default channel grouping recognises them.
  • Never UTM-tag internal links. It resets the session and wipes the original source.
  • Keep a shared spreadsheet of your naming conventions. Future you will thank present you.

Step 6: Push Commission Data Back Into GA4

Now the payoff. Export your network transactions (most offer a CSV export or an API), find the sub ID column, and send each commission to GA4 with the Measurement Protocol.

Endpoint

POST https://www.google-analytics.com/mp/collect
     ?measurement_id=G-XXXXXXXXXX
     &api_secret=YOUR_API_SECRET

Create the API secret under Admin > Data streams > your stream > Measurement Protocol API secrets.

Payload

{
  "client_id": "1786543210.1755840000",
  "events": [
    {
      "name": "affiliate_commission",
      "params": {
        "session_id": "1755840000",
        "transaction_id": "AWIN-88231",
        "value": 42.50,
        "currency": "USD",
        "affiliate_network": "awin",
        "affiliate_partner": "merchant-name",
        "commission_status": "approved",
        "engagement_time_msec": 1
      }
    }
  ]
}

Split the client_id and session_id back out of the sub ID you stored, and you have revenue attached to the exact session, device and channel that produced it.

Three things to get right

  1. Event name. Using purchase makes the money appear automatically in Monetization reports, but it will pollute your ecommerce data if you also sell your own products. If you run a pure content site, purchase is convenient. Otherwise use affiliate_commission and build a custom metric.
  2. Timing. Events sent with a backdated timestamp_micros are only accepted within roughly 72 hours. Since commissions are confirmed weeks later, send them without a timestamp and rely on client_id and session_id for the join. Attribution reporting will be approximate, which is why serious operators also mirror everything into BigQuery.
  3. Reversals. When a network cancels a transaction, send a matching refund event with the same transaction_id, or re-send with commission_status: "declined" and filter it in your reports.

Free alternative: BigQuery

The GA4 to BigQuery export is free on standard properties. Load your network CSV into a table, join on the sub ID, and you get exact revenue by landing page, channel, device and campaign with none of the Measurement Protocol timing constraints. It is more work upfront and by far the most accurate route. This reference is the one worth keeping handy.

Done-for-you alternative

Tools such as wecantrack, AnyTrack or Affilimate handle the sub ID injection and the postback automatically for dozens of networks. Expect a monthly fee, but if you manage more than five programs the time saved usually justifies it.

Step 7: Build the Reports That Actually Change Decisions

Data with no report is just storage cost. Create these three explorations under Explore:

Report 1: Revenue per article

  • Rows: Landing page + query string
  • Values: affiliate_click count, commission value, sessions
  • Add a calculated column for EPC (earnings per click) and RPM (revenue per 1000 sessions)

Report 2: Placement performance

  • Rows: affiliate_placement
  • Values: clicks, click-through rate, commission value
  • Typical finding: comparison tables and above-the-fold buttons carry 60 to 80 percent of revenue while accounting for 20 percent of links

Report 3: Channel to commission path

  • Rows: Session default channel group, Session source / medium
  • Values: commission value, conversion rate
  • This is the report that tells you whether the backlinks and campaigns you are paying for return real money, not just sessions

The reconciliation table you should keep monthly

Metric Network GA4 Match rate
Clicks 12,430 11,180 90%
Transactions 184 171 93%
Commission $4,180 $3,905 93%

If a match rate drops sharply month over month, something broke in your tagging. Treat it as a monitoring metric.

google analytics dashboard laptop

Step 8: QA Checklist Before You Trust the Numbers

  1. Open DebugView and click three different affiliate links. Confirm affiliate_click fires once each with all parameters populated.
  2. Inspect the destination URL after the click and confirm the sub ID parameter is present and not truncated.
  3. Place one real test transaction, then look for your sub ID in the network report within 24 to 48 hours.
  4. Send a test Measurement Protocol event and validate it with the Event Builder / validation server before running a bulk import.
  5. Check that custom dimensions are registered and returning values rather than “(not set)”.
  6. Set data retention to 14 months under Admin > Data settings > Data retention.
  7. Test on mobile. Some cloaker plugins and consent banners behave differently on touch devices.

Common Mistakes That Silently Destroy Affiliate Data

  • Registering custom dimensions after collecting data. Nothing is backfilled, you lose that history permanently.
  • Firing the event on mousedown without “wait for tags”. Fast browsers navigate away before the hit is sent, and you undercount by 10 to 20 percent.
  • Sending revenue as a string. The value parameter must be a number. "42.50" with quotes is silently dropped.
  • Forgetting currency. Without currency, GA4 discards the value on purchase-type events.
  • Tagging internal links with UTMs. Every click restarts the session attribution and your organic traffic magically becomes “email”.
  • Ignoring consent mode. If you operate in the EU, run Consent Mode v2 so modelled conversions fill part of the gap for users who decline cookies.

Putting It Together

Once revenue lives inside GA4 next to your acquisition data, the questions you can finally answer change completely: which article earns the most per thousand visitors, whether organic or referral traffic converts better for a given merchant, and which link placements deserve to be replicated across the site.

That last point matters most for growth. When you can see the exact commission value produced by each traffic source, investing in the pages and the backlinks that feed your highest EPC articles stops being guesswork. At DigBacklink we see the same pattern across publishers: the sites that scale are the ones that pointed authority at the pages their analytics proved were profitable, not the ones they assumed were.

FAQ

Can you track affiliate revenue in Google Analytics for free?

Yes. GA4, Google Tag Manager, the Measurement Protocol and the BigQuery export are all free at standard volumes. The only cost is your time building the sub ID bridge and importing network transactions. Paid tools automate the same workflow.

Does GA4 track affiliate links automatically?

Partly. Enhanced measurement records outbound clicks, but it cannot distinguish affiliate links from ordinary external links, it misses cloaked links on your own domain, and it never captures revenue. A custom affiliate_click event is required.

Should I use the purchase event or a custom event for commissions?

Use purchase if affiliate income is your only revenue stream and you want the data to appear in Monetization reports with no extra setup. Use a custom event such as affiliate_commission if you also run ecommerce, so the two revenue types stay separate.

Why do my GA4 clicks not match my affiliate network clicks?

Ad blockers, consent refusals, bot filtering differences and users who open links in new tabs before the tag fires all create variance. A 5 to 15 percent gap is normal. Anything larger points to a trigger timing issue or a missing tag on part of your site.

How do I track affiliate revenue when the sale happens weeks later?

Store the sub ID (client ID plus session ID) at click time, then send the commission back through the Measurement Protocol or join it in BigQuery once the network confirms it. The sub ID is the only durable link between the two systems because the third-party cookie is not.

What is the best way to keep track of multiple affiliate programs?

Standardise the sub ID format across every network, use the same event schema for all of them, and add affiliate_network as a dimension. One GA4 report then replaces logging into eight dashboards, and you can compare EPC across programs directly.

Is Google Analytics being replaced?

GA4 is the current version and Universal Analytics data is long gone. Many affiliates run GA4 alongside a privacy-focused tool such as Plausible or Matomo for cookieless traffic counts, but GA4 remains the free option with the deepest attribution and BigQuery integration.