One env flag that strips affiliate CTAs for AdSense review โ€” without touching code
DEV Community

One env flag that strips affiliate CTAs for AdSense review - without touching code

After four AdSense rejections, I did a more careful read of what the ossfind.com pages looked like to a human reviewer. The verdict: affiliate CTAs, an Amazon product widget, and "sister site" cross-links to aiappdex and findindiegame - together, they made the site read as a revenue-motivated content network rather than a standalone editorial resource. That's a rejection signal I had underestimated. I decided to try for approval on ossfind specifically.

But stripping those revenue channels to pass review and then re-adding them after would normally mean multiple code deploys. I didn't want that risk - one botched re-activation and the affiliate links silently don't appear. The solution was a single environment variable: PUBLIC_REVIEW_MODE=1.

What it hides

The getMonetization() function in packages/shared/src/monetization/index.ts returns an enabled object that each Astro component checks before rendering:

const reviewMode = process.env.PUBLIC_REVIEW_MODE === "1";
return {
  // ...
  enabled: {
    ads: mode === "adsense" && !!adsenseClient,
    amazon: !!amazonTag && !reviewMode,
    affiliate: !reviewMode,
    newsletter: !!newsletterAction,
    ga4: !!ga4Id,
  },
};

When PUBLIC_REVIEW_MODE=1 is set in Cloudflare Pages:

  • enabled.amazon โ†’ false: AmazonRecommend.astro renders nothing. No product widget, no affiliate tag in any URL.
  • enabled.affiliate โ†’ false: All hosting referral CTAs (DigitalOcean, Hetzner, Vultr, RunPod, Vast.ai) render nothing. The GPU affiliate links I wrote about wiring into the AI tools directory are hidden.
  • Sister-site cross-links: these are controlled separately in templates by checking !reviewMode directly. In review mode the nav and footer drop the "Also see: aiappdex.com / findindiegame.com" links.

Crucially, enabled.ads is not gated by reviewMode. The AdSense script tag needs to be present for account domain verification and for the review itself. Hiding it would defeat the purpose.

Why build it at the environment level, not as a code branch

I could have added a REVIEW_MODE boolean to the TypeScript config object and deployed. But the key property I wanted was zero code change on both entry and exit. Setting a Cloudflare Pages environment variable triggers an automatic redeploy. Removing it triggers another. No PR, no review, no merge. If I later decide mid-review that I want to re-enable Amazon links to test something, I can do it without touching source. The audit trail lives in Cloudflare's env change log, not in git commits.

The PUBLIC_ prefix matters for Astro: environment variables without it are server-only. PUBLIC_REVIEW_MODE is read at build time by getMonetization() inside packages/shared, which runs during Astro's SSG build. The value bakes into the static HTML - there's no runtime re-evaluation. That's correct behaviour for a static site: the entire site builds clean with all affiliate links removed, and any cached CDN responses reflect that clean state. Cloudflare Pages environment variable updates trigger an automatic redeploy of the project, which is the mechanism that makes this pattern work without manual CI intervention.

Restoring after approval

One Cloudflare Pages action: remove PUBLIC_REVIEW_MODE from the project's environment variables. On the next redeploy (automatic, triggered by the env change), all affiliate and Amazon paths re-enable wherever the existing code checks enabled.affiliate and enabled.amazon. Nothing in the TypeScript needs to change. The pattern is closer to a feature flag than a code branch - which is why I used the env layer instead of git checkout -b review-clean.

I don't know yet how long AdSense review takes, or whether they re-crawl after an initial pass. Affiliate monetization is the primary strategy now for two of the three sites regardless, so this review mode only applies to ossfind. I'll publish numbers when there's something real to report.

What I still haven't figured out

Whether AdSense reviews manually or with a bot. The rejection emails have all been form letters with category codes, not specific page URLs. So I don't know whether a reviewer is clicking through a live site or scraping a cached snapshot. If it's the latter, the redeploy timing matters in a way I can't control.

I also don't know if the newsletter field should be gated by reviewMode. Newsletter forms are probably neutral to AdSense, but I'm not certain. Right now they stay visible during review - if there's another rejection I'll check that as well.

Part of an ongoing 6-month experiment running three AI-curated directory sites. The technical claims here are real; this article was AI-assisted.

Comments

No comments yet. Start the discussion.