Google Analytics 4 integration takes under two minutes through the JekCMS settings panel. Custom events — scroll depth, content engagement, search queries, and download tracking — require additional configuration. This tutorial shows the exact dataLayer calls we use on jekcms.com.
After entering your GA4 Measurement ID in Settings › Analytics, JekCMS injects the gtag.js snippet and a basic page-view event automatically. The snippet placement is before the closing </head> tag, which is the correct position for GA4. Custom events — anything beyond page views — require either additional JavaScript in your theme's functions.php or a Google Tag Manager container.
Scroll Depth: A Better Bounce Signal
Scroll depth tracking fires at 25%, 50%, 75%, and 100% milestones for each article page. The event name is scroll_depth with a depth integer parameter. In GA4, create a custom dimension for depth to see it in reports. This metric is more meaningful than bounce rate for content sites: a reader who scrolls to 75% and then leaves has engaged substantively, while one who scrolls 10% and leaves has not.
Two-Dimensional Engagement: Time × Scroll
Content engagement events fire at 30, 60, 120, and 300 seconds of active time on an article page. These events — combined with scroll depth data — furnish a two-dimensional engagement signal. A reader at 300 seconds and 100% scroll depth has read the article; a reader at 30 seconds and 25% scroll depth has not. Segment your GA4 audiences by these combinations to understand content effectiveness without relying on page view counts alone.
Importing the GTM Container
The GTM container export included with the JekCMS documentation contains 14 tags, 9 triggers, and 6 variables covering the standard event set. Import it into your GTM workspace from the Admin panel using the "Import Container" function. Update the GA4 configuration tag with your Measurement ID. No modifications to JekCMS or your theme are required — the container reads from the window.dataLayer object that JekCMS populates on every page.
Implementing Custom dataLayer Events
JekCMS populates the dataLayer with page metadata on every load. To push custom events, add JavaScript to your theme's footer partial or use the jekcms_footer hook:
// Track scroll depth milestones
const milestones = [25, 50, 75, 100];
let fired = new Set();
window.addEventListener('scroll', function() {
const scrollPercent = Math.round(
(window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100
);
milestones.forEach(function(m) {
if (scrollPercent >= m && !fired.has(m)) {
fired.add(m);
window.dataLayer.push({
event: 'scroll_depth',
depth: m,
page_type: document.body.dataset.pageType
});
}
});
});
The page_type parameter lets you segment scroll depth by content type in GA4 reports. Articles typically see 45-65% of readers reaching the 75% milestone, while category pages see only 15-25%.
Search Query Tracking
Track internal search queries by pushing a custom event when the search form submits. In GA4, create custom dimensions for search_term and results_count. This data reveals what your visitors are looking for and how often the search returns zero results, which is a direct content gap signal.
Download and Outbound Link Tracking
Track file downloads (PDF, ZIP, DOCX) and outbound link clicks with a single delegated event listener. Check whether the clicked element is a link, then inspect the href attribute to determine if it points to a downloadable file or an external domain. Push file_download or outbound_click events with the file name, extension, or target domain as parameters.
Building GA4 Audiences from Custom Events
With scroll depth, time-on-page, and search data flowing into GA4, build audiences that reflect real engagement:
- Engaged readers: scroll depth 75%+ AND active time 120+ seconds. These users read your content thoroughly and are strong candidates for newsletter signup prompts.
- Searchers with unmet needs: triggered
site_searchwithresults_count = 0. Export this list monthly and use it to plan new content. - Download converters: triggered
file_downloadat least once in 30 days. These users are actively using your resources. - Bounce scanners: scroll depth below 25% AND active time under 15 seconds. Investigate whether the content matches the search intent that brought them to the page.
Debugging with GA4 DebugView
Enable GA4 DebugView by installing the Google Analytics Debugger browser extension. This sends events to the debug stream in real time, letting you verify event names, parameters, and timing without waiting for the 24-48 hour processing delay in standard GA4 reports. Test every custom event in DebugView before deploying to production. Common issues include misspelled event names, missing parameters, and duplicate events firing from cached JavaScript.
Conversion Tracking Without Third-Party Scripts
JekCMS provides first-party conversion tracking that works alongside GA4 without requiring additional third-party scripts. The built-in conversion event fires when a user completes a defined goal: newsletter signup, contact form submission, file download, or custom actions you define in the admin panel under Settings > Analytics > Conversions.
Each conversion is recorded in both GA4 (through the dataLayer) and the JekCMS conversions table. This dual tracking provides a fallback when ad blockers prevent GA4 from loading, which affects 25-35% of technical audiences.
The admin dashboard shows conversion counts from both sources, highlighting the discrepancy so you understand the true conversion volume rather than the ad-blocker-reduced number that GA4 alone reports. Review the discrepancy report monthly to calibrate your marketing spend against accurate figures.