Preview attribution flows before production - works with Adobe, GA4, Target, and Piano.
Here’s the problem: you can’t preview referrer-driven locally. Browsers don’t send a real Referer
or fill document.referrer
the way they do in production. That leaves Growth, Marketing, Analytics, Experimentation, and QA teams flying blind until things are live-when dashboards suddenly scream “Direct/None” and someone inevitably asks if Adobe is broken. Fun (it’s not, this time).
The fix is surprisingly simple (Which is ironic, because the browser is basically running an obstacle course behind the scenes). All you have to do is act like the referrer for a moment over HTTPS, then jump straight into your app. The browser sets a real referrer - no extensions, no flags, no staring at a waterfall of requests in the network tab while your coffee gets cold.
And it works everywhere: Adobe Analytics/Experience Cloud, Adobe Target, Piano, GA4 - any tool that makes you argue about attribution.
Why it fails locally
Browsers are picky. Open a link from your terminal and hit a top-level 302? Some drop document.referrer
. Serve your app without a “real” HTTPS origin? Same result. Local ≠ production, which is why pre-launch checks for campaigns, partners, and paywalls feel like guesswork - or weather forecasting.
We don’t need to fight the browser; we can play by its rules for five minutes: look like the referrer, then redirect.
Meet Reflex (the Fix)
To make that easier, I built a tiny helper called Reflex. It’s a simple CLI that handles the annoying setup for you so you can test referrer-driven flows locally without wrestling with configs or browser quirks.
What Reflex does
Point the referrer host (e.g., news.google.com) at your machine for a moment.
Serve a tiny HTTPS page using a locally trusted certificate.
Redirect into your app so the browser sets a real Referer
and document.referrer
.
You can do this with a small CLI, reflex
. It updates your hosts file with a tagged entry, spins up HTTPS, and opens your browser in private mode so each run is clean. Push button, receive referrer.
15-Second Setup
One-time setup: share the same local CA between root and your user so browsers trust the certs.
# Assume you already installed mkcert
sudo mkcert -install
mkcert -install
# required in Linux
sudo mkdir -p /etc/mkcert
sudo cp -a "$(mkcert -CAROOT)/." /etc/mkcert/
sudo chmod 755 /etc/mkcert && sudo chmod 644 /etc/mkcert/*
Then run a flow using reflex (deep breath, two commands):
sudo reflex run \
--referrer https://news.google.com \
--target https://your-app.example
What happens: it opens a private window (will do his best), serves a tiny HTTPS “referrer” page, and sends you to your app with a real Referer
- so tags, SDKs, and experiments act like the real world.
Cleanup (It does it on exit though):
sudo reflex cleanup --referrer news.google.com
# OR if you are too lazy (just like me 😅)
sudo reflex cleanup --all
Pick your redirect
meta
(default): the reliable workhorse. Short HTML meta refresh - best bet for a stable document.referrer
.js
: same idea, different flavor. Quick window.location
after a beat.302
: the spicy one. Great for testing 302 behavior, but some browsers drop document.referrer
on top-level 302s opened externally. Choose with care.
Who benefits (and how)
Growth/Marketing: confirm attribution before launch so dashboards don’t go “Direct/None”.
Analytics/Tagging: validate Adobe Analytics/Experience, Piano, GA4 events with correct referrer and UTM context.
Experimentation: verify A/B targeting rules (Adobe Target, Piano) actually trigger.
QA/E2E: write stable tests for referrer-sensitive flows without staging contortions.
Data/BI: reduce “mystery traffic” and post-deploy fire drills.
Gotchas (quick fixes)
Need the full referrer URL, not just origin? Add --referrer-policy unsafe-url
.
Corporate VPN/DNS agents can override /etc/hosts
. If it seems ignored, that’s the culprit. Thanks, security.
Private/incognito keeps runs clean and reduces “why does this only happen on my machine?” moments.
Requires admin rights (hosts + binding to 443). If 443 is busy, reflex
falls back to 8443.
Bottom line
This is the missing local preview: see how your site behaves under a specific referrer before you ship. Emulate the referrer, redirect once, and your browser plays by real-world rules. Your analytics tools (Adobe Analytics/Experience, Piano, GA4, etc.) get proper context, experiments behave, and your team gets their evening back (maybe the weekend, too).
If you want the CLI that does this, it’s reflex
. Use it, tweak it, or copy the idea - the key is giving your browser the polite intro it expects.
Source and Binary on Github: https://github.com/samfrm/reflex