Cookie Stuffing: How It Hijacks Affiliate Attribution
Cookie stuffing sets an affiliate cookie with no click at all. How the mechanism works, and how to detect it in your own logs.
Cookie stuffing works because setting an affiliate cookie takes an HTTP request, and an HTTP request takes nothing more than an image tag. A click is how the request is supposed to be triggered. Nothing in the protocol requires one.
The usual lists of cookie stuffing techniques (hidden iframes, pixels, stylesheets, pop-unders, redirect chains, browser extensions) describe one mechanism wearing six different pieces of markup. Once you see it that way, it becomes clear what to log, what to query, and what to change about how your program joins a click to a conversion.
What Is Cookie Stuffing?
Cookie stuffing is a form of affiliate fraud in which a visitor's browser receives an affiliate tracking cookie without the visitor ever clicking that affiliate's link. If the visitor later buys from the merchant, the affiliate is credited with the sale and paid commission for a referral it never made.
It is also called cookie dropping. The stuffed cookie usually overwrites whatever affiliate cookie was there before, because most programs credit the last partner to touch the browser. So the fraud takes commission from you and, often, from a legitimate partner who did earn it.
Later in this article, detection relies on a browser fingerprint: an identifier computed from the browser's own characteristics rather than stored in it. That distinction matters, because the whole attack is about who gets to write what into the visitor's browser.
How Cookie Stuffing Actually Works
Affiliate cookie stuffing is easiest to understand by walking through the legitimate flow first and finding the step that never checks anything.
The legitimate flow
A partner publishes a tracking link, for example https://example-shop.com/track?aff_id=PARTNER123. When a reader clicks it:
The browser sends
GET /track?aff_id=PARTNER123to your tracking endpoint.The endpoint responds
302 Found, redirecting to your storefront.The same response carries
Set-Cookie: aff=PARTNER123, typically valid for 30 days.When the browser later reaches your order confirmation page, your tracking reads
affand credits PARTNER123.
The step that assumes the click
Steps 2 and 3 run on every request to /track. The endpoint has no concept of a click. It sees a GET request with a partner ID and answers it, whatever caused the browser to send it.
So any markup that makes a browser request that URL is a complete attack. An <img> with the tracking URL as its src. A 1×1 iframe. A stylesheet <link>. A pop-under window. A script that sets window.location on page load, or a lookalike domain that 302s visitors through the tracking link on their way to your real site. A browser extension that fires the request at checkout. These are interchangeable delivery vehicles for one payload, and the fraudster picks whichever the target program polices least.
Volume makes it cheap. A stuffing page loaded by automated traffic or bought pop-under inventory drops cookies into thousands of browsers a day, and only needs a small fraction of them to buy something within the cookie window.
A cookie stuffing example
The payload fits in three lines. This is a minimal, fictional illustration of the hidden-image variant:
<!-- On a page the partner controls, unrelated to your products. Nobody clicks anything. -->
<!-- Loading the page makes the browser request the tracking URL as if it were an image. -->
<img src="https://example-shop.com/track?aff_id=PARTNER123" width="1" height="1" style="display:none" alt="">What reaches your server is an ordinary tracking hit. The browser stores the cookie from the redirect response, then fails to decode your storefront HTML as an image. That failure is invisible and irrelevant: the cookie is already set.
GET /track?aff_id=PARTNER123 HTTP/1.1
Host: example-shop.com
Referer: https://unrelated-blog.example/
Sec-Fetch-Dest: image
HTTP/1.1 302 Found
Location: https://example-shop.com/?utm_source=affiliate
Set-Cookie: aff=PARTNER123; Max-Age=2592000; Path=/; Secure; SameSite=NoneWhere the request gives itself away
Look at that request again. The Referer names a page that is not one of the partner's declared placements, and Sec-Fetch-Dest: image says the browser was loading an image, not navigating. A real click on a link arrives as a top-level navigation (Sec-Fetch-Mode: navigate, Sec-Fetch-Dest: document), and current versions of Chrome, Firefox, Edge and Safari add Sec-Fetch-User: ?1 when the navigation came from a user gesture.
Fraudsters know the referrer is visible, which is why they hide it. A 2015 UC San Diego measurement study crawled more than 475,000 domains and collected around 12,000 stuffed cookies. Redirects delivered over 91% of them, and 84% were fetched through at least one intermediate domain, so that the affiliate program saw only the last hop in the Referer header. The study is a decade old, and the same research found stuffing less common than industry reports suggested. The mechanism it describes has not changed.
Why This Is an Attribution Problem, Not an Affiliate Problem
The tracking endpoint cannot tell a click from a tag because of what it is joining on. Attribution in most programs is a join between a conversion and a cookie, and a cookie is written by whoever can cause the request. That means the party being paid controls the evidence that it earned the payment.
That is the point covered at category level in the wider affiliate fraud picture, and cookie stuffing is its cleanest demonstration. Every other control is downstream of that join.
Partner vetting judges the partner at admission. It says nothing about any individual cookie written months later, and a partner can pass vetting with a clean content site while running stuffing pages on other domains. Payout audits examine conversions after they have been credited, using the same cookie that was forged. Both are useful, and both are working from the fraudster's own paperwork.
This is why programs that do both still leak. The durable fixes all do one of two things: verify that the request which wrote the cookie was a real click, or change the join so it no longer depends on a value the partner can cause to be written.
How to Detect Cookie Stuffing
The signals in most published advice are the right ones. What follows attaches a method to each, ordered from cheapest to most involved. The first three need nothing beyond logs you probably already have.
Request metadata on every tracking hit
Log the Referer, Sec-Fetch-Dest, Sec-Fetch-Mode and Sec-Fetch-User headers on every request to your tracking endpoint, alongside the partner ID. Then compare each partner's referrers to the domains they declared when they joined.
This query, against a log table of tracking hits, gives each partner's share of cookie-setting requests that arrived with no referrer, from an undeclared domain, or not as a navigation at all:
-- Share of each partner's cookie-setting hits that don't look like a click on a declared placement
SELECT h.partner_id,
count(*) AS cookie_sets,
round(100.0 * count(*) FILTER (WHERE h.referer_host IS NULL) / count(*), 1) AS no_referrer_pct,
round(100.0 * count(*) FILTER (WHERE h.referer_host <> ALL (p.declared_domains)) / count(*), 1) AS undeclared_pct,
round(100.0 * count(*) FILTER (WHERE h.sec_fetch_dest IS DISTINCT FROM 'document') / count(*), 1) AS not_navigation_pct
FROM tracking_hits h
JOIN partners p USING (partner_id)
WHERE h.hit_at >= now() - INTERVAL '30 days'
GROUP BY h.partner_id
ORDER BY undeclared_pct DESC;A missing referrer on its own proves little, because privacy settings and app webviews strip it. A partner whose cookie-sets mostly come from domains it never declared, or arrive as image and iframe loads, is a different matter. The same headers also let you prevent the subresource variants outright: refuse to set the cookie unless the request is a navigation, and set the cookie SameSite=Lax, which browsers reject when it arrives in the response to a cross-site image or iframe request.
Click-to-conversion latency, per partner ID
Instead of watching for "suspicious latency", histogram the gap between cookie-set and conversion for each partner and look for two shapes. A mass near zero means the cookie was written while a purchase was already in progress, which is the signature of checkout-time stuffing. Unnaturally uniform gaps across hundreds of conversions suggest scripted timing rather than human browsing.
Cookie-sets that never became a visit
A real click lands a person on your site. A stuffed image or iframe sets the cookie and nothing else. Divide each partner's landing-page sessions by its tracking hits: a partner whose hits mostly produce no page view is writing cookies, not sending visitors.
Conversion-rate outliers, in context
Conversion-rate monitoring appears on every list of controls, and it belongs in the set. On its own it is weak: it is a lagging, aggregate indicator that catches the crude operator stuffing at volume and misses the calibrated one who keeps their rate plausible. Use it to decide where to look, and the per-request signals above to decide what happened.
The join-key check
Everything so far infers stuffing from patterns. This last method checks the claim directly: did the click happen in the browser that converted?
Generate a browser-level identifier on the partner's page at the moment of the click and again on your conversion page, record both, and match them server-side. ThumbmarkJS is one example of a browser identification library built for this, used on 60,000+ websites. Because the identifier is derived from the browser rather than stored in it, a partner cannot write it into a visitor's browser from a hidden tag. The open-source library is enough to measure your own mismatch rate before you change any enforcement.
The client side is the same on both pages. This sends the identifier and the partner ID to your own attribution endpoint:
// Run on the partner's click placement and on your order confirmation page
import { Thumbmark } from '@thumbmarkjs/thumbmarkjs';
const tm = new Thumbmark({ api_key: 'YOUR_API_KEY' }); // omit api_key to use the open-source library alone
const result = await tm.get();
navigator.sendBeacon('https://example-shop.com/attribution/events', JSON.stringify({
event: 'click', // 'conversion' on the confirmation page
partner_id: 'PARTNER123',
browser_id: result.thumbmark,
visitor_id: result.visitorId, // only present when an api_key is set
}));The test itself is a single query: conversions credited to a partner for which no click from that partner shares the converting browser's identifier.
-- Conversions credited to a partner whose click never happened in the converting browser
WITH credited AS (
SELECT c.partner_id,
EXISTS (
SELECT 1
FROM partner_clicks k
WHERE k.partner_id = c.partner_id
AND k.browser_id = c.browser_id
AND k.clicked_at BETWEEN c.converted_at - INTERVAL '30 days' AND c.converted_at
) AS click_in_same_browser
FROM conversions c
WHERE c.converted_at >= now() - INTERVAL '90 days'
)
SELECT partner_id,
count(*) AS conversions,
count(*) FILTER (WHERE NOT click_in_same_browser) AS unmatched,
round(100.0 * count(*) FILTER (WHERE NOT click_in_same_browser) / count(*), 1) AS unmatched_pct
FROM credited
GROUP BY partner_id
ORDER BY unmatched_pct DESC;Every program has a baseline of unmatched conversions from legitimate journeys, covered in the next section. The signal is a partner far above that baseline. Its unmatched conversions are not anomalies to be scored: they are conversions whose credited click did not happen in that browser.
This works where you have code on both sides of the handoff, as affiliate platforms and multi-domain merchants do, with the identifier matched across domains server-side. If you prefer the data not to pass through the browser on its way to you, the API can also deliver each result by webhook. Delivery is asynchronous and unordered, which suits attribution reconciliation because it runs after the fact anyway.
What a Browser-Level Identifier Doesn't Catch
The join-key check is the strongest method on this list. It is not complete, and the gaps are specific.
It identifies a browser environment, not a person or a device. A journey that starts in Chrome on a laptop and converts in Safari on a phone will not join. That is a legitimate journey, and it is part of the baseline the query must not flag. Cross-device attribution needs the customer to log in.
IP address is part of the default fingerprint. An operator who resets their browser and switches proxy at the same time produces a new identifier.
It cannot catch an extension stuffing at checkout. A malicious extension runs inside the real visitor's real browser, so anything it triggers comes from that browser and the identifiers match on both sides. The join proves the click happened in this browser, not that the visitor chose it. Latency and request metadata catch this variant; the join key does not.
It produces a signal, not a verdict. Whether to hold, reverse, or pay a flagged commission is your program's decision.
What it changes is what the attribution join is made of: a value the partner cannot write instead of one it can. That raises the cost of forging attribution at scale. It does not make attribution unforgeable.
Is Cookie Stuffing Illegal?
In the US it has been prosecuted as a crime. eBay sued several of its top affiliates over cookie stuffing in 2008 (case documents collected by Benjamin Edelman), and federal wire fraud charges followed. In 2014 one of those affiliates was sentenced to 15 months in prison after pleading guilty to wire fraud over a scheme that ran from 2006 to 2007, according to the US Attorney's Office for the Northern District of California.
Criminal prosecution is rare, though. The route most merchants actually use is contractual. Every major affiliate network prohibits cookie stuffing in its terms, and the usual consequences are reversed commissions, withheld payouts and removal from the program.
Browser extensions have moved the question into civil litigation and network enforcement. In January 2026, Rakuten Advertising removed PayPal's Honey extension from its network, a week after an amended class-action complaint alleged that the extension had repeatedly violated the network's stand-down policies. Those allegations are unproven, and the extension was later readmitted. For a merchant deciding whether to pursue a partner, the practical lesson is that the evidence you log at the tracking endpoint is what any of these routes will rest on.
Closing the Gap
Cookie stuffing is not six techniques. It is one gap: an attribution endpoint that cannot distinguish a click from a tag. Every durable fix either verifies the request that writes the cookie, or changes the join so it stops depending on that cookie.
The request-metadata and latency queries can run against your existing logs this week. For the join-key check, the ThumbmarkJS open-source library on GitHub will generate an identifier on both domains so you can measure your own mismatch rate before changing anything, and our guide to generating an identifier in the browser walks through the implementation.
Frequently Asked Questions
Is cookie stuffing illegal?
In the US it has led to federal wire fraud convictions, including a 15-month prison sentence for an eBay affiliate in 2014. More commonly it is handled as a contract breach: every major affiliate network prohibits it, and stuffing partners lose their commissions and their place in the program.
Can you give me an example of cookie stuffing?
A partner places a hidden 1×1 image on an unrelated web page, with the image's source set to their affiliate tracking URL. Every visitor who loads that page sends a request to the merchant's tracking endpoint and receives the partner's cookie. If any of them later buys, the partner is paid, though nobody clicked anything.
How is cookie stuffing different from click injection?
Cookie stuffing plants a web affiliate cookie in a browser without a click. Click injection is a mobile app install fraud, in which a malicious app on the same phone fires a fake ad click moments before another app finishes installing, so that it is credited with the install.
Does blocking third-party cookies stop cookie stuffing?
Mostly not. Restrictions on third-party cookies can stop the hidden-image and iframe variants, where the cookie is set in a third-party context. But redirect-based stuffing sends the browser to the merchant's own domain, so the affiliate cookie is first-party and unaffected. Redirects delivered over 91% of stuffed cookies in the 2015 UC San Diego measurement cited above.