Set up Google Tag Manager
Set up Google Tag Manager for webpages by following Google's "set up and install" steps in the following video.
Add Google Tag Manager code to Layout Editor pages
This section is applicable to customers using Layout Editor pages or other custom pages that use Vanilla’s single-page application navigation.
Why this is needed
Vanilla renders custom pages using client-side navigation. When a user moves between two Layout Editor pages or other custom/layout pages, there may be no full page reload. Instead, navigation happens through the app router.
Because of this:
- page view tracking that only runs on initial page load may miss later page changes
- older Google Analytics implementations may undercount page views on custom pages
- customer-added snippets in Pockets or Custom HTML will usually only fire on full page loads unless they are explicitly tied to Vanilla’s SPA lifecycle
To support page view tracking on both full page loads and client-side transitions, Vanilla exposes:
window.onPageView(handler)
This hook fires on:
- the initial page load
- supported SPA page transitions
Recommended solution for Layout Editor pages
Use window.onPageView() to send page view events whenever the page changes.
Add the following script where your Layout Editor custom code is loaded:
Navigate to:
- Settings
- Appearance
- Style-guides
- select your current style-guide and then Edit
- Select the Javascript Tab
- Scroll to the bottom and add the OnVanillaReady() script below
onVanillaReady(() => {
window.onPageView(function () {
const startTitle = document.title;
const startUrl = window.location.href;
const maxWaitMs = 1000;
const intervalMs = 50;
const startedAt = Date.now();
const sendPageView = () => {
const payload = {
event: "page_view",
page_location: window.location.href,
page_title: document.title,
};
if (typeof window.gtag === "function") {
window.gtag("event", "page_view", {
page_location: payload.page_location,
page_title: payload.page_title,
});
} else {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push(payload);
}
console.log("[page_view tracked]", payload);
};
const timer = setInterval(() => {
const titleChanged = document.title !== startTitle;
const urlChanged = window.location.href !== startUrl;
const timedOut = Date.now() - startedAt >= maxWaitMs;
if (titleChanged || timedOut) {
clearInterval(timer);
sendPageView();
}
}, intervalMs);
});
});
What this script does
When window.onPageView() fires, the script does not send the page view immediately. Instead, it captures the current page title and URL, then starts a short polling loop that checks every 50 milliseconds to see whether the page title has updated. It does this because on some Vanilla pages, the URL changes first and document.title updates a moment later.
The polling stops when either:
- the page title changes, or
- 1 second passes
At that point, it sends a page view event using the most current values for:
If Google’s gtag() function is available, it sends the event directly to GA4 with gtag('event', 'page_view', ...).
If gtag() is not available, it falls back to pushing a page_view event into window.dataLayer, which allows Google Tag Manager to process it instead.
Finally, it logs the tracked payload to the console so you can verify what was sent.
This ensures page views are recorded for both:
- full page loads
- client-side navigation between Layout Editor/custom pages
Important notes
console.log('[page_view tracked]', payload); // can be removed after confirmation its working
- This script assumes Google Analytics has already been loaded on the page.
- If page view tracking is already being sent elsewhere, adding this snippet may create duplicate page views.
- If a customer reports undercounted page views specifically on custom or Layout Editor pages, this is the recommended supported solution.
Test Layout Editor page view tracking
- Open a Layout Editor page in your community.
- Open your browser’s developer tools.
- click on 'Console'
The script will load on initial refresh of the page. This should be tracked via GA normally. Now click on a link within a Custom layout editor page. You should see a
[Page_view tracked] message with the data sent to GTM
If not use the following script below:
Use the following snippet in the browser console to verify that window.onPageView() is firing correctly on page transitions. This should provide some information on what might be missing.
This version logs page view events to the console and also sends a GA4 page_view event if gtag() is available.
(function testVanillaPageViews() {
if (typeof window.onPageView !== 'function') {
console.error('window.onPageView is not available on this page.');
return;
}
window.onPageView(function () {
console.log('[Vanilla onPageView fired]');
console.log('URL:', window.location.href);
console.log('Title:', document.title);
console.log('Timestamp:', new Date().toISOString());
if (typeof window.gtag === 'function') {
window.gtag('event', 'page_view', {
page_location: window.location.href,
page_title: document.title
});
console.log('[GA4 page_view sent]');
} else {
console.warn('gtag is not defined, so no GA4 event was sent.');
}
});
console.log('Vanilla page view test hook registered.');
})();
Test steps
- Open a Layout Editor page in your community.
- Open your browser’s developer tools.
- Paste the script above into the console and run it.
- Navigate between Layout Editor pages or other custom pages.
- Confirm that console messages appear for each page transition.
If the hook is working, you should see a new console log entry each time the page changes.
Add Google Tag Manager code to Standard Foundation theme
The information in this section is applicable to Foundation themes and those looking to measure Google Analytics activity in the Vanilla KB.
You will have to add two snippets of code from Google. Let's add them to Vanilla now!
Google Tag Manager gives you:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','yourGTM_ID');</script>
<!-- End Google Tag Manager -->
...and:
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=yourGTM_ID"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
NOTE: This second block, with the iframe (<!-- Google Tag Manager (noscript) -->), is for when someone (or a bot) browses your site and does not have JavaScript.
The first block is doing two things:
- Injecting a script tag that calls the URL
https://www.googletagmanager.com/gtm.js?id=[yourGTM_ID]. - Adding
{'gtm.start':new Date().getTime(),event:'gtm.js'} to a browser object known as window['dataLayer'].
You will have to format it so that it can be executed by the Foundation theming engine without violating our Content Security Policy.
1. Open Theme Editor and click the Edit button.
2. Add the JavaScript code to be placed in the <head> in the JavaScript tab.
/**
* Get the current nonce from scripts in the head.
**/
const getNonce = () => {
const scripts = document.querySelectorAll('script');
for (let i = 0; i < scripts.length; i++) {
if (scripts[i].nonce) {
return scripts[i].nonce;
}
}
console.warn('Failed to retrieve a nonce. Check to see if your scripts work.');
};
// Get the nonce value that Vanilla is putting on scripts on this page.
const NONCE = document.querySelector('script')?.nonce ?? getNonce();
// Create a script tag to embed the Google Script in the head of the page.
const injectGTMFile = (validUrl) => {
const head = document.querySelector('head');
const scriptTag = document.createElement('script');
scriptTag.setAttribute('nonce', NONCE);
scriptTag.async = true;
scriptTag.src = (validUrl) ? validUrl : '';
head.appendChild(scriptTag);
}
onVanillaReady(() => {
// Put a script tag in the head of the document with tag manager Id attached to it.
injectGTMFile('https://www.googletagmanager.com/gtm.js?id=[yourGTM_ID]');
window.addEventListener('load', () => {
// Once the window is loaded, get the dataLayer and do the push function to attach GTM magic.
const dataLayer = window['dataLayer']||window.dataLayer;
dataLayer.push({'gtm.start': new Date().getTime(), event:'gtm.js'});
});
});
3. Add the <noscript> portion of the snippet to the Header tab of your Foundation theme.
4. Click Save.
5. Navigate to the Technical > Security tab to ensure Google Analytics traffic can be read.
6. Add the following in the Content Security Domains field.
*.googletagmanager.com*.google-analytics.com
as shown below:
7. Go to Google Tag Assistant and run the debug to make sure things are working as expected.
NOTE: Foundation must be the theme used for mobile theme; otherwise, mobile traffic will not be measured, unless this code has been separately added to the mobile theme.
Add Google Tag Manager code to non-Foundation theme
The information in this section is applicable only to non-Foundation themes.
You will have to create two Pockets in order to add the two snippets of code from Google.
NOTE: Pockets is a legacy feature of Vanilla communities and is available on legacy non-Foundation themes only. The Pockets feature is not enabled by default. To have the feature enabled, contact Vanilla Support.
First Pocket
The Pocket houses the Google Tag Manager code for the Head area.
1. Slide the toggle to the right to enable the Pocket.
2. Give the Pocket a memorable Name and:
- Body - paste Google Tag Manager code from part one
- Page - select (All)
- Location - select Head
- Repeat - select Before
3. Click Save.
Second Pocket
The Pocket houses the secondary Google Tag Manager code for the Content area.
1. Slide the toggle to the right to enable the Pocket.
2. Give the Pocket a memorable Name and:
- Body - paste Google Tag Manager code from part two
- Page - select (All)
- Location - select Content
- Repeat - select Before
3. Click Save.
Add Universal Analytics
Now you're ready to add Google Universal Analytics tags in your Google Tag Manager.