### Run Local Web Server Source: https://github.com/googleanalytics/ga4-tutorials/blob/main/README.md Use this command to start the local web server. Ensure Deno is installed. ```bash deno task start ``` -------------------------------- ### Run Deno Development Server Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt Installs Deno and starts the development server. Use the --port flag to override the default port. ```bash # Install Deno: https://deno.land # Run from the /src directory (or root with the root deno.json task) denо task start # Override the default port (80) denо task start --port 8000 # Then open http://localhost or http://localhost:8000 ``` -------------------------------- ### Deno HTTP Server Setup Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt Configures a Deno HTTP server to render Eta templates and serve static files. Handles routing and error responses. ```typescript import * as path from "https://deno.land/std@0.224.0/path/mod.ts"; import { Eta } from "https://deno.land/x/eta@v3.0.3/src/index.ts"; import { parseArgs } from "jsr:@std/cli/parse-args"; const __dirname = new URL(".", import.meta.url).pathname; const eta = new Eta({ views: path.join(__dirname, "public"), cache: true }); const flags = parseArgs(Deno.args, { string: ["port"], default: { port: "80" }, }); async function handler(request: Request): Promise { const url = new URL(request.url); let filepath = decodeURIComponent(url.pathname); // Default route → index page if (filepath === "/") { filepath = "/index.eta"; } else if (filepath.toLocaleLowerCase().indexOf(".") <= 0) { // Extensionless paths → try as .eta template filepath = `${filepath}.eta`; } try { if (filepath.indexOf(".eta") > 0) { // Render Eta template return new Response(await eta.render(filepath, {}), { headers: { "content-type": "text/html" }, }); } else { // Serve static file const file = await Deno.open(__dirname + "/public" + filepath, { read: true }); return new Response(file.readable); } } catch (e) { console.error(e); return new Response("404 Not Found", { status: 404 }); } } Deno.serve({ port: parseInt(flags.port) }, handler); // Server starts on http://localhost: ``` -------------------------------- ### Fetch and Display GA4 Debug Information Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt This JavaScript retrieves GA4 internal values like tag ID, client ID, and session ID using `gtag('get')` and displays them. It also includes functionality to clear all GA4 cookies and reload the page to simulate a fresh session. ```javascript function setIds() { // Find the active GA4 measurement ID (format: G-XXXXXXXXXX) via GTM const gtagIds = Object.keys(window.google_tag_manager || []) .filter(e => e.substring(0, 2) === 'G-'); if (gtagIds.length > 0) { const firstTagId = gtagIds[0]; // e.g. "G-ABC123XYZ" Promise.all([ firstTagId, localStorage.getItem('userId'), // gtag('get') is async – wrap in Promise to use with Promise.all new Promise(cid => gtag('get', firstTagId, 'client_id', cid)), new Promise(sid => gtag('get', firstTagId, 'session_id', sid)), ]).then(([tagId, userId, clientId, sessionId]) => { document.getElementById('tag-id').value = tagId; document.getElementById('user-id').value = userId; document.getElementById('client-id').value = clientId; document.getElementById('session-id').value = sessionId; // Expected console output: // { // "user_id": "effortlessly-482910374821", // "client_id": "1234567890.0987654321", // "session_id": "1716201234" // } console.log(JSON.stringify({ user_id: userId, client_id: clientId, session_id: sessionId }, null, ' ')); }); } } // Clear all GA4 cookies and reload (resets client_id / session_id) function clearCookies() { document.cookie.split('; ') .map(c => c.split('=')[0]) .forEach(name => { document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; }); location.reload(); } document.getElementById('btn-fetch').addEventListener('click', setIds); document.getElementById('btn-clear').addEventListener('click', clearCookies); // Auto-populate when the Bootstrap collapse panel opens document.getElementById('debug-panel').addEventListener('shown.bs.collapse', () => setIds()); ``` -------------------------------- ### Initialize GTM and GA4 with Consent Defaults Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt This script initializes the dataLayer, sets default consent settings for GA4 before GTM loads, and pushes the user ID if available. Ensure consent defaults are set before GTM loads for GA4 to respect them. ```html ``` -------------------------------- ### Run Local Web Server on a Specific Port Source: https://github.com/googleanalytics/ga4-tutorials/blob/main/README.md Override the default port (80) by using the --port argument. This is useful if port 80 is already in use. ```bash deno task start --port 8000 ``` -------------------------------- ### Render Eta Page Template with Layout and Partials Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt This template defines a parent layout and includes navigation and footer partials. It passes a title to the layout and renders a form for user role selection. ```html <%-- Any page template --%>\n<% layout("./layouts/layout", { title: "Profile - GA Tutorials" }) %>\n\n<%~ include("./partials/nav") %>\n\n
\n

Choose your role:

\n
\n \n \n
\n
\n\n<%~ include("./partials/footer.eta") %>\n\n<%--\n Layout variables:\n it.title – HTML and page heading\n it.body – rendered page body injected via <%~ it.body %>\n\n Available partials:\n ./partials/nav – top navigation bar\n ./partials/footer – footer with newsletter form\n ./partials/consent – cookie consent banner + setConsent() logic\n ./partials/debug – collapsible GA4 debug panel\n--%> ``` -------------------------------- ### Implement Cookie Consent Banner Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt This HTML and JavaScript code implements a cookie consent banner that appears on the first visit. It allows users to accept all, accept selected, or reject all cookies, updating GA4 consent settings and persisting the choice in localStorage. ```html <!-- HTML: rendered only when consentMode is not set --> <div id="cookie-consent-banner" class="cookie-consent-banner"> <h3>Cookie settings</h3> <button id="btn-accept-all" class="cookie-consent-button btn-success">Accept All</button> <button id="btn-accept-some" class="cookie-consent-button btn-outline">Accept Selection</button> <button id="btn-reject-all" class="cookie-consent-button btn-grayscale">Reject All</button> <div class="cookie-consent-options"> <label><input id="consent-necessary" type="checkbox" checked disabled> Necessary</label> <label><input id="consent-analytics" type="checkbox" checked> Analytics</label> <label><input id="consent-preferences" type="checkbox" checked> Preferences</label> <label><input id="consent-marketing" type="checkbox"> Marketing</label> </div> </div> <script> function hideBanner() { document.getElementById('cookie-consent-banner').style.display = 'none'; } // Maps UI checkboxes → GA4 consent type keys function setConsent(consent) { const consentMode = { 'functionality_storage': consent.necessary ? 'granted' : 'denied', 'security_storage': consent.necessary ? 'granted' : 'denied', 'ad_storage': consent.marketing ? 'granted' : 'denied', 'analytics_storage': consent.analytics ? 'granted' : 'denied', 'personalization_storage': consent.preferences ? 'granted' : 'denied', }; gtag('consent', 'update', consentMode); // notify GA4 localStorage.setItem('consentMode', JSON.stringify(consentMode)); // persist } if (localStorage.getItem('consentMode') === null) { // Wire up buttons only on first visit document.getElementById('btn-accept-all').addEventListener('click', () => { setConsent({ necessary: true, analytics: true, preferences: true, marketing: true }); hideBanner(); }); document.getElementById('btn-accept-some').addEventListener('click', () => { setConsent({ necessary: true, analytics: document.getElementById('consent-analytics').checked, preferences: document.getElementById('consent-preferences').checked, marketing: document.getElementById('consent-marketing').checked, }); hideBanner(); }); document.getElementById('btn-reject-all').addEventListener('click', () => { setConsent({ necessary: false, analytics: false, preferences: false, marketing: false }); hideBanner(); }); document.getElementById('cookie-consent-banner').style.display = 'block'; } </script> ``` -------------------------------- ### Simulate User Login with Persistent User ID Source: https://context7.com/googleanalytics/ga4-tutorials/llms.txt Use this JavaScript to store a user ID in localStorage, allowing it to persist across sessions. This ID is then pushed to dataLayer on subsequent page loads. It also includes functions to clear the ID (logout) and generate a random ID for testing. ```html <script> // Persist a user_id that layout.eta will push to dataLayer on every page function loginUserId(userId) { localStorage.setItem('userId', userId); // On the next page load, layout.eta will execute: // window.dataLayer.push({ 'user_id': userId }); } // Remove the stored user_id (simulates logout) function logout(userIdField) { localStorage.removeItem('userId'); userIdField.value = null; } // Generate a random human-readable ID for demo purposes function generateUserId(userField) { const prefixes = ['doubloons', 'oceanographer', 'retrogressed', 'effortlessly', /* … */]; const randIndex = Math.floor(Math.random() * prefixes.length); const randId = Math.floor(Math.random() * 1_000_000_000_000); userField.value = prefixes[randIndex] + '-' + randId; // Example output: "effortlessly-482910374821" } // Event wiring document.getElementById('btn-login').addEventListener('click', () => loginUserId(document.getElementById('user').value)); document.getElementById('btn-logout').addEventListener('click', () => logout(document.getElementById('user'))); document.getElementById('gen-id').addEventListener('click', () => generateUserId(document.getElementById('user'))); // Restore stored ID on page load window.onload = () => document.getElementById('user').value = localStorage.getItem('userId'); </script> ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.