Skip to content

Commit 4d58d40

Browse files
committed
feat: use Google Tag Manager gtm.js in addition to gtag.js
1 parent 5f901d0 commit 4d58d40

File tree

2 files changed

+49
-30
lines changed

2 files changed

+49
-30
lines changed

.vitepress/config.ts

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ import { defaultGroupLink, sidebarLinks } from '../docs/links';
66

77
dotenv.config();
88

9-
const BASE = '/';
10-
const BASE_WITH_ORIGIN = `https://developer.stackblitz.com${BASE}`;
9+
const BASE_PATH = '/';
10+
const BASE_WITH_ORIGIN = `https://developer.stackblitz.com${BASE_PATH}`;
1111

1212
interface ThemeConfig extends DefaultTheme.Config {
1313
chatlio: {
14-
id: string | undefined,
15-
allowedRoutes: (RegExp|string)[],
16-
}
14+
id: string | undefined;
15+
allowedRoutes: (RegExp | string)[];
16+
};
1717
}
1818

1919
export default defineConfigWithTheme<ThemeConfig>({
2020
srcDir: './docs',
21-
outDir: `./build${BASE}`,
21+
outDir: `./build${BASE_PATH}`,
2222
assetsDir: 'assets',
23-
base: BASE,
23+
base: BASE_PATH,
2424

2525
// Generate files as `/path/to/page.html` and URLs as `/path/to/page`
2626
cleanUrls: true,
@@ -34,7 +34,7 @@ export default defineConfigWithTheme<ThemeConfig>({
3434
description:
3535
'Discover how to use StackBlitz, an online development environment for frontend, Node.js and the JavaScript ecosystem.',
3636
head: [
37-
['link', { rel: 'icon', type: 'image/png', href: `${BASE}img/theme/favicon.png` }],
37+
['link', { rel: 'icon', type: 'image/png', href: `${BASE_PATH}img/theme/favicon.png` }],
3838
...getAnalyticsTags(process.env),
3939
],
4040

@@ -103,9 +103,9 @@ export default defineConfigWithTheme<ThemeConfig>({
103103
'/enterprise/': sidebarLinks('enterprise', ['enterprise']),
104104
},
105105
chatlio: {
106-
allowedRoutes: [`^${BASE}teams/.*`, `^${BASE}enterprise/.*`],
106+
allowedRoutes: [`^${BASE_PATH}teams/.*`, `^${BASE_PATH}enterprise/.*`],
107107
id: process.env.VITE_CHATLIO_ID,
108-
}
108+
},
109109
},
110110

111111
postRender(context) {
@@ -122,31 +122,48 @@ export default defineConfigWithTheme<ThemeConfig>({
122122
template: {
123123
compilerOptions: {
124124
isCustomElement: (tag) => {
125-
return ["chatlio-widget"].includes(tag.toLowerCase());
126-
}
127-
}
128-
}
125+
return ['chatlio-widget'].includes(tag.toLowerCase());
126+
},
127+
},
128+
},
129129
},
130130
});
131131

132-
function getAnalyticsTags(env: NodeJS.ProcessEnv): HeadConfig[] {
133-
if (!env.VITE_GTAG_ID) {
134-
return [];
132+
function getAnalyticsTags({
133+
VITE_GTM_ID = '',
134+
VITE_GTAG_ID = '',
135+
}: NodeJS.ProcessEnv): HeadConfig[] {
136+
// Fail the build if we have a defined but malformed analytics id
137+
const idPattern = /^(G|GTM)-[A-Z\d]+$/;
138+
for (const [name, value] of Object.entries({ VITE_GTM_ID, VITE_GTAG_ID })) {
139+
if (value && !idPattern.test(value)) {
140+
throw new Error(`Invalid ${name} value: '${value}'`);
141+
}
135142
}
136-
return [
137-
[
138-
'script',
139-
{ src: `https://www.googletagmanager.com/gtag/js?id=${env.VITE_GTAG_ID}`, async: '' },
140-
],
141-
[
142-
'script',
143-
{},
144-
`function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag('js',new Date),gtag('config','${env.VITE_GTAG_ID}',{anonymize_ip:true})`,
145-
],
146-
];
143+
144+
const tags: HeadConfig[] = [];
145+
146+
// We're migrating from gtag.js to gtm.js, but using both as we verify this change
147+
if (VITE_GTM_ID) {
148+
const js = `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
149+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
150+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
151+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
152+
})(window,document,'script','dataLayer','${VITE_GTM_ID}');`;
153+
tags.push(['script', {}, js]);
154+
}
155+
156+
if (VITE_GTAG_ID) {
157+
const url = `https://www.googletagmanager.com/gtag/js?id=${VITE_GTAG_ID}`;
158+
tags.push(['script', { async: '', src: url }]);
159+
const source = `function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag('js',new Date),gtag('config','${VITE_GTAG_ID}',{anonymize_ip:true})`;
160+
tags.push(['script', {}, source]);
161+
}
162+
163+
return tags;
147164
}
148165

149-
function getSearchConfig(env: NodeJS.ProcessEnv) {
166+
function getSearchConfig(env: NodeJS.ProcessEnv): ThemeConfig['search'] {
150167
if (env.VITE_ALGOLIA_ID && env.VITE_ALGOLIA_KEY) {
151168
return {
152169
provider: 'algolia',

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,16 @@ For production, the docs expect the following environment variables to be define
105105

106106
- `VITE_ALGOLIA_ID`: Algolia `appId`.
107107
- `VITE_ALGOLIA_KEY`: Algolia `apiKey`.
108+
- `VITE_GTM_ID`: Google Tag Manager id.
108109
- `VITE_GTAG_ID`: Google Analytics id.
109110

110-
They can be defined in CI server configuration, or in a `.env` file:
111+
They can be defined in CI configuration, or in a `.env` file:
111112

112113
```sh
113114
# .env
114115
VITE_ALGOLIA_ID='******'
115116
VITE_ALGOLIA_KEY='******'
117+
VITE_GTM_ID='******'
116118
VITE_GTAG_ID='******'
117119
```
118120

0 commit comments

Comments
 (0)