feat: smart visitor detection for GA/GTM #8
@@ -19,6 +19,11 @@ All notable changes to the MokoOnyx Joomla template are documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **Smart Visitor Detection** — Pushes anonymised visitor properties (login status, user group, page type) to the dataLayer for Google Analytics / Tag Manager. Sets GA4 `user_properties` for persistent session-scoped dimensions. No PII is sent. Default enabled when GTM or GA4 is active.
|
||||
|
||||
## [03.10.00] - 2026-04-18 — Bridge Release (MokoOnyx → MokoOnyx)
|
||||
|
||||
### Important
|
||||
|
||||
@@ -33,7 +33,7 @@ MokoOnyx is a modern, lightweight enhancement layer built on top of Joomla's Cas
|
||||
- **Bootstrap 5**: Extended utility classes and responsive grid system
|
||||
- **Template Overrides**: Includes overrides for all core Joomla modules, Community Builder, and DPCalendar
|
||||
- **Dark Mode Support**: Built-in light/dark mode toggle with system preference detection
|
||||
- **Google Tag Manager / GA4**: Optional analytics integrations
|
||||
- **Google Tag Manager / GA4**: Optional analytics integrations with smart visitor detection (login status, user group, page type)
|
||||
- **Table of Contents**: Automatic TOC generation for long articles
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -565,6 +565,15 @@ Users still running MokoCassiopeia must install MokoOnyx v01.x first to migrate
|
||||
- **Universal Analytics Fallback**: Legacy UA support
|
||||
- **Privacy-First**: Conditional loading based on settings
|
||||
|
||||
#### Smart Visitor Detection
|
||||
- **Enable/Disable**: Admin toggle (default: enabled)
|
||||
- **Visitor Type**: Pushes `logged_in` or `guest` to dataLayer
|
||||
- **Visitor Group**: Pushes highest-privilege Joomla user group name (e.g., "Registered", "Author")
|
||||
- **Page Type**: Pushes component + view (e.g., `com_content.article`)
|
||||
- **GA4 User Properties**: Sets `visitor_type` and `visitor_group` as persistent user-scoped dimensions
|
||||
- **Privacy-Safe**: No PII (usernames, emails, or user IDs) is ever sent
|
||||
- **Dual Integration**: Works with both GTM (`moko.visitor_detect` event) and standalone GA4 (`user_properties`)
|
||||
|
||||
### 🎛️ Customization & Developer Tools
|
||||
|
||||
#### Custom Code Injection
|
||||
@@ -657,6 +666,7 @@ Users still running MokoCassiopeia must install MokoOnyx v01.x first to migrate
|
||||
- `googletagmanagerid` - GTM container ID
|
||||
- `googleanalytics` - Enable GA4
|
||||
- `googleanalyticsid` - GA4 property ID
|
||||
- `googlevisitordetection` - Smart Visitor Detection (default: enabled)
|
||||
|
||||
#### Custom Code Tab
|
||||
- `custom_head_start` - Custom code at head start
|
||||
|
||||
@@ -37,6 +37,7 @@ $params_googletagmanagerid = $this->params->get('googletagmanagerid', null);
|
||||
$params_googleanalytics = $this->params->get('googleanalytics', false);
|
||||
$params_googleanalyticsid = $this->params->get('googleanalyticsid', null);
|
||||
$params_googlesitekey = $this->params->get('googlesitekey', null);
|
||||
$params_visitordetection = $this->params->get('googlevisitordetection', true);
|
||||
$params_custom_head_start = $this->params->get('custom_head_start', null);
|
||||
$params_custom_head_end = $this->params->get('custom_head_end', null);
|
||||
$params_developmentmode = $this->params->get('developmentmode', false) || $app->get('debug', false);
|
||||
@@ -349,6 +350,37 @@ $wa->useScript('user.js'); // js/user.js
|
||||
. $hasClass
|
||||
. ($this->direction == 'rtl' ? ' rtl' : '');
|
||||
?>">
|
||||
<?php if (!empty($params_visitordetection) && (!empty($params_googletagmanager) || !empty($params_googleanalytics))) :
|
||||
$user = Factory::getUser();
|
||||
$visitorType = $user->guest ? 'guest' : 'logged_in';
|
||||
$visitorGroup = 'none';
|
||||
if (!$user->guest) {
|
||||
$groupIds = $user->getAuthorisedGroups();
|
||||
if (!empty($groupIds)) {
|
||||
$db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class);
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('title'))
|
||||
->from($db->quoteName('#__usergroups'))
|
||||
->where($db->quoteName('id') . ' = ' . (int) end($groupIds));
|
||||
$db->setQuery($query);
|
||||
$visitorGroup = $db->loadResult() ?: 'unknown';
|
||||
}
|
||||
}
|
||||
$pageType = $option . ($view ? '.' . $view : '');
|
||||
?>
|
||||
<!-- Smart Visitor Detection -->
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
window.dataLayer.push({
|
||||
'event': 'moko.visitor_detect',
|
||||
'visitor_type': '<?php echo $visitorType; ?>',
|
||||
'visitor_group': '<?php echo htmlspecialchars($visitorGroup, ENT_QUOTES, 'UTF-8'); ?>',
|
||||
'page_type': '<?php echo htmlspecialchars($pageType, ENT_QUOTES, 'UTF-8'); ?>'
|
||||
});
|
||||
</script>
|
||||
<!-- End Smart Visitor Detection -->
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) :
|
||||
$gtmID = htmlspecialchars($params_googletagmanagerid, ENT_QUOTES, 'UTF-8'); ?>
|
||||
<!-- Google Tag Manager -->
|
||||
@@ -398,6 +430,12 @@ $wa->useScript('user.js'); // js/user.js
|
||||
console.warn('Unrecognized Google Analytics ID format:', id);
|
||||
}
|
||||
})('<?php echo $gaId; ?>');
|
||||
<?php if (!empty($params_visitordetection)) : ?>
|
||||
gtag('set', 'user_properties', {
|
||||
'visitor_type': '<?php echo $user->guest ? 'guest' : 'logged_in'; ?>',
|
||||
'visitor_group': '<?php echo htmlspecialchars($visitorGroup ?? 'none', ENT_QUOTES, 'UTF-8'); ?>'
|
||||
});
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
<!-- End Google Analytics -->
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -46,6 +46,8 @@ TPL_MOKOONYX_GOOGLEANALYTICSID_LABEL="Google Analytics ID"
|
||||
TPL_MOKOONYX_GOOGLEANALYTICSID_DESC="Begins with 'G-'"
|
||||
TPL_MOKOONYX_GOOGLESITEKEY_LABEL="Google Search Console Verification"
|
||||
TPL_MOKOONYX_GOOGLESITEKEY_DESC="Paste the content value from the <meta name="google-site-verification"> tag. Find this in Google Search Console under Ownership Verification → HTML tag method."
|
||||
TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_LABEL="Smart Visitor Detection"
|
||||
TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_DESC="Push anonymised visitor properties (login status, user group, page type) to the dataLayer for use in Google Analytics / Tag Manager. No personally identifiable information is sent."
|
||||
|
||||
; ===== Branding & icons (Theme tab) =====
|
||||
TPL_MOKOONYX_BRAND_LABEL="Brand"
|
||||
|
||||
@@ -46,6 +46,8 @@ TPL_MOKOONYX_GOOGLEANALYTICSID_LABEL="Google Analytics ID"
|
||||
TPL_MOKOONYX_GOOGLEANALYTICSID_DESC="Begins with 'G-'"
|
||||
TPL_MOKOONYX_GOOGLESITEKEY_LABEL="Google Search Console Verification"
|
||||
TPL_MOKOONYX_GOOGLESITEKEY_DESC="Paste the content value from the <meta name="google-site-verification"> tag. Find this in Google Search Console under Ownership Verification → HTML tag method."
|
||||
TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_LABEL="Smart Visitor Detection"
|
||||
TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_DESC="Push anonymised visitor properties (login status, user group, page type) to the dataLayer for use in Google Analytics / Tag Manager. No personally identifiable information is sent."
|
||||
|
||||
; ===== Branding & icons (Theme tab) =====
|
||||
TPL_MOKOONYX_BRAND_LABEL="Brand"
|
||||
|
||||
@@ -142,6 +142,10 @@
|
||||
</field>
|
||||
<field name="googleanalyticsid" type="text" default="" label="TPL_MOKOONYX_GOOGLEANALYTICSID_LABEL" description="TPL_MOKOONYX_GOOGLEANALYTICSID_DESC" filter="string" showon="googleanalytics:1" />
|
||||
<field name="googlesitekey" type="text" default="" label="TPL_MOKOONYX_GOOGLESITEKEY_LABEL" description="TPL_MOKOONYX_GOOGLESITEKEY_DESC" filter="string" />
|
||||
<field name="googlevisitordetection" type="radio" default="1" label="TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_LABEL" description="TPL_MOKOONYX_GOOGLE_VISITOR_DETECTION_DESC" layout="joomla.form.field.radio.switcher" filter="boolean" showon="googletagmanager:1[OR]googleanalytics:1">
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
|
||||
<!-- Custom Code tab -->
|
||||
|
||||
Reference in New Issue
Block a user