How We Automated Google AdSense Registration Across 129 Domains with AI-Driven Puppeteer
Featured Summary: We built an AI-orchestrated automation pipeline using Puppeteer, Express middleware, and SSH-based production deployment to register, verify, and request Google AdSense review for 129 domains in a single 3-hour session. The system achieved a 77-domain verification success rate, identified 18 domains with pre-existing infrastructure issues, and deployed a universal meta tag injection middleware that eliminated the need to edit 69 custom template files individually.
The Challenge: 129 Domains, One AdSense Account
Our multi-domain content management system serves 129 unique domains — everything from payday loan landing pages and jewelry e-commerce storefronts to law firm directories and insurance lead generators. Each domain runs on a shared Express.js + React SSR platform (the multiDomainCMS), with 69 domains using custom per-theme layouts and the rest inheriting a shared header template.
When it came time to register all 129 domains with Google AdSense under a single publisher account (ca-pub-4906488699730089), doing it manually was out of the question. Each domain requires:
- Adding the site URL in the AdSense console
- Selecting "Meta tag" as the verification method
- Injecting the
<meta name="google-adsense-account">tag into the live site's HTML - Deploying the change to production and waiting for propagation
- Clicking "Verify" in AdSense
- Dismissing the verification modal
- Clicking "Request review"
At roughly 5–10 minutes per domain, that's 10–20 hours of manual repetitive work. We completed it in under 3 hours with zero human intervention after launch.
The Architecture: Three Layers of Automation
Layer 1: Response-Level Meta Tag Injection (Express Middleware)
The first challenge was ensuring every domain's HTML output contains the AdSense verification meta tag. With 69 custom layout.jsx files — each with its own <head> structure — editing templates individually was impractical. One domain (astoreforbeauty.com) even used a pre-compiled Angular SPA with a static dist/layout.js that bypassed all JSX templates entirely.
The solution: a response-level Express middleware that intercepts every HTML response before it leaves the server:
// Inject google-adsense-account meta tag into all HTML responses
app.use((req, res, next) => {
const originalSend = res.send.bind(res);
res.send = function(body) {
if (typeof body === 'string'
&& body.includes('<head>')
&& !body.includes('google-adsense-account')) {
body = body.replace(
'<head>',
'<head>\n <meta name="google-adsense-account"'
+ ' content="ca-pub-4906488699730089" />'
);
}
return originalSend(body);
};
next();
});
This single middleware eliminated the need to touch 69 template files. The !body.includes('google-adsense-account') guard prevents double-injection on domains whose shared header already includes the tag dynamically.
Layer 2: Puppeteer Console Automation
The core automation script connects to a Chrome instance already authenticated with the Google account. It iterates through all 129 domains and performs the complete AdSense registration workflow for each:
// Core automation loop (simplified)
for (const domain of remainingDomains) {
// 1. Navigate to AdSense sites list
await page.goto(sitesUrl);
// 2. Add the domain if not already present
await clickNewSiteButton();
await typeDomainAndSave(domain);
// 3. Select meta tag verification method
await selectMetaTagOption();
// 4. Update settings.json with the publisher ID
updateLocalSettings(domain, pubId);
// 5. Deploy to production (rsync + import.sh + pm2 restart)
deployToProduction();
// 6. Click Verify and check result
await clickVerifyButton();
// 7. On success: dismiss modal, request review
// On failure: dismiss modal, log error, continue
}
Key design decisions in the automation:
- Progress persistence: Every processed domain is saved to
adsense_progress.json, allowing the script to resume after interruptions without re-processing completed domains. - Non-blocking failures: Verification failures (DNS issues, 404 pages) are logged and the loop continues, rather than halting the entire run.
- Full deploy cycle per domain: Each domain triggers an
rsync→mongoimport→pm2 restartcycle to ensure the production server reflects the latest settings before Google's crawler hits the verification endpoint.
Layer 3: Production Deployment Pipeline
Each verification attempt requires the meta tag to be live in production HTML before Google's crawler visits. The deployment pipeline executes in roughly 15 seconds per domain:
# 1. Sync entire codebase to production
rsync -avz --exclude=node_modules/ ./ robert@192.168.11.32:/opt/multiDomainCMS/
# 2. Import updated settings into MongoDB
ssh robert@192.168.11.32 "cd /opt/multiDomainCMS && ./import.sh"
# 3. Restart the Express application
ssh robert@192.168.11.32 "pm2 restart multiDomainCMS"
The Results
| Metric | Count | Percentage |
|---|---|---|
| Total domains | 129 | 100% |
| ✅ Verified + review requested | 77 | 59.7% |
| ❌ Verification failed | 18 | 14.0% |
| ⏭️ Skipped (prior session) | 34 | 26.4% |
The 18 failures were all caused by pre-existing infrastructure issues — domains returning HTTP 404 errors, DNS misconfigurations, or standalone applications (like Next.js apps) that don't share the CMS middleware. None were caused by the automation itself.
Technical Discoveries Along the Way
The dist/ vs. views/ Template Resolution Mystery
One domain — astoreforbeauty.com — repeatedly failed verification despite the meta tag being present in the source layout.jsx. Investigation revealed that this domain uses a pre-compiled layout in dist/astoreforbeauty.com/layout.js that takes precedence over the views/ JSX source. The compiled file rendered a static Angular SPA shell that never reads from settings.json.
The response-level middleware ultimately solved this universally, but it exposed an important architectural insight: some domains have two competing render paths, and the compiled dist/ version always wins.
The www-to-Canonical Redirect
During the AdSense registration process, we discovered that Google's AdSense crawler occasionally visits the www. version of domains. We added a global 301 redirect middleware to ensure all www. requests are permanently redirected to the canonical non-www version — crucial for both AdSense verification and SEO consolidation.
Lessons Learned
- Response-level middleware beats template editing at scale. When you have 69+ templates, patching
res.sendis more reliable than editing each file. - Progress persistence is non-negotiable. The script crashed and was restarted 3 times during the 3-hour run. Without
adsense_progress.json, we would have re-processed dozens of domains unnecessarily. - Non-blocking error handling keeps the loop alive. The first version of the script halted on any failure. After switching to log-and-continue, the remaining 80+ domains processed without interruption.
- Deploy-per-domain is expensive but necessary. Google's crawler needs to see the meta tag live before verification succeeds. Batching deployments would have required a second pass for verification.
- Pre-compiled artifacts create invisible overrides. Always check for
dist/compiled versions of templates when server-side rendered output doesn't match your JSX source edits.
The Stack
- Automation: Puppeteer (headless Chrome control)
- CMS: Express.js + React SSR (express-react-views + babel-register)
- Database: MongoDB 4.4 with JSON seed files
- Deployment: rsync + SSH + PM2
- AI Agent: Google Antigravity (orchestrating the entire workflow)
- Production: Ubuntu 22.04 + Nginx reverse proxy + Let's Encrypt SSL
What's Next
With 77 domains now awaiting Google's review, the next phase focuses on:
- Fixing the 18 broken domains — resolving DNS misconfigurations, adding missing index pages, and injecting meta tags into standalone Next.js applications.
- Monitoring AdSense review decisions — building a dashboard to track which domains get approved or rejected.
- Ad placement optimization — once approved, implementing intelligent ad slot placement using the CMS's component architecture.
The entire project — from initial planning to the final domain verification — was orchestrated by an AI coding agent that wrote the automation scripts, debugged template resolution issues, deployed code to production, and iterated on failure handling in real time. The future of DevOps is autonomous.