The easiest way to add Google Analytics 4 to WeWeb is through the native Google Tag Manager plugin (Plugins → Extensions → Google Tag Manager, enter your GTM Container ID). GTM then manages GA4 tracking including SPA page views, which require a custom GTM trigger since WeWeb navigation does not fire standard pageview events. Setup takes about 20 minutes.
Google Analytics 4 Tracking in WeWeb
WeWeb generates Vue.js single-page applications (SPAs). In a SPA, page navigation does not trigger browser full-page reloads — the URL changes via JavaScript's History API but no new HTML document is fetched. This breaks standard Google Analytics page tracking, which relies on detecting page loads. WeWeb solves this with a native Google Tag Manager plugin. GTM is injected once, and you configure it to detect WeWeb's SPA navigation events and fire GA4 page_view events accordingly. This tutorial walks through the GTM plugin setup, GA4 configuration inside GTM, SPA history tracking, custom event pushing from WeWeb workflows, and how to test that everything works before going live.
Prerequisites
- A WeWeb project open in the editor (Free plan or above)
- A Google Tag Manager account with a container created (tagmanager.google.com — free)
- A Google Analytics 4 property created in Google Analytics (analytics.google.com — free)
- Your GTM Container ID (format: GTM-XXXXXXX) and GA4 Measurement ID (format: G-XXXXXXXXXX)
Step-by-step guide
Install the Google Tag Manager plugin in WeWeb
Install the Google Tag Manager plugin in WeWeb
In the WeWeb editor, click the plug icon in the left sidebar to open the Plugins panel. Under the 'Extensions' section, find 'Google Tag Manager' and click Add. In the plugin configuration dialog, enter your GTM Container ID in the 'Container ID' field — it looks like GTM-XXXXXXX. You can optionally enter separate Container IDs for different environments (Editor, Staging, Production) if you use multiple GTM containers. Click Save. WeWeb will inject the GTM snippet (`<script>` in the head and `<noscript>` in the body) into every page of your application automatically. You do not need to add any code manually to App Settings → Custom Code.
Expected result: Google Tag Manager plugin appears in Plugins → Extensions with a green active indicator. Your GTM container ID is visible in the plugin config.
Connect GA4 to your GTM container
Connect GA4 to your GTM container
Open Google Tag Manager (tagmanager.google.com) and go to your container. Click 'Tags' in the left sidebar → 'New'. Name the tag 'GA4 Configuration'. Click 'Tag Configuration' → 'Google Tag' (the newer recommended tag type that replaces the old GA4 Configuration tag). Enter your GA4 Measurement ID (G-XXXXXXXXXX). Under 'Triggering', click the '+' button. Select 'Initialization - All Pages' as the trigger — this fires the tag on every page load including SPA navigation when combined with the history change trigger in the next step. Click Save. This tag establishes the GA4 connection and initializes the gtag.js tracker for all subsequent events.
Expected result: A GA4 Google Tag appears in your GTM workspace configured with your Measurement ID and the Initialization trigger.
Configure SPA page view tracking with a History Change trigger
Configure SPA page view tracking with a History Change trigger
WeWeb navigation changes the browser URL without a full page reload, so the 'All Pages' trigger only fires once when the app first loads. To track every SPA page view, you need a GTM History Change trigger. In GTM, click 'Triggers' → 'New'. Name it 'History Change - SPA Navigation'. Under 'Trigger Type', select 'History Change'. Leave all conditions as default (fire on all history changes). Click Save. Now go back to your GA4 tag → edit it → under 'Triggering' click '+' again and add this History Change trigger alongside the existing Initialization trigger. This means GA4 fires once on first load AND every time the WeWeb app navigates between pages. Click Save. Publish your GTM container by clicking 'Submit' in the top right.
Expected result: GTM workspace shows the History Change trigger assigned to the GA4 tag. GA4 now fires on every WeWeb page navigation.
Push custom events to GTM dataLayer from WeWeb workflows
Push custom events to GTM dataLayer from WeWeb workflows
WeWeb has a native GTM action in workflows: 'GTM - Push dataLayer event'. This action sends custom event data to GTM's dataLayer, which GTM can then use to fire GA4 custom events. Select any element in WeWeb that you want to track — a sign-up button, a video play, a form submit. Open its workflow (Workflows tab). Add a new action, search for 'GTM' and select 'GTM - Push dataLayer event'. Fill in the Event name (use GA4 naming convention: lowercase_with_underscores, e.g. `sign_up_button_click`). Add parameters as key-value pairs: `button_location` mapped to the page name (`wwPage.name`), `user_type` mapped to whether the user is logged in. In GTM, create a corresponding Custom Event trigger on the event name, and a GA4 Event tag that fires on that trigger.
1// GTM dataLayer push (for reference — WeWeb uses the built-in GTM action)2// This is what the 'GTM - Push dataLayer event' action sends3// Injection point: Workflow → GTM - Push dataLayer event action4// (You configure this through the WeWeb action UI, not raw code)56// What gets pushed to window.dataLayer:7{8 "event": "sign_up_button_click",9 "button_location": "hero_section",10 "page_name": "{{wwPage.name}}",11 "user_logged_in": false12}1314// Alternatively, for manual injection in a Custom JavaScript workflow action:15// Injection point: Workflow → Custom JavaScript action16window.dataLayer = window.dataLayer || [];17window.dataLayer.push({18 event: 'form_submit',19 form_id: 'contact_form',20 form_source: wwPage ? wwPage.name : 'unknown',21 submission_value: formData ? formData.planTier : 'unknown'22});23return { pushed: true };Expected result: Custom events from WeWeb workflows appear in GA4 Real-Time reports and DebugView after the GTM trigger and tag are configured.
Verify tracking with GTM Preview mode and Tag Assistant
Verify tracking with GTM Preview mode and Tag Assistant
Before going live, verify your tracking setup works. In GTM, click 'Preview' in the top right. A new browser tab opens with your WeWeb app URL in a GTM debug overlay. Navigate through your app — you should see each tag fire in the GTM debug panel at the bottom of the screen. Confirm the 'GA4 Configuration - Google Tag' fires on initialization and on each History Change. Click your tracked elements to verify custom events fire. For GA4 verification, open Google Analytics → Configure → DebugView. If you have the Google Tag Assistant extension installed in Chrome, it shows a badge on your site with tag status. You can also check GA4 Real-Time reports within 30 seconds of page visits — look for active users and events. If GA4 is not receiving data, check that your GTM container is published (not just saved) and that WeWeb is also published.
Expected result: GTM Preview shows the GA4 tag firing on page load and History Change events. GA4 DebugView shows real-time events.
Alternative: Add GA4 directly via Custom Code Head injection
Alternative: Add GA4 directly via Custom Code Head injection
If you prefer to skip GTM and add GA4 directly, go to App Settings (gear icon) → Custom Code → Head section. Paste the GA4 global site tag (gtag.js) code block. Replace G-XXXXXXXXXX with your GA4 Measurement ID. For SPA navigation tracking without GTM, add a custom script that listens to history state changes using the History API's popstate event and calls gtag('event', 'page_view', ...) manually. This method works but is harder to maintain than the GTM approach — any time you want to change tracking, you need to edit code and republish WeWeb. GTM is preferred for most use cases because you can change tags in GTM without touching WeWeb.
1<!-- Injection point: App Settings → Custom Code → Head -->2<!-- Replace G-XXXXXXXXXX with your GA4 Measurement ID -->34<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>5<script>6 window.dataLayer = window.dataLayer || [];7 function gtag(){ dataLayer.push(arguments); }8 gtag('js', new Date());9 gtag('config', 'G-XXXXXXXXXX', {10 send_page_view: false // Disable auto pageview — we handle it manually below11 });1213 // SPA navigation tracking for WeWeb14 // Fires a page_view event on every URL change15 let lastPath = '';1617 function trackPageView() {18 const currentPath = window.location.pathname + window.location.search;19 if (currentPath !== lastPath) {20 lastPath = currentPath;21 gtag('event', 'page_view', {22 page_location: window.location.href,23 page_path: window.location.pathname,24 page_title: document.title25 });26 }27 }2829 // Listen for Vue Router history changes30 window.addEventListener('popstate', trackPageView);3132 // Also patch pushState for programmatic navigation33 const originalPushState = history.pushState;34 history.pushState = function() {35 originalPushState.apply(this, arguments);36 trackPageView();37 };3839 // Track initial page load40 document.addEventListener('DOMContentLoaded', trackPageView);41</script>Expected result: GA4 Real-Time reports show page_view events firing for each WeWeb page navigation without using GTM.
Add cookie consent integration for GDPR compliance
Add cookie consent integration for GDPR compliance
If your app has users in the EU, you need a cookie consent mechanism before loading analytics. WeWeb has a Privacy & Consent settings section (App Settings → Privacy & Consent) where you can configure a basic consent banner. For more robust consent management, use a third-party Consent Management Platform (CMP) like Cookiebot or OneTrust. In GTM, configure 'Consent Mode v2' by adding a default consent state tag that fires before all other tags: set analytics_storage to 'denied' by default, then update to 'granted' when the user accepts. This is required for GA4 to comply with EU ePrivacy regulations. The GTM consent mode approach is more reliable than building consent logic directly in WeWeb workflows.
Expected result: Analytics only loads after user consent, and GTM Consent Mode sends consent state signals to GA4 for compliant data collection.
Complete working example
1<!-- Injection point: App Settings → Custom Code → Head -->2<!-- Full GA4 SPA tracking implementation for WeWeb (alternative to GTM plugin) -->3<!-- Replace both instances of G-XXXXXXXXXX with your GA4 Measurement ID -->45<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>6<script>7 // Initialize dataLayer and gtag8 window.dataLayer = window.dataLayer || [];9 function gtag() { dataLayer.push(arguments); }10 gtag('js', new Date());1112 // Configure GA4 with consent mode defaults (GDPR-friendly)13 gtag('consent', 'default', {14 analytics_storage: 'denied', // Default: denied until user consents15 ad_storage: 'denied',16 wait_for_update: 50017 });1819 gtag('config', 'G-XXXXXXXXXX', {20 send_page_view: false, // Manual SPA page view tracking below21 debug_mode: false // Set to true during development22 });2324 // SPA page view tracking for WeWeb Vue.js navigation25 (function() {26 let lastTrackedPath = '';2728 function sendPageView() {29 const path = window.location.pathname + window.location.search;30 if (path === lastTrackedPath) return;31 lastTrackedPath = path;3233 gtag('event', 'page_view', {34 page_location: window.location.href,35 page_path: window.location.pathname,36 page_title: document.title,37 page_referrer: document.referrer38 });39 }4041 // Track initial load42 window.addEventListener('load', sendPageView);4344 // Track back/forward navigation45 window.addEventListener('popstate', sendPageView);4647 // Intercept pushState (Vue Router uses this for navigation)48 const _pushState = history.pushState.bind(history);49 history.pushState = function(state, title, url) {50 _pushState(state, title, url);51 setTimeout(sendPageView, 100); // Small delay for page title update52 };5354 // Intercept replaceState55 const _replaceState = history.replaceState.bind(history);56 history.replaceState = function(state, title, url) {57 _replaceState(state, title, url);58 };5960 // Helper for custom events from WeWeb workflows61 // Call: window.trackEvent('button_click', { button: 'signup_hero' })62 window.trackEvent = function(eventName, params) {63 gtag('event', eventName, params || {});64 };65 })();66</script>Common mistakes
Why it's a problem: Not publishing the GTM container after making tag/trigger changes
How to avoid: GTM changes only take effect after you click Submit → Publish in GTM. Saving a tag in GTM does not deploy it. After publishing GTM, you do not need to republish WeWeb for GTM tag changes — only the initial GTM snippet installation requires WeWeb to be published.
Why it's a problem: Using 'All Pages' trigger only, which fires just once on SPA initial load and misses subsequent navigation
How to avoid: Add a 'History Change' trigger to your GA4 tag in GTM alongside the Initialization trigger. This fires on every WeWeb page navigation. Without it, GA4 only records the first page view and misses all subsequent navigation.
Why it's a problem: Double-counting page views by having both the GTM plugin and a manual GA4 script in Custom Code Head
How to avoid: Use only one method: either the GTM plugin OR the Custom Code Head injection. Never both. If you have both, GA4 will receive two page_view events for every page navigation.
Why it's a problem: Not testing with GTM Preview mode before publishing, leading to silent tracking failures
How to avoid: Always click Preview in GTM before Submit/Publish. GTM Preview shows exactly which tags fired on which events. If a tag does not fire, the debug panel shows which triggers were evaluated and why they did not match.
Best practices
- Use the GTM plugin rather than direct GA4 head injection — GTM lets you update tracking without republishing WeWeb
- Always use GTM Preview mode to validate tags fire before publishing the GTM container to production
- Configure Consent Mode v2 in GTM for EU/GDPR compliance — set analytics_storage to denied by default and update to granted after user consent
- Use GA4 naming conventions for custom events: lowercase with underscores, descriptive verb-noun format (e.g., form_submit, video_play, signup_complete)
- Set up GA4 Conversions for your most important events (signup_complete, purchase, form_submit) so they appear in Conversion reports
- Test GA4 tracking in GA4 DebugView (Admin → DebugView) — it shows real-time events with full parameter details during testing
- Use the Segment plugin as an alternative to GTM if you want a customer data platform — Segment routes events to GA4, Mixpanel, Amplitude, and 300+ other tools from a single integration
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I have a WeWeb SPA app and want to track page views and custom events in Google Analytics 4. I'm using Google Tag Manager. Explain how to configure GTM to track SPA navigation (History Change trigger) and how to set up a custom event tag for button clicks coming from WeWeb's dataLayer push.
In WeWeb, I have the Google Tag Manager plugin installed with my Container ID. I want to track when users click a specific 'Start Free Trial' button and send this as a custom event to GA4. What workflow action should I add to the button's On click workflow, what event name and parameters should I use, and how do I configure the corresponding GTM tag and trigger?
Frequently asked questions
Why does GA4 only show one page view per session in my WeWeb app?
This is the classic SPA tracking problem. WeWeb navigation does not trigger browser page reloads, so the standard 'All Pages' GA4 trigger only fires once. You need a GTM History Change trigger (or equivalent) assigned to your GA4 tag. In GTM, create a new trigger with type 'History Change' and assign it to your GA4 tag alongside the Initialization trigger. This fires GA4 on every WeWeb page navigation.
Does WeWeb's GTM plugin support separate GTM containers for development and production?
Yes. In the GTM plugin configuration (Plugins → Extensions → Google Tag Manager → Edit), you can enter different Container IDs for the Editor, Staging, and Production environments. This lets you test new tags in a development GTM container without affecting production analytics data.
Can I use Google Analytics Universal Analytics (UA) instead of GA4 in WeWeb?
Universal Analytics was shut down in July 2024. All new tracking must use Google Analytics 4. If you have an old UA property, you need to create a new GA4 property in Google Analytics and reconfigure your GTM tags to use the GA4 Measurement ID (G-XXXXXXXXXX format) instead of the old UA Tracking ID (UA-XXXXXXXXX-X format).
How do I track conversions like form submissions and sign-ups in GA4 via WeWeb?
In your WeWeb workflow, add a 'GTM - Push dataLayer event' action after a successful form submission with an event name like 'form_submit' and relevant parameters. In GTM, create a Custom Event trigger on 'form_submit' and a GA4 Event tag that fires on it. Then in GA4 Admin → Events, find your 'form_submit' event and click the star icon to mark it as a Conversion. GA4 Conversion reports will then track these events separately with conversion rate metrics.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation