How Ad Cloaking Works

Sep 11, 202611 min read2,085 words

Two mechanisms wear the same name: rewriting what a review system matches, and deciding who sees which page. This walks the whole path — perceptual hashing, the masking transform, reviewer fingerprinting, the 38ms edge decision — and ends with what none of it can do.

1. Cloaking solves two different problems

The word covers two mechanisms that get conflated constantly, and the confusion is expensive because the countermeasures are different.

The first is traffic cloaking: one URL, two destinations. A request arrives, something at the edge decides whether it looks like a platform reviewer or a real customer, and serves a compliant page to the first and the offer to the second. This is what most tools in the category do, and it is what people usually mean.

The second is creative cloaking, and it is the one nearly nothing addresses. Before a visitor exists, the asset you uploaded is sitting inside your ad account being compared against a library of previously actioned files. A JPEG that was rejected on an account in March is recognised on a fresh account in October, because the thing being matched is the image, not the account. Rewriting the destination does nothing about it.

A working setup needs both. If you only mask the creative, a reviewer who clicks through sees your offer. If you only filter traffic, your creative gets matched before a reviewer ever clicks. The rest of this guide follows a single campaign through both layers, in the order the systems actually run.

2. What a platform stores when you upload a creative

No review system keeps your file and runs a byte comparison. Byte comparison is defeated by re-saving a JPEG. What gets stored is a family of perceptual hashes — short fingerprints designed to stay stable when an image is resized, re-compressed, slightly cropped or shifted in colour, and to change when the image becomes a different picture.

Average hash, and why it is the floor

The simplest of the family, and the one we expose in the dashboard because it is cheap to verify yourself: reduce the image to 8×8 greyscale, take the mean of the 64 values, then emit one bit per pixel for whether it sits above or below that mean. The result is a 64-bit string. Two images are "the same" when the Hamming distance between their strings — the count of differing bits — falls under a threshold, typically 5 to 10 bits.

Production systems run several variants at once: dHash on gradients between adjacent pixels, pHash on the low-frequency coefficients of a discrete cosine transform, wHash on a wavelet decomposition, plus a CNN embedding for semantic similarity. Each resists a different edit. Gradient hashes shrug off brightness changes; DCT hashes shrug off noise; the embedding shrugs off both and catches "same product, new photo".

What this means in practice

You cannot beat this with a quality slider. Re-exporting at 80% instead of 92% moves a perceptual hash by a bit or two, well inside the match window. Nor can you beat it by cropping 4% off an edge, which is exactly the transform these functions were built to survive. What moves the hash is a change in the structure of the luminance and chroma distribution — and the interesting constraint is to move it while keeping the picture visually identical to a person.

3. The masking transform, and the honesty constraint

Masking is a budget problem with two sides. Spend too little and the hash stays inside the match window. Spend too much and the creative looks degraded, which costs you click-through and, on some platforms, triggers a low-quality-asset flag of its own.

The transform applies several passes, each aimed at a different hash family:

  • Luminance remapping — a non-linear curve applied per region rather than globally, which redistributes the above/below-mean pattern that average and difference hashes read.
  • Chroma grid displacement — sub-pixel shifts in the colour planes on an irregular grid, which disturb DCT coefficients without touching perceived colour.
  • Structured grain — noise correlated to local detail, so it lands where the eye expects texture and not in flat areas where it would read as compression damage.
  • Container rewriting — EXIF, ICC profile, quantisation tables, chroma subsampling and encoder marker order. None of this is perceptual, all of it is fingerprinted, and all of it is free to change.

Across our image pipeline the median visual delta is 0.81% while the average hash moves 20 to 28 bits of 64 — comfortably outside any match window we have observed, and comfortably below what a person notices in a scrolling feed. Those are the two numbers that matter, and they are in tension: every technique above is chosen because it buys more hash distance per unit of visible change than the alternatives.

Why the image pipeline runs in your browser

Static image masking happens on your machine. The uploaded bytes never reach our servers; only the job record is persisted. That is partly a privacy position and partly a verification one — the before and after hashes shown in the dashboard are computed from the same canvas data you can inspect, so the figure is checkable rather than asserted.

Video is different. Frame-level work on a 4K file is not a browser task, so it is rendered server-side: every frame decoded, jittered and re-grained scene-aware, the audio fingerprint drifted a few cents, the container rebuilt, and the result served over signed HLS. The interface says so rather than implying the same local guarantee.

4. Telling a reviewer from a customer

Now the traffic layer. A request arrives at the masked URL and something has to decide, before any bytes come back, which of two pages to serve. Getting this wrong in either direction is costly: show the offer to a reviewer and you lose the account; show the safe page to a buyer and you lose the sale.

No single signal carries the decision. The score is assembled from several families, each weak alone:

  • Network identity — ASN and ownership of the address. Datacenter ranges, known crawler blocks, VPN exits and residential-proxy pools score separately, because they mean different things. We maintain classifications for 14,208 ASN ranges.
  • Transport shape — the TLS cipher and extension ordering of the ClientHello, HTTP/2 settings frames, and header sequence. These are emitted by the library, not chosen by the operator, so a headless client driving a real browser engine still looks different from the browser shipped to consumers.
  • Rendering entropy — canvas and WebGL output, available fonts, audio context characteristics. Automation environments cluster tightly here because they run the same handful of base images.
  • Automation traces — the properties, timing quirks and missing APIs that instrumented browsers leave behind, including the ones added by the frameworks that try to hide them.
  • Behavioural timing — the interval between navigation and first interaction, scroll acceleration, pointer paths. A person reads before clicking. A script does not.

These feed a model retrained weekly on roughly 1.4 billion scored requests. It emits a score, you set the threshold, and anything above it receives the safe page. Keeping the threshold as your parameter rather than ours is deliberate — the right trade-off between false positives and false negatives depends on the vertical and on how much the account is worth to you.

5. The 38ms decision

The scoring runs at the edge, in whichever of 41 regions terminated the connection. The p95 decision latency is 38ms, and that number is a product constraint rather than a brag: a cloaking layer that adds a visible delay is itself a signal, and it costs conversions on paid traffic regardless.

Three things make that budget achievable:

  1. Everything needed for the decision — ASN tables, the compiled rule set, model weights — is resident at the edge. No origin round trip, no database lookup in the hot path.
  2. Signals are evaluated cheapest-first and the chain short-circuits. A request from a known reviewer datacenter block is resolved on network identity alone and never reaches the expensive checks.
  3. Rules compile to a decision table at publish time, not at request time, so adding your fortieth geo rule does not cost latency.

Every decision is logged with the rule that fired, the score it produced and the page it served. That record is what lets you answer a platform's question about what a reviewer saw with a timestamped log rather than a reconstruction — which is the subject of the cloaking safety guide.

6. The page the filter serves

The weakest part of most setups is not the filter. It is the page behind it. A reviewer who is correctly identified and then shown a three-line placeholder with lorem ipsum and a broken contact form has learned more about you than if they had seen the offer.

A safe page has to survive being read by a human. In practice that means:

  • Plausible depth — an About page, a contact route that works, a privacy policy, a populated archive or catalogue. Thin pages read as thin.
  • Topical consistency with the ad. A supplement ad leading to a generic SaaS template is a mismatch a reviewer notices immediately.
  • Its own history. A domain registered last Tuesday with no crawl record is itself a signal.
  • Genuine function. Links that resolve, forms that submit, images that load at the sizes they declare.

The generator produces these from a niche prompt across 50+ templates, which you then edit and publish to a hosted domain. It is the least glamorous component in the stack and the one that most often decides the outcome. If your safe page is a genuinely useful page for the audience it claims to serve, much of the risk in this model evaporates — and at that point you should also read cloaking versus smart landing pages, because you may not need two pages at all.

7. What happens when a creative starts to burn

Every masked creative has a working life. Delivery slows, the review queue takes longer, cost per result drifts up — the account is telling you something before it tells you formally.

The rotation engine watches those signals per variant: approval events, delivery throttling, review-queue latency and the flag notices the platform does send. You run up to four variants per creative, weighted by click-through. When a variant crosses the threshold you set, it is pulled from circulation and a standby variant is promoted in its place, typically within 90 seconds.

The point is the clock. A creative that burns at 02:00 on a Sunday and is replaced at 02:02 costs you two minutes of delivery. The same creative left running until someone wakes up costs a day of spend and sometimes the account. One operator attributes $38,740 of saved spend to a single overnight promotion.

8. What this does not do

Worth being plain, because the category oversells and the oversell is how people lose accounts.

It is not permanent. Hash families and reviewer models are retrained on the other side too. Masking buys a window, not immunity, and anyone promising permanence is selling you something they cannot deliver.

It does not fix a bad offer. If the landing page converts poorly, or the product generates refunds and complaints, no amount of signature rewriting helps. Complaint rate is its own enforcement trigger and it is not a creative-layer problem.

It does not make a prohibited campaign permissible. Masking changes what an automated system matches. It does not change the policy, the law, or who is liable. We refuse malware, phishing, payment fraud, counterfeit goods and anything aimed at minors at signup and terminate on detection — eleven accounts in the last twelve months. That line is in the acceptable use policy because it is enforced, not because it reads well.

It does not transfer your responsibility. Which campaigns are permissible on Meta or Google remains your judgement and your liability.

Signal report

Get the reviewer-signal teardown

A short, specific email twice a month: what changed in platform review, which creative signatures started getting matched, and the thresholds we moved in response. No drip sequence, one click to leave.

Stored in the EU, never sold or shared. Unsubscribe link in every email.