// @requirements REQ-GOOGLE-MODE REQ-PRODUCT-MOBILE REQ-PRODUCT-A11Y import {readFile} from 'node:fs/promises'; import {compileLegalDocuments} from 'notabenda/content'; import {renderLegalLinks} from 'notabenda'; import {exampleConsentConfig} from '../static/choices-build.mjs'; export async function googleBasicFiles(base){ const config=exampleConsentConfig(base);config.site.id='juniper-google-basic';const necessaryPurposes=new Set(config.services.filter(s=>s.id==='privacy-choices').flatMap(s=>s.purposeIds));config.purposes=config.purposes.filter(p=>p.id==='measurement'||necessaryPurposes.has(p.id));config.services=config.services.filter(s=>s.id==='privacy-choices');config.storage=config.storage.filter(s=>s.serviceId==='privacy-choices');for(const item of config.storage)item.name=item.name.replace('juniper-choices',config.site.id); config.services.push({id:'google-measurement',name:'Site measurement',provider:'Google',location:'Operator-reviewed Google destinations',purposeIds:['measurement'],resourceOrigins:['https://www.googletagmanager.com'],processingActivities:[],googleBasic:{version:1,tagIds:['G-DEMO0000'],signals:{analytics_storage:['measurement'],ad_storage:[],ad_user_data:[],ad_personalization:[]}}});config.consent.purposes=[{id:'measurement',scope:'google-measurement-1'}];config.consent.services=[{id:'google-measurement',scope:'google-tag-1'}];config.scopeGuards={version:1,revision:'ordinary-measurement-1',site:{children:'absent',sensitiveData:'absent',highRiskProfiling:'absent',regulatedSector:'absent'}}; const files={'assets/google-basic.mjs':await readFile(new URL('./client.mjs',import.meta.url),'utf8'),'assets/google-basic.css':await readFile(new URL('./style.css',import.meta.url),'utf8')}; for(const dark of [false,true]){const prefix=dark?'dark/':'',themed=structuredClone(config);for(const [kind,document] of Object.entries(themed.documents))document.route='/'+prefix+'google-basic/'+kind;const build=compileLegalDocuments(themed,{mode:'preview',stylesheetUrl:dark?'/assets/dark.css':'/assets/notabenda.css'});Object.assign(files,Object.fromEntries(Object.entries(build.files).filter(([path])=>path.startsWith('artifacts/')||path.startsWith(prefix+'google-basic/'))));files[prefix+'google-basic/site.json']=JSON.stringify(build.publicConfig); files[prefix+'google-basic/index.html']=`Google Basic Consent Mode simulator · Juniper Notes
Juniper Notes

Notabenda · Google Basic · Local simulator

Google Basic
Consent Mode

Optional measurement waits for your choice. See the consent commands in order, with no live Google tag or account connected.

01 / AT YOUR DISCRETION

Tags wait for permission

Preparing the local example…

Tag state
Blocked
Simulated starts
0
Simulated page views
0

After a tag-loading attempt, withdrawal closes this adapter until reload. Removing a real script cannot undo code that has already run.

${dark?'Light':'Midnight'} theme ↗

02 / THE FOUR SIGNALS

Consent signal mapping

${['analytics_storage','ad_storage','ad_user_data','ad_personalization'].map(type=>`
${type}
Denied
`).join('')}

Only measurement is mapped in this example. Advertising signals remain denied. A combined measurement/advertising service would wait for all of its declared purposes.

03 / THE COMMAND TRAIL

Adapter event log

Commands stay local here. The real browser adapter inserts the Google tag only after effective permission, including any required receipt and independent processing restrictions.

  1. Waiting for the local controller.
What this example proves

It exercises the actual adapter with a local execution port. It does not load Google's library or verify vendor behavior. Automated interception checks separately cover the real browser loader URL. Neither a working adapter nor Consent Mode is Google CMP certification.

Integration guide ↗
`; }return files; }