Google Tag Manager Integration
Learn how to integrate Google Tag Manager (GTM) for advanced tracking flexibility and easier tag management without code deployments.
๐ฏ Why Use Google Tag Manager?โ
Current Setup: Direct GA4 implementation via gtag.js
With GTM: Centralized tag management platform
Benefitsโ
โ
No Code Deployments - Add/modify tags without changing code
โ
Multiple Tools - Manage GA4, ads, heatmaps, A/B testing in one place
โ
Version Control - Track all tag changes
โ
Testing Environment - Preview before publishing
โ
Team Collaboration - Multiple users with permissions
โ
Advanced Triggers - Complex tracking conditions
โ
Data Layer - Structured event data
When to Use GTMโ
Use GTM if you:
- Need to frequently add/modify tracking
- Want to add multiple analytics tools
- Have non-technical team members managing tags
- Need advanced e-commerce tracking
- Want sophisticated trigger conditions
- Need A/B testing or heatmap tools
Stick with gtag.js if you:
- Only use GA4
- Rarely modify tracking
- Prefer simpler implementation
- Have small team/solo developer
- Want minimal page weight
๐ GTM Setup Guideโ
Step 1: Create GTM Accountโ
- Go to Google Tag Manager
- Click Create Account
- Fill in:
- Account Name: 4SCH Documentation
- Country: Nigeria (or your location)
- Container Name: docs.4sch.com
- Target Platform: Web
- Click Create
- Accept Terms of Service
Step 2: Install GTM Containerโ
You'll receive two code snippets:
Head Snippetโ
<!-- 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','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
Body Snippetโ
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
Step 3: Add GTM to Docusaurusโ
Option A: Keep Current GA4 + Add GTM (Recommended for transition)
Add to docusaurus.config.js headTags:
{
tagName: 'script',
innerHTML: `
(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','GTM-XXXXXXX');
`,
},
Add noscript via plugin at end of config:
module.exports.plugins.push(function(context, options) {
return {
name: 'docusaurus-plugin-gtm-noscript',
injectHtmlTags() {
return {
postBodyTags: [
{
tagName: 'noscript',
innerHTML: '<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX" height="0" width="0" style="display:none;visibility:hidden"></iframe>',
},
],
};
},
};
});
Option B: Replace GA4 with GTM (After testing)
- Remove existing GA4 scripts from headTags
- Add GTM snippets as shown above
- Configure GA4 tag inside GTM
๐ท๏ธ Configure Tags in GTMโ
Tag 1: Google Analytics 4โ
Purpose: Replace or supplement direct GA4 implementation
- Tags โ New
- Tag Configuration โ Google Analytics: GA4 Configuration
- Measurement ID:
G-9DY20V8FQD - Configuration Settings:
send_page_view: true
anonymize_ip: true
cookie_flags: SameSite=None;Secure - Triggering: All Pages
- Save and name: "GA4 - Configuration"
Tag 2: GA4 Event - Page Viewโ
Purpose: Track all page views
- Tags โ New
- Tag Configuration โ Google Analytics: GA4 Event
- Configuration Tag: Select "GA4 - Configuration"
- Event Name:
page_view - Triggering: All Pages
- Save as "GA4 - Page View"
Tag 3: GA4 Event - Guide Viewโ
Purpose: Track guide section views
- Tags โ New
- Tag Configuration โ Google Analytics: GA4 Event
- Configuration Tag: GA4 - Configuration
- Event Name:
guide_view - Event Parameters:
- guide_type:
{{Page Path}}(extract with variable) - page_path:
{{Page Path}}
- guide_type:
- Triggering: Custom trigger (Page Path contains
/guides/) - Save as "GA4 - Guide View"
Tag 4: GA4 Event - Search Openโ
Purpose: Track documentation search
- Tag Configuration โ Google Analytics: GA4 Event
- Event Name:
search_open - Event Parameters:
- event_category: engagement
- event_label: documentation_search
- Triggering: Click - Search elements (custom trigger)
- Save as "GA4 - Search Open"
Tag 5: GA4 Event - Code Copyโ
Purpose: Track code snippet copies
- Tag Configuration โ Google Analytics: GA4 Event
- Event Name:
code_copy - Event Parameters:
- event_category: engagement
- event_label: code_snippet_copied
- Triggering: Click - Copy Button (custom trigger)
- Save as "GA4 - Code Copy"
๐๏ธ Create Custom Triggersโ
Trigger 1: Guide Page Viewโ
- Triggers โ New
- Trigger Type: Page View - DOM Ready
- This trigger fires on: Some DOM Ready Events
- Condition: Page Path contains
/guides/ - Save as "Page - Guide View"
Trigger 2: Search Clickโ
- Trigger Type: Click - All Elements
- This trigger fires on: Some Clicks
- Condition:
- Click Element matches CSS selector
.DocSearchOR - Click Element matches CSS selector
[class*="search"]
- Click Element matches CSS selector
- Save as "Click - Search"
Trigger 3: Code Copy Clickโ
- Trigger Type: Click - All Elements
- This trigger fires on: Some Clicks
- Condition:
- Click Element matches CSS selector
button[class*="copy"]OR - Click Element matches CSS selector
.copyButton
- Click Element matches CSS selector
- Save as "Click - Copy Button"
Trigger 4: External Link Clickโ
- Trigger Type: Click - All Elements
- This trigger fires on: Some Clicks
- Condition:
- Click URL does NOT contain
docs.4sch.com - Click Element matches CSS selector
a[href^="http"]
- Click URL does NOT contain
- Save as "Click - External Link"
Trigger 5: Download Clickโ
- Trigger Type: Click - All Elements
- This trigger fires on: Some Clicks
- Condition:
- Click URL contains
/downloadOR - Click Element has attribute
download
- Click URL contains
- Save as "Click - Download"
Trigger 6: Video Playโ
- Trigger Type: YouTube Video
- Capture: Player Progress (25%, 50%, 75%, 100%)
- Add JavaScript API support: Yes
- This trigger fires on: All Videos
- Save as "Video - Play Events"
Trigger 7: Scroll Depthโ
- Trigger Type: Scroll Depth
- Vertical Scroll Depths: 25, 50, 75, 100
- This trigger fires on: All Pages
- Save as "Scroll - Depth Tracking"
๐ฆ Create Variablesโ
Built-in Variablesโ
Enable these in Variables โ Configure:
- โ Page Path
- โ Page URL
- โ Referrer
- โ Click Element
- โ Click URL
- โ Click Text
- โ Form Element
- โ Form ID
- โ Video URL
- โ Video Status
- โ Scroll Depth Threshold
Custom Variablesโ
Variable 1: Guide Typeโ
- Variables โ New โ User-Defined
- Variable Type: Custom JavaScript
- Code:
function() {
var path = {{Page Path}};
if (path.includes('/guides/')) {
var parts = path.split('/');
var guideIndex = parts.indexOf('guides');
return parts[guideIndex + 1] || 'unknown';
}
return 'not_a_guide';
} - Save as "Guide Type"
Variable 2: Documentation Sectionโ
- Variable Type: Custom JavaScript
- Code:
function() {
var path = {{Page Path}};
var sections = ['intro', 'guides', 'reference', 'support'];
for (var i = 0; i < sections.length; i++) {
if (path.includes('/' + sections[i] + '/')) {
return sections[i];
}
}
return 'other';
} - Save as "Documentation Section"
Variable 3: User Type (via Cookie)โ
- Variable Type: 1st Party Cookie
- Cookie Name:
user_role - Save as "User Role Cookie"
๐งช Testing & Debuggingโ
Preview Modeโ
- Click Preview in GTM workspace
- Enter:
http://localhost:3000orhttps://docs.4sch.com - Click Connect
- Tag Assistant opens showing:
- Tags fired
- Tags not fired
- Variables
- Data layer
- Errors
Debug Checklistโ
- โ GTM container loads
- โ GA4 config tag fires on all pages
- โ Page view event fires
- โ Custom events fire on correct triggers
- โ Variables populate correctly
- โ No duplicate events (if using both GTM + direct GA4)
Common Issuesโ
Issue: Tags not firing
Solution: Check trigger conditions, verify CSS selectors
Issue: Duplicate events
Solution: Choose either GTM OR direct implementation, not both
Issue: Variables empty
Solution: Ensure built-in variables are enabled
๐ Data Layer Implementationโ
What is Data Layer?โ
Structured JavaScript object for passing data to GTM:
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'custom_event',
'eventCategory': 'category',
'eventAction': 'action',
'eventLabel': 'label'
});
Enhanced Data Layer for Documentationโ
Add to docusaurus.config.js:
{
tagName: 'script',
innerHTML: `
// Initialize data layer
window.dataLayer = window.dataLayer || [];
// Push page data on load
document.addEventListener('DOMContentLoaded', function() {
var pagePath = window.location.pathname;
var pageData = {
'event': 'page_data_ready',
'page': {
'path': pagePath,
'title': document.title,
'section': getDocSection(pagePath),
'guideType': getGuideType(pagePath)
},
'user': {
'role': getCookie('user_role') || 'unknown',
'newUser': !getCookie('returning_user'),
'sessionNumber': parseInt(getCookie('session_count') || '1')
}
};
dataLayer.push(pageData);
});
function getDocSection(path) {
if (path.includes('/intro/')) return 'intro';
if (path.includes('/guides/')) return 'guides';
if (path.includes('/reference/')) return 'reference';
if (path.includes('/support/')) return 'support';
return 'other';
}
function getGuideType(path) {
if (!path.includes('/guides/')) return null;
var parts = path.split('/');
return parts[parts.indexOf('guides') + 1] || 'unknown';
}
function getCookie(name) {
var value = '; ' + document.cookie;
var parts = value.split('; ' + name + '=');
if (parts.length === 2) return parts.pop().split(';').shift();
}
`,
}
Accessing Data Layer in GTMโ
- Variables โ New
- Variable Type: Data Layer Variable
- Data Layer Variable Name:
page.section - Save as "DL - Page Section"
Repeat for:
page.guideTypeโ "DL - Guide Type"user.roleโ "DL - User Role"user.newUserโ "DL - New User"
๐ง Advanced GTM Featuresโ
Custom HTML Tagsโ
Example: Hotjar Heatmaps
- Tags โ New
- Tag Type: Custom HTML
- HTML:
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script> - Triggering: All Pages
- Save as "Hotjar Tracking"
Tag Sequencingโ
Fire tags in specific order:
- Edit any tag
- Advanced Settings โ Tag Sequencing
- Setup Tag: Select tag to fire before
- Cleanup Tag: Select tag to fire after
Tag Templatesโ
Use community templates:
- Tags โ New
- Discover more tag types in Community Template Gallery
- Search for tools (e.g., "LinkedIn Insight Tag", "Facebook Pixel")
- Add and configure
๐ Migration Plan: gtag.js โ GTMโ
Phase 1: Preparation (Week 1)โ
- Create GTM account and container
- Document current GA4 events
- Set up GTM alongside existing tracking
- Configure GA4 tag in GTM
- Test in Preview mode
Phase 2: Parallel Tracking (Week 2-3)โ
- Deploy GTM to production
- Run both implementations
- Compare data accuracy
- Verify all events tracked
- Fix any discrepancies
Phase 3: Migration (Week 4)โ
- Remove direct GA4 code
- Keep only GTM implementation
- Monitor for 7 days
- Verify data continuity
- Document new setup
Phase 4: Enhancement (Week 5+)โ
- Add additional tools (heatmaps, A/B testing)
- Create advanced triggers
- Implement enhanced data layer
- Train team on GTM
๐ GTM Best Practicesโ
Organizationโ
-
Naming Convention:
Category - Description- Tags:
GA4 - Event - Code Copy - Triggers:
Click - Copy Button - Variables:
DL - User Role
- Tags:
-
Folders: Group related items
- Analytics Tags
- Marketing Tags
- Triggers - Clicks
- Triggers - Page Views
- Variables - Data Layer
- Variables - Custom
-
Version Control
- Name versions clearly: "v1.2 - Added video tracking"
- Add descriptions
- Tag who made changes
Testingโ
- โ Always use Preview mode before publishing
- โ Test on staging environment first
- โ Verify in GA4 Realtime reports
- โ Check for JavaScript errors
- โ Test on multiple devices/browsers
Performanceโ
- โก Minimize custom HTML tags
- โก Use built-in tag types when possible
- โก Avoid synchronous tags
- โก Use tag firing limits for scroll/timer events
- โก Clean up unused tags/triggers/variables
Securityโ
- ๐ Limit GTM user permissions
- ๐ Review tag changes before publishing
- ๐ Avoid exposing sensitive data in data layer
- ๐ Use environment-specific containers for testing
- ๐ Enable 2-factor authentication
๐ Resourcesโ
Internal:
- Analytics Setup:
/reference/analytics-setup - Dashboard Guide:
/reference/ga4-dashboard-guide - Conversions Guide:
/reference/ga4-conversions-funnels
โ Quick Decision Guideโ
Stay with Direct GA4 if:
- โ Only using Google Analytics
- โ Infrequent tracking changes
- โ Small team
- โ Prefer simplicity
Switch to GTM if:
- โ Need multiple tracking tools
- โ Frequent tracking updates
- โ Non-technical team members
- โ Want advanced control
- โ Planning A/B testing
- โ Need marketing pixels
Current recommendation: Continue with direct GA4 implementation unless you need the advanced features GTM provides. Our current setup is working well and covers all documentation analytics needs.
๐ก Next Stepsโ
If you decide to implement GTM:
- Week 1: Create account, set up container, test in Preview
- Week 2: Deploy alongside existing tracking
- Week 3: Verify data accuracy
- Week 4: Remove direct implementation if GTM working well
- Week 5+: Add additional tools and advanced features
Support: Need help with GTM setup? Contact the technical team or refer to this guide.