This is a first-person build log for aogl.cn itself—not a third-party tutorial and not a scraped “how to monetize” outline. I maintain a static multilanguage editorial site that also hosts original demos and sibling apps (EatToday, WordPet, Worlds Greatest). The practical question AdSense reviewers and fellow builders keep asking is simple: how does the pipeline turn source HTML into locale sites, which pages stay indexable, and where do ads actually load? This note answers with the real scripts under scripts/ and js/adsense.js, dated 2026-09-14.
og-default.png — site-level Open Graph default; cover WebP is generated into upload/articles/.Mental model: one multilang source, many locale outputs
Almost every public page starts life under _multilang/. That folder holds bilingual (or multilingual) source documents with lang-* class spans for English, Simplified Chinese, Japanese, Korean, French, Russian, and Arabic. I do not hand-maintain seven full copies of every paragraph for hubs and static pages. Instead, scripts/build-seo-locale-pages.mjs reads _multilang/*.html, then writes:
- Site root — Simplified Chinese as the primary Chinese surface (canonical on itself).
/zh/— Traditional Chinese via OpenCC conversion from the Simplifiedlang-zhblocks./en/,/ja/,/ko/,/fr/,/ru/,/ar/— monolingual locale trees.
That split is the spine of the site. If you edit only a locale file under /en/ and forget _multilang/, the next full locale rebuild will overwrite you. The durable edit surface for shared chrome is always the multilang source (plus article fragment files described below).
Articles: JSON hubs + htmlFragments
scripts/build-articles.mjs reads every file in data/articles/*.json. Each JSON is a small hub: slug, layout, dates, hero paths, seven-language titles/descriptions, and an htmlFragments map pointing at files under data/articles/fragments/. The builder writes _multilang/articles/<slug>.html, refreshes the homepage INDEX_ORIGINALS markers, and rebuilds _multilang/articles/index.html. Thick English and Chinese fragments carry AdSense review weight; short ja/ko/fr/ru/ar stubs keep hreflang surfaces honest without pretending every locale is a full essay.
Hero covers are not invented stock photography. npm run generate-article-covers runs scripts/generate-article-covers.py, which crops heroImageSource into a 1200×675 WebP at upload/articles/<slug>.webp. For this page the source is the committed site asset og-default.png (cover generated separately because the Python helper skips the literal string og-default.png as a safety default).
Navigation injection and homepage composition
Primary nav is not copy-pasted across fifty templates. scripts/inject-site-nav.mjs injects shared markup from scripts/site-nav.mjs into _multilang/index.html between SITE_NAV_AUTO_START / SITE_NAV_AUTO_END markers. Related injectors (inject-categories.mjs, inject-index-pills.mjs, inject-tools-directory.mjs, update-reading.mjs) keep the homepage rails mechanical. The full orchestration lives in package.json as build-site: articles → briefs → tool guides → hubs → nav → reading → contact → SEO locales. I run pieces when I need them; I avoid blind full rebuilds mid-edit so fragment drafts are not half-overwritten.
seo-index-policy: ARTICLE_ARCHIVE_NOINDEX
scripts/seo-index-policy.mjs is the policy brain for robots, sitemap membership, and “is this thin archive?” decisions. Ranking tables, chart dumps, and buy-guide listicles sit in ARTICLE_ARCHIVE_NOINDEX_SLUGS. Those URLs stay useful as human bookmarks and hub cards, but they ship with noindex,follow and are kept out of the primary AdSense surface. Original demos, production notes, and first-party app essays—EatToday, WordPet, Worlds Greatest, this build log—stay indexable.
Related constants matter too: NOINDEX_PATH_PREFIXES covers aggregator rails like hub-links/, briefs/, and tool-guides/; NOINDEX_STATIC_PAGES covers hub verticals such as tech.html and life.html; SITEMAP_STATIC_PAGES whitelists only a small set of static pages plus indexable articles. When people ask why the homepage is quiet and the hubs feel sparse for ads, the answer is intentional policy—not a broken publisher tag.
AdSense only on indexable primary pages
js/adsense.js always ships on many templates, but it does not always request adsbygoogle.js. The loader checks isContentPrimaryPage(): about/changelog qualify; article URLs qualify only when the page meta robots content does not include noindex. Localhost, ?noads=1, localStorage aogl-disable-ads, and window.AOGL_DISABLE_ADSENSE also skip the network call. That pairing—server/build policy sets robots, client loader respects robots—is what keeps auto ads off thin archives while still allowing them on thick originals.
Homepage slim outbound
Earlier AdSense remediation removed dense bookmark walls and Google-search SEO pills. scripts/adsense-slim-outbound.mjs documents the one-shot helpers: slim the homepage #pillars section to a short lead that points at editorial demos and About, and strip google.com/search pills from article fragments. Current article footers should only pill to real app URLs and /articles/index.html (plus maybe home originals). That is not “less SEO”—it is clearer primary content with fewer outbound distractions for reviewers.
Day-to-day edit loop I actually use
- Author or revise
data/articles/<slug>.jsonand thick*-en.html/*-zh.htmlfragments. - Prepend the slug into
data/tech-hub-articles.jsonordata/life-hub-articles.jsonwhen the piece belongs on a hub rail. - Generate covers if
heroImageSourcechanged. - Run
npm run build-articles(and later locale split) when ready to publish HTML—not while drafting prose. - Verify robots on archive vs primary pages before expecting ads.
Sibling apps stay on their own origins (eattoday.aogl.cn, wordpet.aogl.cn, mnm.aogl.cn). The editorial site documents them with first-screen HTML and original screenshot archives; the interactive products keep their own cookies and deploy cadence. That boundary is as important as any AdSense toggle.
What this page is not claiming
This is not a guarantee of AdSense approval, CPC, or traffic. Policy files change when Google’s review signals change. Script names above are accurate as of 2026-09-14 in this repository; if you fork the site, re-read the files rather than trusting a blog paraphrase. The durable lesson is architectural: separate multilang authoring from locale emission, separate bookmark archives from indexable essays, and load ads only where the HTML is worth indexing.