Skip to content

Commit 4fbb879

Browse files
committed
Merge branch 'main' into 772-feature/prevent-content-flash
2 parents 64f7423 + 63f849e commit 4fbb879

18 files changed

Lines changed: 246 additions & 15 deletions

File tree

.cursor/rules/common

Submodule common updated 1 file

.github/CODEOWNERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This is a CODEOWNERS file for the repository
2-
# @killev will be requested for review when someone opens a pull request
2+
# @killev and @vasilyyaremchuk will be requested for review when someone opens a pull request
33
# affecting any file in the repository
44

55
# Default owner for everything in the repo
6-
* @killev
6+
* @killev @vasilyyaremchuk

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,6 @@ website/public/apos-frontend
144144
dump.archive
145145
.prettierrc
146146
aposUsersSafe.json
147+
148+
# Temporary files directory
149+
tmp/

website/app.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ function createAposConfig() {
3434
},
3535
},
3636
},
37-
37+
// Enable local SEO module with GTM integration
38+
'@apostrophecms/seo': {},
39+
'@apostrophecms/global': {},
3840
// Make getEnv function available to templates
3941
'@apostrophecms/template': {
4042
options: {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ module.exports = {
120120
},
121121
},
122122
},
123+
// SEO fields
124+
seoGoogleTagManager: {
125+
label: 'Google Tag Manager ID',
126+
type: 'string',
127+
help: 'Enter your GTM container ID (e.g., GTM-XXXXXXX)',
128+
},
123129
},
124130
group: {
125131
navs: {
@@ -130,6 +136,10 @@ module.exports = {
130136
label: 'Footer',
131137
fields: ['comAddress', 'footerLinks', 'socialMediaLinks', 'footerForm'],
132138
},
139+
seo: {
140+
label: 'SEO & Analytics',
141+
fields: ['seoGoogleTagManager'],
142+
},
133143
},
134144
},
135145
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const gtmUtils = require('./lib/gtm-utils');
2+
3+
module.exports = {
4+
options: {
5+
googleTagManager: {
6+
id: process.env.GOOGLE_TAG_MANAGER_ID,
7+
},
8+
},
9+
// No init hook required (layout renders components explicitly).
10+
components(self) {
11+
const getGtmId = (req) => gtmUtils.resolveGtmId(req, self.options);
12+
return {
13+
tagManagerBody(req, data) {
14+
if (!req?.data?.page) {
15+
return {};
16+
}
17+
const gtmId = getGtmId(req);
18+
if (gtmId) {
19+
return { gtmId };
20+
}
21+
return {};
22+
},
23+
tagManagerHead(req, data) {
24+
if (!req?.data?.page) {
25+
return {};
26+
}
27+
const gtmId = getGtmId(req);
28+
if (gtmId) {
29+
return { gtmId };
30+
}
31+
return {};
32+
},
33+
};
34+
},
35+
};
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 };
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{# Meta head template for SEO - placeholder for other meta tags #}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{% if data.gtmId %}
2+
<!-- Google Tag Manager (noscript) -->
3+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ data.gtmId }}"
4+
height="0" width="0" style="display:none;visibility:hidden" title="Google Tag Manager"></iframe></noscript>
5+
<!-- End Google Tag Manager (noscript) -->
6+
{% endif %}

0 commit comments

Comments
 (0)