Skip to content

Commit 352b2b9

Browse files
committed
Merge branch 'main' into 785-fix/403-forbidden-form-submission-in-production
2 parents 1474476 + e823b3a commit 352b2b9

5 files changed

Lines changed: 35 additions & 43 deletions

File tree

website/app.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,8 @@ function createAposConfig() {
5151
},
5252
},
5353
},
54-
// GTM setup and dependencies
55-
'@apostrophecms/seo': {
56-
options: {
57-
googleTagManager: {
58-
id: process.env.GOOGLE_TAG_MANAGER_ID,
59-
},
60-
},
61-
},
54+
// Enable local SEO module with GTM integration
55+
'@apostrophecms/seo': {},
6256
'@apostrophecms/global': {},
6357
// Make getEnv function available to templates
6458
'@apostrophecms/template': {

website/modules/@apostrophecms/seo/index.js

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,20 @@
1+
const gtmUtils = require('./lib/gtm-utils');
2+
13
module.exports = {
2-
improve: '@apostrophecms/seo',
3-
init(self) {
4-
// Ensure SEO components are injected into the template
5-
self.apos.template.prepend('body', '@apostrophecms/seo:tagManagerBody');
6-
self.apos.template.append('head', '@apostrophecms/seo:tagManagerHead');
7-
self.apos.template.prepend('head', '@apostrophecms/seo:metaHead');
4+
options: {
5+
googleTagManager: {
6+
id: process.env.GOOGLE_TAG_MANAGER_ID,
7+
},
88
},
9+
// No init hook required (layout renders components explicitly).
910
components(self) {
10-
/*
11-
* Resolve GTM ID from global override or module options and validate it
12-
*/
13-
const sanitizeGtmId = (id) => {
14-
const value = String(id || '').trim();
15-
if (/^gtm-[\da-z]+$/iu.test(value)) {
16-
return value.toUpperCase();
17-
}
18-
return '';
19-
};
20-
const resolveGtmId = (req) => {
21-
const fromGlobal = req?.data?.global?.seoGoogleTagManager;
22-
const fromOptions = self.options?.googleTagManager?.id;
23-
const candidate =
24-
(fromGlobal && String(fromGlobal).trim()) ||
25-
(fromOptions && String(fromOptions).trim());
26-
return sanitizeGtmId(candidate);
27-
};
28-
11+
const getGtmId = (req) => gtmUtils.resolveGtmId(req, self.options);
2912
return {
30-
metaHead(req, data) {
31-
// Only on front-end page requests
32-
if (!req?.data?.page) {
33-
return {};
34-
}
35-
return {};
36-
},
3713
tagManagerBody(req, data) {
3814
if (!req?.data?.page) {
3915
return {};
4016
}
41-
const gtmId = resolveGtmId(req);
17+
const gtmId = getGtmId(req);
4218
if (gtmId) {
4319
return { gtmId };
4420
}
@@ -48,7 +24,7 @@ module.exports = {
4824
if (!req?.data?.page) {
4925
return {};
5026
}
51-
const gtmId = resolveGtmId(req);
27+
const gtmId = getGtmId(req);
5228
if (gtmId) {
5329
return { gtmId };
5430
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const sanitizeGtmId = function (id) {
2+
const value = String(id || '')
3+
.trim()
4+
.toUpperCase();
5+
// Strict GTM container format, e.g., "GTM-XXXXXXX"
6+
if (/^GTM-[\dA-Z]+$/u.test(value)) {
7+
return value;
8+
}
9+
return '';
10+
};
11+
12+
const resolveGtmId = function (req, options) {
13+
const fromGlobal = req?.data?.global?.seoGoogleTagManager;
14+
const fromOptions = options?.googleTagManager?.id;
15+
const candidate =
16+
(fromGlobal && String(fromGlobal).trim()) ||
17+
(fromOptions && String(fromOptions).trim());
18+
return sanitizeGtmId(candidate);
19+
};
20+
21+
module.exports = { sanitizeGtmId, resolveGtmId };

website/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"dependencies": {
4141
"@apostrophecms/form": "^1.4.2",
4242
"@apostrophecms/import-export": "^3.2.0",
43-
"@apostrophecms/seo": "^1.3.1",
4443
"@barba/core": "^2.10.3",
4544
"abort-controller": "^3.0.0",
4645
"apostrophe": "^4.17.0",

website/views/layout.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
{# ✅ Add favicon in the <head> section #}
1515
{% block extraHead %}
1616
<link rel="icon" href="{{ apos.asset.url('/modules/asset/favicon/favicon.ico') }}" type="image/x-icon">
17+
{% component '@apostrophecms/seo:tagManagerHead' with data %}
1718
{% endblock %}
1819

1920
{% block beforeMain %}
21+
{% component '@apostrophecms/seo:tagManagerBody' with data %}
2022
<a class="sr-only" href="#main">Skip to content</a>
2123
<div
2224
class="bp-wrapper relative"

0 commit comments

Comments
 (0)