Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions website/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,7 @@ function createAposConfig() {
},
},
},
// GTM setup and dependencies
'@apostrophecms/seo': {
options: {
googleTagManager: {
id: process.env.GOOGLE_TAG_MANAGER_ID,
},
},
},
// GTM setup handled by local SEO module
Comment thread
killev marked this conversation as resolved.
Outdated
'@apostrophecms/global': {},
// Make getEnv function available to templates
'@apostrophecms/template': {
Expand Down
31 changes: 9 additions & 22 deletions website/modules/@apostrophecms/seo/index.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
const gtmUtils = require('./lib/gtm-utils');

module.exports = {
improve: '@apostrophecms/seo',
options: {
googleTagManager: {
id: process.env.GOOGLE_TAG_MANAGER_ID,
},
},
init(self) {
// Ensure SEO components are injected into the template
self.apos.template.prepend('body', '@apostrophecms/seo:tagManagerBody');
self.apos.template.append('head', '@apostrophecms/seo:tagManagerHead');
self.apos.template.prepend('head', '@apostrophecms/seo:metaHead');
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
components(self) {
/*
* Resolve GTM ID from global override or module options and validate it
*/
const sanitizeGtmId = (id) => {
const value = String(id || '').trim();
if (/^gtm-[\da-z]+$/iu.test(value)) {
return value.toUpperCase();
}
return '';
};
const resolveGtmId = (req) => {
const fromGlobal = req?.data?.global?.seoGoogleTagManager;
const fromOptions = self.options?.googleTagManager?.id;
const candidate =
(fromGlobal && String(fromGlobal).trim()) ||
(fromOptions && String(fromOptions).trim());
return sanitizeGtmId(candidate);
};

return {
metaHead(req, data) {
// Only on front-end page requests
Expand All @@ -38,7 +25,7 @@ module.exports = {
if (!req?.data?.page) {
return {};
}
const gtmId = resolveGtmId(req);
const gtmId = gtmUtils.resolveGtmId(req, self.options);
if (gtmId) {
return { gtmId };
}
Expand All @@ -48,7 +35,7 @@ module.exports = {
if (!req?.data?.page) {
return {};
}
const gtmId = resolveGtmId(req);
const gtmId = gtmUtils.resolveGtmId(req, self.options);
if (gtmId) {
return { gtmId };
}
Expand Down
21 changes: 21 additions & 0 deletions website/modules/@apostrophecms/seo/lib/gtm-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const sanitizeGtmId = function (id) {
const value = String(id || '')
.trim()
.toUpperCase();
// Strict GTM container format, e.g., "GTM-XXXXXXX"
if (/^GTM-[\dA-Z]+$/u.test(value)) {
return value;
}
return '';
};

const resolveGtmId = function (req, options) {
const fromGlobal = req?.data?.global?.seoGoogleTagManager;
const fromOptions = options?.googleTagManager?.id;
const candidate =
(fromGlobal && String(fromGlobal).trim()) ||
(fromOptions && String(fromOptions).trim());
return sanitizeGtmId(candidate);
};

module.exports = { sanitizeGtmId, resolveGtmId };
4 changes: 4 additions & 0 deletions website/modules/@apostrophecms/seo/views/gtmBody.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ data.gtmId }}"
height="0" width="0" style="display:none;visibility:hidden" title="Google Tag Manager"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
7 changes: 7 additions & 0 deletions website/modules/@apostrophecms/seo/views/gtmHead.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- 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','{{ data.gtmId }}');</script>
<!-- End Google Tag Manager -->
5 changes: 1 addition & 4 deletions website/modules/@apostrophecms/seo/views/tagManagerBody.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{% if data.gtmId %}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ data.gtmId }}"
height="0" width="0" style="display:none;visibility:hidden" title="Google Tag Manager"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{% render '@apostrophecms/seo:gtmBody', data %}
{% endif %}
8 changes: 1 addition & 7 deletions website/modules/@apostrophecms/seo/views/tagManagerHead.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
{% if data.gtmId %}
<!-- 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','{{ data.gtmId }}');</script>
<!-- End Google Tag Manager -->
{% render '@apostrophecms/seo:gtmHead', data %}
{% endif %}
1 change: 0 additions & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"dependencies": {
"@apostrophecms/form": "^1.4.2",
"@apostrophecms/import-export": "^3.2.0",
"@apostrophecms/seo": "^1.3.1",
"@barba/core": "^2.10.3",
"abort-controller": "^3.0.0",
"apostrophe": "^4.17.0",
Expand Down
2 changes: 2 additions & 0 deletions website/views/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
{# ✅ Add favicon in the <head> section #}
{% block extraHead %}
<link rel="icon" href="{{ apos.asset.url('/modules/asset/favicon/favicon.ico') }}" type="image/x-icon">
{% render '@apostrophecms/seo:tagManagerHead', data %}
{% endblock %}

{% block beforeMain %}
{% render '@apostrophecms/seo:tagManagerBody', data %}
Comment thread
killev marked this conversation as resolved.
Outdated
<a class="sr-only" href="#main">Skip to content</a>
<div
class="bp-wrapper relative"
Expand Down
Loading