├── client
├── .nuxtrc
├── package.json
├── app.vue
├── components
│ ├── ModuleAuthorNote.vue
│ └── OptionTable.vue
├── nuxt.config.ts
└── pages
│ └── index.vue
├── .eslintignore
├── .npmrc
├── .nuxtrc
├── tsconfig.json
├── assets
├── nuxt-gtm.png
├── icon-logo.png
├── icon-logo-dark.png
├── icon-logo.svg
├── icon-logo-dark.svg
├── nuxt-gtm.svg
└── zadigetvoltaire-logo.svg
├── Makefile
├── playground
├── package.json
├── nuxt.config.ts
└── app.vue
├── test
├── fixtures
│ └── basic
│ │ ├── package.json
│ │ ├── nuxt.config.ts
│ │ └── app.vue
└── basic.test.ts
├── .editorconfig
├── .vscode
└── settings.json
├── src
├── runtime
│ └── plugin.ts
├── module.ts
└── devtools.ts
├── .eslintrc.cjs
├── .gitignore
├── .github
└── workflows
│ ├── test-lint.yml
│ ├── test-build.yml
│ └── lib-publish.yml
├── LICENCE
├── package.json
├── CHANGELOG.md
└── README.md
/client/.nuxtrc:
--------------------------------------------------------------------------------
1 | imports.autoImport=true
2 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | *.svg
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
2 | strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/.nuxtrc:
--------------------------------------------------------------------------------
1 | imports.autoImport=false
2 | typescript.includeWorkspace=true
3 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./client/.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/assets/nuxt-gtm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zadigetvoltaire/nuxt-gtm/HEAD/assets/nuxt-gtm.png
--------------------------------------------------------------------------------
/assets/icon-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zadigetvoltaire/nuxt-gtm/HEAD/assets/icon-logo.png
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "@zadigetvoltaire/nuxt-gtm-client"
4 | }
5 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | start:
2 | pnpm install
3 | pnpm dev:prepare
4 | pnpm dev
5 |
6 | release:
7 | pnpm release
--------------------------------------------------------------------------------
/client/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/assets/icon-logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zadigetvoltaire/nuxt-gtm/HEAD/assets/icon-logo-dark.png
--------------------------------------------------------------------------------
/playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "@zadigetvoltaire/nuxt-gtm-playground"
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixtures/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "basic",
4 | "type": "module"
5 | }
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_size = 2
5 | indent_style = space
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/client/components/ModuleAuthorNote.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Documentation available in the
4 | README.me
5 | on our github project.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/test/fixtures/basic/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | import nuxtGtm from '../../../src/module'
2 |
3 | export default defineNuxtConfig({
4 | modules: [
5 | // @ts-ignore
6 | nuxtGtm
7 | ],
8 | gtm: {
9 | devtools: true,
10 | id: 'GTM-XXXXXX',
11 | enableRouterSync: true
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/client/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'node:path'
2 |
3 | export default defineNuxtConfig({
4 | ssr: false,
5 | modules: [
6 | '@nuxt/devtools-ui-kit'
7 | ],
8 | nitro: {
9 | output: {
10 | publicDir: resolve(__dirname, '../dist/client')
11 | }
12 | },
13 | app: {
14 | baseURL: '/__nuxt-gtm'
15 | }
16 | })
17 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.eslint": true,
5 | "source.fixAll.stylelint": true
6 | },
7 | // ESLINT
8 | "eslint.enable": true,
9 | "eslint.format.enable": true,
10 | "eslint.validate": ["javascript", "typescript", "html", "vue"],
11 | // CSS
12 | "css.validate": false
13 | }
14 |
--------------------------------------------------------------------------------
/test/basic.test.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath } from 'node:url'
2 | import { describe, it, expect } from 'vitest'
3 | import { setup, $fetch } from '@nuxt/test-utils'
4 |
5 | describe('ssr', async () => {
6 | await setup({
7 | rootDir: fileURLToPath(new URL('fixtures/basic', import.meta.url))
8 | })
9 |
10 | it('renders the index page', async () => {
11 | // Get response to a server-rendered page with `$fetch`.
12 | const html = await $fetch('/')
13 |
14 | expect(html).toContain('
basic
')
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/assets/icon-logo.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/assets/icon-logo-dark.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/src/runtime/plugin.ts:
--------------------------------------------------------------------------------
1 |
2 | import { defineNuxtPlugin, useRouter } from 'nuxt/app'
3 | import { createGtm, type VueGtmUseOptions } from '@gtm-support/vue-gtm'
4 | // @ts-ignore
5 |
6 | export default defineNuxtPlugin((nuxt) => {
7 | if (process.client) {
8 | const options = nuxt.$config.public.gtm
9 |
10 | const router = useRouter()
11 |
12 | const pluginOptions: VueGtmUseOptions = {
13 | ...options,
14 | vueRouter: options.enableRouterSync && router ? router as VueGtmUseOptions['vueRouter'] : undefined
15 | }
16 |
17 | nuxt.vueApp.use(createGtm(pluginOptions))
18 | }
19 | })
20 |
--------------------------------------------------------------------------------
/playground/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | modules: [
3 | '../src/module',
4 | '@nuxt/devtools'
5 | ],
6 | gtm: {
7 | id: 'GTM-XXXXXX',
8 | enableRouterSync: true,
9 | queryParams: {
10 | gtm_auth: 'init',
11 | gtm_cookies_win: 'init',
12 | gtm_preview: 'init'
13 | }
14 | },
15 | runtimeConfig: {
16 | public: {
17 | gtm: {
18 | id: 'GTM-YYYYYY',
19 | queryParams: {
20 | gtm_auth: 'test',
21 | gtm_cookies_win: 'test',
22 | gtm_preview: 'test'
23 | }
24 | }
25 | }
26 | }
27 | })
28 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: [
4 | 'plugin:sonarjs/recommended',
5 | 'plugin:unicorn/recommended',
6 | '@nuxtjs/eslint-config-typescript'
7 | ],
8 | rules: {
9 | 'no-console': [
10 | process.env.NODE_ENV === 'production' ? 'error' : 'warn',
11 | { allow: ['error', 'warn'] }
12 | ],
13 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
14 | // UNICORN
15 | 'unicorn/prefer-module': 'off',
16 | 'unicorn/no-array-for-each': 'off',
17 | 'unicorn/prevent-abbreviations': [
18 | 'error',
19 | {
20 | allowList: {
21 | setupDevToolsUI: true
22 | }
23 | }
24 | ]
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/fixtures/basic/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Nuxt GTM playground!
4 |
5 |
{{ $gtm.options }}
6 |
7 |
10 |
11 |
14 |
15 |
16 |
17 |
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules
3 |
4 | # Logs
5 | *.log*
6 |
7 | # Temp directories
8 | .temp
9 | .tmp
10 | .cache
11 |
12 | # Yarn
13 | **/.yarn/cache
14 | **/.yarn/*state*
15 |
16 | # Generated dirs
17 | dist
18 |
19 | # Nuxt
20 | .nuxt
21 | .output
22 | .vercel_build_output
23 | .build-*
24 | .env
25 | .netlify
26 |
27 | # Env
28 | .env
29 |
30 | # Testing
31 | reports
32 | coverage
33 | *.lcov
34 | .nyc_output
35 |
36 | # VSCode
37 | .vscode/*
38 | !.vscode/settings.json
39 | !.vscode/tasks.json
40 | !.vscode/launch.json
41 | !.vscode/extensions.json
42 | !.vscode/*.code-snippets
43 |
44 | # Intellij idea
45 | *.iml
46 | .idea
47 |
48 | # OSX
49 | .DS_Store
50 | .AppleDouble
51 | .LSOverride
52 | .AppleDB
53 | .AppleDesktop
54 | Network Trash Folder
55 | Temporary Items
56 | .apdisk
57 |
--------------------------------------------------------------------------------
/.github/workflows/test-lint.yml:
--------------------------------------------------------------------------------
1 | name: Test Lint
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - ".github/workflows/test-lint.yml"
9 | pull_request:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | test-lint:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 |
20 | - uses: pnpm/action-setup@v2
21 | with:
22 | version: 7
23 |
24 | - name: Use Node.js
25 | uses: actions/setup-node@v3
26 | with:
27 | node-version: "18"
28 | cache: "pnpm"
29 |
30 | - name: Install modules
31 | run: pnpm install --no-frozen-lockfile
32 |
33 | - name: Prepare project
34 | run: pnpm dev:prepare
35 |
36 | - name: Run linter
37 | run: pnpm lint
38 |
--------------------------------------------------------------------------------
/.github/workflows/test-build.yml:
--------------------------------------------------------------------------------
1 | name: Test Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - ".github/workflows/test-build.yml"
9 | pull_request:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | test-build:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 |
20 | - uses: pnpm/action-setup@v2
21 | with:
22 | version: 7
23 |
24 | - name: Use Node.js
25 | uses: actions/setup-node@v3
26 | with:
27 | node-version: "18"
28 | cache: "pnpm"
29 |
30 | - name: Install modules
31 | run: pnpm install --no-frozen-lockfile
32 |
33 | - name: Prepare project
34 | run: pnpm dev:prepare
35 |
36 | - name: Build module
37 | run: pnpm prepack
38 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Zadig&Voltaire
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/.github/workflows/lib-publish.yml:
--------------------------------------------------------------------------------
1 | name: Lib Publish To Npm
2 |
3 | on:
4 | release:
5 | types: [created]
6 | # push:
7 | # branches:
8 | # - main
9 | # paths:
10 | # - ".github/workflows/lib-publish.yml"
11 |
12 | jobs:
13 | lib-publish:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | - uses: pnpm/action-setup@v2
20 | with:
21 | version: 7
22 |
23 | - name: Use Node.js
24 | uses: actions/setup-node@v3
25 | with:
26 | cache: "pnpm"
27 | node-version: "18"
28 | registry-url: "https://registry.npmjs.org"
29 |
30 | - name: Install dependencies
31 | run: pnpm install --no-frozen-lockfile
32 |
33 | - name: Prepare env
34 | run: pnpm dev:prepare
35 |
36 | - name: Run linter
37 | run: pnpm lint
38 |
39 | - name: Build Lib
40 | run: pnpm prepack
41 |
42 | - name: Publish package to npm registry
43 | run: pnpm publish --access public --no-git-checks
44 | env:
45 | NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
46 |
--------------------------------------------------------------------------------
/playground/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Nuxt GTM playground!
5 |
6 |
7 |
8 | Options
9 |
10 |
11 |
{{ gtmOptions }}
12 |
13 |
14 | Actions
15 |
16 |
17 |
20 |
21 |
24 |
25 |
26 | Datalayer
27 |
28 |
29 | {{ dataLayerPayload }}
30 |
31 |
32 |
33 |
63 |
--------------------------------------------------------------------------------
/client/pages/index.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 | Nuxt GTM
14 |
15 |
16 |
17 | By Zadig&voltaire ©
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ⚠️ No configuration found
35 |
36 |
37 |
38 |
39 |
40 |
41 |
46 | Close DevTools
47 |
48 |
49 |
50 |
51 |
52 | Failed to connect to the client. Did you open this page inside Nuxt DevTools?
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/module.ts:
--------------------------------------------------------------------------------
1 | import { type VueGtmUseOptions } from '@gtm-support/vue-gtm'
2 | import { defineNuxtModule, addPlugin, createResolver, addImports } from '@nuxt/kit'
3 | import { defu } from 'defu'
4 | import { setupDevToolsUI } from './devtools'
5 |
6 | // Module options TypeScript interface definition
7 | export interface ModuleOptions extends Omit {
8 | enableRouterSync?: boolean
9 | /**
10 | * Enable Nuxt Devtools integration
11 | *
12 | * @default true
13 | */
14 | devtools?: boolean
15 | }
16 |
17 | declare module '@nuxt/schema' {
18 | interface PublicRuntimeConfig {
19 | gtm: ModuleOptions
20 | }
21 | interface NuxtConfig {
22 | gtm?: ModuleOptions
23 | }
24 | interface NuxtOptions {
25 | gtm?: ModuleOptions
26 | }
27 | }
28 |
29 | export default defineNuxtModule({
30 | meta: {
31 | name: '@zadigetvoltaire/nuxt-gtm',
32 | configKey: 'gtm',
33 | compatibility: {
34 | nuxt: '^3.0.0'
35 | }
36 | },
37 | // @ts-ignore
38 | defaults: {
39 | devtools: true
40 | },
41 | setup (options, nuxt) {
42 | const resolver = createResolver(import.meta.url)
43 |
44 | const moduleOptions: ModuleOptions = defu(nuxt.options.runtimeConfig.public.gtm, options)
45 |
46 | nuxt.options.runtimeConfig.public.gtm = moduleOptions
47 |
48 | // Do not add the extension since the `.ts` will be transpiled to `.mjs` after `npm run prepack`
49 | addPlugin(resolver.resolve('./runtime/plugin'))
50 |
51 | addImports({
52 | name: 'useGtm',
53 | as: 'useGtm',
54 | from: '@gtm-support/vue-gtm'
55 | })
56 |
57 | if (options.devtools) {
58 | setupDevToolsUI(nuxt, resolver)
59 | }
60 | }
61 | })
62 |
--------------------------------------------------------------------------------
/src/devtools.ts:
--------------------------------------------------------------------------------
1 | import { existsSync } from 'node:fs'
2 | import { Nuxt } from 'nuxt/schema'
3 | import { Resolver } from '@nuxt/kit'
4 |
5 | const DEVTOOLS_UI_ROUTE = '/__nuxt-gtm'
6 | const DEVTOOLS_UI_LOCAL_PORT = 3300
7 |
8 | export function setupDevToolsUI (nuxt: Nuxt, resolver: Resolver) {
9 | const clientPath = resolver.resolve('./client')
10 | const isProductionBuild = existsSync(clientPath)
11 |
12 | // Serve production-built client (used when package is published)
13 | if (isProductionBuild) {
14 | nuxt.hook('vite:serverCreated', async (server) => {
15 | const sirv = await import('sirv').then(r => r.default || r)
16 | server.middlewares.use(
17 | DEVTOOLS_UI_ROUTE,
18 | sirv(clientPath, { dev: true, single: true })
19 | )
20 | })
21 | } else {
22 | nuxt.hook('vite:extendConfig', (config) => {
23 | config.server = config.server || {}
24 | config.server.proxy = config.server.proxy || {}
25 | config.server.proxy[DEVTOOLS_UI_ROUTE] = {
26 | target: 'http://localhost:' + DEVTOOLS_UI_LOCAL_PORT + DEVTOOLS_UI_ROUTE,
27 | changeOrigin: true,
28 | followRedirects: true,
29 | rewrite: path => path.replace(DEVTOOLS_UI_ROUTE, '')
30 | }
31 | })
32 | }
33 |
34 | // @ts-expect-error
35 | nuxt.hook('devtools:customTabs', (tabs) => {
36 | tabs.push({
37 | // unique identifier
38 | name: 'nuxt-gtm',
39 | // title to display in the tab
40 | title: 'Nuxt GTM',
41 | // any icon from Iconify, or a URL to an image
42 | icon: 'carbon:text-link-analysis',
43 | // iframe view
44 | view: {
45 | type: 'iframe',
46 | src: DEVTOOLS_UI_ROUTE
47 | }
48 | })
49 | })
50 | }
51 |
--------------------------------------------------------------------------------
/client/components/OptionTable.vue:
--------------------------------------------------------------------------------
1 |
46 |
47 |
48 |
49 |
50 | Your GTM configuration:
51 |
52 |
53 |
54 |
55 |
56 |
57 |
84 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@zadigetvoltaire/nuxt-gtm",
3 | "version": "0.0.13",
4 | "description": "Nuxt module to add Google Tag Manager",
5 | "license": "MIT",
6 | "type": "module",
7 | "exports": {
8 | ".": {
9 | "types": "./dist/types.d.ts",
10 | "import": "./dist/module.mjs",
11 | "require": "./dist/module.cjs"
12 | }
13 | },
14 | "main": "./dist/module.cjs",
15 | "types": "./dist/types.d.ts",
16 | "files": [
17 | "dist"
18 | ],
19 | "scripts": {
20 | "prepack": "nuxt-module-build && npm run client:build",
21 | "client:build": "nuxi generate client",
22 | "client:dev": "nuxi dev client --port 3300",
23 | "dev": "concurrently \"npm:client:dev\" \"npm:play:dev\"",
24 | "dev:prepare": "nuxt-module-build --stub && nuxi prepare client",
25 | "play:dev": "nuxi dev playground",
26 | "play:prod": "npm run prepack && nuxi dev playground",
27 | "release": "changelogen --release --push",
28 | "lint": "cross-env NODE_ENV=production eslint .",
29 | "test": "vitest run",
30 | "test:watch": "vitest watch"
31 | },
32 | "dependencies": {
33 | "@gtm-support/vue-gtm": "^2.0.0",
34 | "@nuxt/kit": "^3.5.1",
35 | "defu": "^6.1.2",
36 | "sirv": "^2.0.3"
37 | },
38 | "peerDependencies": {
39 | "nuxt": "^3.0.0"
40 | },
41 | "devDependencies": {
42 | "@iconify-json/carbon": "^1.1.15",
43 | "@nuxt/devtools": "0.5.0",
44 | "@nuxt/devtools-ui-kit": "0.5.0",
45 | "@nuxt/eslint-config": "^0.1.1",
46 | "@nuxt/module-builder": "^0.3.1",
47 | "@nuxt/schema": "^3.5.1",
48 | "@nuxt/test-utils": "^3.5.1",
49 | "@nuxtjs/eslint-config-typescript": "^12.0.0",
50 | "changelogen": "^0.5.1",
51 | "concurrently": "^8.0.1",
52 | "cross-env": "^7.0.3",
53 | "eslint": "^8.41.0",
54 | "eslint-plugin-sonarjs": "^0.19.0",
55 | "eslint-plugin-unicorn": "^47.0.0",
56 | "nuxt": "^3.5.1",
57 | "vitest": "^0.31.1"
58 | },
59 | "repository": {
60 | "type": "git",
61 | "url": "https://github.com/zadigetvoltaire/nuxt-gtm.git"
62 | },
63 | "keywords": [
64 | "nuxt",
65 | "nuxt3",
66 | "module",
67 | "nuxt-module",
68 | "gtm",
69 | "google tag manager",
70 | "googletagmanager",
71 | "open-source"
72 | ],
73 | "author": "Zadig&Voltaire",
74 | "bugs": {
75 | "url": "https://github.com/zadigetvoltaire/nuxt-gtm/issues"
76 | },
77 | "homepage": "https://github.com/zadigetvoltaire/nuxt-gtm#readme",
78 | "changelog": {
79 | "repo": {
80 | "provider": "github"
81 | }
82 | },
83 | "pnpm": {
84 | "peerDependencyRules": {
85 | "ignoreMissing": [
86 | "typescript",
87 | "webpack",
88 | "vue",
89 | "vite"
90 | ]
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/assets/nuxt-gtm.svg:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/assets/zadigetvoltaire-logo.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 |
4 | ## v0.0.13
5 |
6 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.12...v0.0.13)
7 |
8 |
9 | ### 💅 Refactors
10 |
11 | - Use composable useRouter to get nuxt router ([3624f1c](https://github.com/zadigetvoltaire/nuxt-gtm/commit/3624f1c))
12 | - Export useGtm composable directly from dependency ([4ff7a85](https://github.com/zadigetvoltaire/nuxt-gtm/commit/4ff7a85))
13 |
14 | ### 📖 Documentation
15 |
16 | - Update logo in readme ([e08f3f9](https://github.com/zadigetvoltaire/nuxt-gtm/commit/e08f3f9))
17 |
18 | ### 🏡 Chore
19 |
20 | - Format code ([647fcdf](https://github.com/zadigetvoltaire/nuxt-gtm/commit/647fcdf))
21 | - Remove commented code ([7d74054](https://github.com/zadigetvoltaire/nuxt-gtm/commit/7d74054))
22 | - Upgrade dependencies ([0de6f85](https://github.com/zadigetvoltaire/nuxt-gtm/commit/0de6f85))
23 |
24 | ### ❤️ Contributors
25 |
26 | - LouisMazel
27 |
28 | ## v0.0.12
29 |
30 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.11...v0.0.12)
31 |
32 |
33 | ### 🩹 Fixes
34 |
35 | - Make devtools option not required ([bba2ff9](https://github.com/zadigetvoltaire/nuxt-gtm/commit/bba2ff9))
36 |
37 | ### ❤️ Contributors
38 |
39 | - LouisMazel
40 |
41 | ## v0.0.11
42 |
43 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.10...v0.0.11)
44 |
45 |
46 | ### 🏡 Chore
47 |
48 | - Downgrade changelogen to 0.5.1 ([56cf7ec](https://github.com/zadigetvoltaire/nuxt-gtm/commit/56cf7ec))
49 | - Upgrade dependencies ([8fa8ca6](https://github.com/zadigetvoltaire/nuxt-gtm/commit/8fa8ca6))
50 |
51 | ### ❤️ Contributors
52 |
53 | - LouisMazel
54 |
55 | ## v0.0.10
56 |
57 | [compare changes](https://undefined/undefined/compare/v0.0.9...v0.0.10)
58 |
59 |
60 | ### 🏡 Chore
61 |
62 | - Downgrade changelogen to 0.5.1 ([abdd000](https://undefined/undefined/commit/abdd000))
63 | - Upgrade dependencies ([aa6e9f1](https://undefined/undefined/commit/aa6e9f1))
64 | - Update repository url in package.json ([80cad0c](https://undefined/undefined/commit/80cad0c))
65 | - Upgrade changelogen dependency ([9d8a52e](https://undefined/undefined/commit/9d8a52e))
66 |
67 | ### ❤️ Contributors
68 |
69 | - LouisMazel
70 |
71 | ## v0.0.9
72 |
73 | [compare changes](https://undefined/undefined/compare/v0.0.8...v0.0.9)
74 |
75 |
76 | ### 🏡 Chore
77 |
78 | - Upgrade dependencies ([999fb9f](https://undefined/undefined/commit/999fb9f))
79 |
80 | ### ❤️ Contributors
81 |
82 | - LouisMazel
83 |
84 | ## v0.0.8
85 |
86 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.7...v0.0.8)
87 |
88 |
89 | ### 🚀 Enhancements
90 |
91 | - Add support of nuxt public runtime config ([874231c](https://github.com/zadigetvoltaire/nuxt-gtm/commit/874231c))
92 |
93 | ### 🩹 Fixes
94 |
95 | - Build - move defu in dependencies instead of dev dependencies ([a770ed1](https://github.com/zadigetvoltaire/nuxt-gtm/commit/a770ed1))
96 |
97 | ### ❤️ Contributors
98 |
99 | - LouisMazel
100 |
101 | ## v0.0.7
102 |
103 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.6...v0.0.7)
104 |
105 |
106 | ### 🏡 Chore
107 |
108 | - Upgrade dependencies ([da19d18](https://github.com/zadigetvoltaire/nuxt-gtm/commit/da19d18))
109 |
110 | ### ❤️ Contributors
111 |
112 | - LouisMazel
113 |
114 | ## v0.0.6
115 |
116 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.5...v0.0.6)
117 |
118 |
119 | ### 💅 Refactors
120 |
121 | - Add documentation link in devtools view ([1c8c0da](https://github.com/zadigetvoltaire/nuxt-gtm/commit/1c8c0da))
122 |
123 | ### ❤️ Contributors
124 |
125 | - LouisMazel
126 |
127 | ## v0.0.5
128 |
129 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.4...v0.0.5)
130 |
131 |
132 | ### 💅 Refactors
133 |
134 | - Add zadig&voltaire mentions in devtools view ([f83c50a](https://github.com/zadigetvoltaire/nuxt-gtm/commit/f83c50a))
135 |
136 | ### 🏡 Chore
137 |
138 | - Add logo svg ([9b9f1a2](https://github.com/zadigetvoltaire/nuxt-gtm/commit/9b9f1a2))
139 | - Replace ZV mention ([8812ade](https://github.com/zadigetvoltaire/nuxt-gtm/commit/8812ade))
140 |
141 | ### ❤️ Contributors
142 |
143 | - LouisMazel
144 |
145 | ## v0.0.4
146 |
147 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.3...v0.0.4)
148 |
149 |
150 | ### 🚀 Enhancements
151 |
152 | - Implementation of the useGtm composable directly in the module to take advantage of auto import ([5c6cb1c](https://github.com/zadigetvoltaire/nuxt-gtm/commit/5c6cb1c))
153 |
154 | ### 📖 Documentation
155 |
156 | - Add logo and zv mentions in README ([26f9419](https://github.com/zadigetvoltaire/nuxt-gtm/commit/26f9419))
157 |
158 | ### ❤️ Contributors
159 |
160 | - LouisMazel
161 |
162 | ## v0.0.3
163 |
164 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.2...v0.0.3)
165 |
166 |
167 | ### 🚀 Enhancements
168 |
169 | - Display gtm options in nuxt devtools ([d4f0e06](https://github.com/zadigetvoltaire/nuxt-gtm/commit/d4f0e06))
170 |
171 | ### 🩹 Fixes
172 |
173 | - Inject gtm plugin only on client side ([8ec1b62](https://github.com/zadigetvoltaire/nuxt-gtm/commit/8ec1b62))
174 | - Typo in keywords ([d0f70f1](https://github.com/zadigetvoltaire/nuxt-gtm/commit/d0f70f1))
175 |
176 | ### 📖 Documentation
177 |
178 | - Typo ([ac68317](https://github.com/zadigetvoltaire/nuxt-gtm/commit/ac68317))
179 |
180 | ### 🏡 Chore
181 |
182 | - Remove debug log ([0cd8fdf](https://github.com/zadigetvoltaire/nuxt-gtm/commit/0cd8fdf))
183 |
184 | ### 🤖 CI
185 |
186 | - Enable pipeline for all PR on main branch ([6163b6c](https://github.com/zadigetvoltaire/nuxt-gtm/commit/6163b6c))
187 |
188 | ### ❤️ Contributors
189 |
190 | - LouisMazel
191 | - Mazel
192 |
193 | ## v0.0.2
194 |
195 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.1...v0.0.2)
196 |
197 |
198 | ### 🤖 CI
199 |
200 | - Remove run of tests in publish pipeline ([90fb0f4](https://github.com/zadigetvoltaire/nuxt-gtm/commit/90fb0f4))
201 |
202 | ### ❤️ Contributors
203 |
204 | - LouisMazel
205 |
206 | ## v0.0.1
207 |
208 | [compare changes](https://github.com/zadigetvoltaire/nuxt-gtm/compare/v0.0.0...v0.0.1)
209 |
210 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | # Nuxt GTM
10 |
11 | [![npm version][npm-version-src]][npm-version-href]
12 | [![npm downloads][npm-downloads-src]][npm-downloads-href]
13 | [![License][license-src]][license-href]
14 | [![Nuxt][nuxt-src]][nuxt-href]
15 |
16 | > Nuxt Google Tag Manager module integrated with the [Nuxt Devtools](https://github.com/nuxt/devtools) for Nuxt 3.
17 | >
18 | > This library is an Nuxt 3 module wrapper of the [@gtm-support/vue-gtm](https://github.com/gtm-support/vue-gtm) plugin
19 |
20 | - [✨ Release Notes](/CHANGELOG.md)
21 |
22 | ## Quick Setup
23 |
24 | 1. Add `@zadigetvoltaire/nuxt-gtm` dependency to your project
25 |
26 | ```bash
27 | # Using pnpm
28 | pnpm add -D @zadigetvoltaire/nuxt-gtm
29 |
30 | # Using yarn
31 | yarn add --dev @zadigetvoltaire/nuxt-gtm
32 |
33 | # Using npm
34 | npm install --save-dev @zadigetvoltaire/nuxt-gtm
35 | ```
36 |
37 | 2. Add `@zadigetvoltaire/nuxt-gtm` to the `modules` section of `nuxt.config.ts`
38 |
39 | ```ts
40 | export default defineNuxtConfig({
41 | modules: [
42 | '@zadigetvoltaire/nuxt-gtm'
43 | ],
44 | })
45 | ```
46 |
47 | 3. Add configuration in `nuxtConfig.gtm` or in `nuxtConfig.runtimeConfig.public.gtm`
48 |
49 | This module supports 2 ways of configuration:
50 | - Directly in key `gtm` of the Nuxt config
51 | - In public runtimeConfig: useful to override the config with environment variables and handle multiple environments
52 |
53 | ```ts
54 | export default defineNuxtConfig({
55 | ...
56 | gtm: {
57 | id: 'GTM-xxxxxx', // Your GTM single container ID, array of container ids ['GTM-xxxxxx', 'GTM-yyyyyy'] or array of objects [{id: 'GTM-xxxxxx', queryParams: { gtm_auth: 'abc123', gtm_preview: 'env-4', gtm_cookies_win: 'x'}}, {id: 'GTM-yyyyyy', queryParams: {gtm_auth: 'abc234', gtm_preview: 'env-5', gtm_cookies_win: 'x'}}], // Your GTM single container ID or array of container ids ['GTM-xxxxxx', 'GTM-yyyyyy']
58 | queryParams: {
59 | // Add URL query string when loading gtm.js with GTM ID (required when using custom environments)
60 | gtm_auth: 'AB7cDEf3GHIjkl-MnOP8qr',
61 | gtm_preview: 'env-4',
62 | gtm_cookies_win: 'x',
63 | },
64 | defer: false, // Script can be set to `defer` to speed up page load at the cost of less accurate results (in case visitor leaves before script is loaded, which is unlikely but possible). Defaults to false, so the script is loaded `async` by default
65 | compatibility: false, // Will add `async` and `defer` to the script tag to not block requests for old browsers that do not support `async`
66 | nonce: '2726c7f26c', // Will add `nonce` to the script tag
67 | enabled: true, // defaults to true. Plugin can be disabled by setting this to false for Ex: enabled: !!GDPR_Cookie (optional)
68 | debug: true, // Whether or not display console logs debugs (optional)
69 | loadScript: true, // Whether or not to load the GTM Script (Helpful if you are including GTM manually, but need the dataLayer functionality in your components) (optional)
70 | enableRouterSync: true, // Pass the router instance of your app to automatically sync with router (optional)
71 | ignoredViews: ['homepage'], // Don't trigger events for specified router names (optional)
72 | trackOnNextTick: false, // Whether or not call trackView in Vue.nextTick
73 | devtools: true, // (optional)
74 | }
75 | ...
76 | runtimeConfig: {
77 | public: {
78 | gtm: {
79 | id: 'GTM-xxxxxx',
80 | queryParams: {
81 | gtm_auth: 'AB7cDEf3GHIjkl-MnOP8qr',
82 | gtm_preview: 'env-4',
83 | gtm_cookies_win: 'x',
84 | },
85 | defer: false,
86 | compatibility: false,
87 | nonce: '2726c7f26c',
88 | enabled: true,
89 | debug: true,
90 | loadScript: true,
91 | enableRouterSync: true,
92 | ignoredViews: ['homepage'],
93 | trackOnNextTick: false,
94 | devtools: true,
95 | }
96 | }
97 | }
98 | })
99 | ```
100 |
101 | ## Documentation
102 |
103 | Please refer to the [@gtm-support/vue-gtm documentation](https://github.com/gtm-support/vue-gtm#documentation)
104 |
105 | ## Composition API - useGtm composable
106 |
107 | Example:
108 |
109 | ```vue
110 |
111 |
114 |
117 |
118 |
119 |
137 | ```
138 |
139 | ## Options API
140 |
141 | ```ts
142 | export default {
143 | methods: {
144 | triggerEvent() {
145 | this.$gtm.trackEvent({
146 | event: 'event name',
147 | category: 'category',
148 | action: 'click',
149 | label: 'My custom component trigger',
150 | value: 5000,
151 | noninteraction: false,
152 | })
153 | }
154 | }
155 | }
156 | ```
157 |
158 | ## Modules options
159 |
160 | The modules inherit the options of the plugin [@gtm-support/vue-gtm](https://github.com/gtm-support/vue-gtm#configuration), except `vueRouter` entry replaced by `enableRouterSync`.
161 |
162 | ```ts
163 | type ModuleOptions = {
164 | // SPECIFIC MODULES OPTIONS
165 | /**
166 | * Enable Nuxt Devtools integration
167 | *
168 | * @default true
169 | */
170 | devtools?: boolean
171 | /**
172 | * Synchronise GTM with NuxtRouter
173 | */
174 | enableRouterSync?: boolean
175 |
176 | // PLUGIN AND MODULE OPTIONS
177 |
178 | /**
179 | * Derive additional event data after navigation.
180 | */
181 | vueRouterAdditionalEventData?: (to: RouteLocationNormalized, from: RouteLocationNormalized) => Record | Promise>;
182 | /**
183 | * Don't trigger events for specified router names.
184 | */
185 | ignoredViews?: string[] | ((to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean);
186 | /**
187 | * Whether or not call `trackView` in `Vue.nextTick`.
188 | */
189 | trackOnNextTick?: boolean;
190 | /**
191 | * Your GTM single container ID, array of container ids or array of objects.
192 | *
193 | * @example
194 | * 'GTM-xxxxxx'
195 | * // or
196 | * ['GTM-xxxxxx', 'GTM-yyyyyy']
197 | * // or
198 | * [{
199 | * id: 'GTM-xxxxxx',
200 | * queryParams: {
201 | * gtm_auth: 'abc123',
202 | * gtm_preview: 'env-4',
203 | * gtm_cookies_win: 'x'
204 | * }
205 | * }, {
206 | * id: 'GTM-yyyyyy',
207 | * queryParams: {
208 | * gtm_auth: 'abc234',
209 | * gtm_preview: 'env-5',
210 | * gtm_cookies_win: 'x'
211 | * }
212 | * }]
213 | */
214 | id: string | string[] | GtmIdContainer[];
215 | /**
216 | * Add url query string when load gtm.js with GTM ID.
217 | */
218 | queryParams?: GtmQueryParams;
219 | /**
220 | * Script can be set to `defer` to speed up page load at the cost of less accurate results (in case visitor leaves before script is loaded, which is unlikely but possible).
221 | *
222 | * Defaults to false, so the script is loaded `async` by default.
223 | *
224 | * @default false
225 | */
226 | defer?: boolean;
227 | /**
228 | * Will add `async` and `defer` to the script tag to not block requests for old browsers that do not support `async`.
229 | *
230 | * @default false
231 | */
232 | compatibility?: boolean;
233 | /**
234 | * Will add `nonce` to the script tag.
235 | *
236 | * @see [Using Google Tag Manager with a Content Security Policy](https://developers.google.com/tag-manager/web/csp)
237 | */
238 | nonce?: string;
239 | /**
240 | * The URL of the script; useful for server-side GTM.
241 | *
242 | * @default https://www.googletagmanager.com/gtm.js
243 | */
244 | source?: string;
245 | /**
246 | * Plugin can be disabled by setting this to `false`.
247 | *
248 | * @example enabled: !!GDPR_Cookie
249 | * @default true
250 | */
251 | enabled?: boolean;
252 | /**
253 | * Whether or not to display console logs debugs.
254 | */
255 | debug?: boolean;
256 | /**
257 | * Whether or not to load the GTM Script.
258 | *
259 | * Helpful if you are including GTM manually, but need the dataLayer functionality in your components.
260 | */
261 | loadScript?: boolean;
262 | /**
263 | * The property of Track view event.
264 | *
265 | * @example trackViewEventProperty: 'track-view-event-demo'
266 | * @default content-view
267 | */
268 | trackViewEventProperty?: string;
269 | }
270 | ```
271 |
272 | ---
273 |
274 | That's it! You can now use Nuxt GTM in your Nuxt app ✨
275 |
276 | ## Contributing
277 |
278 | ```bash
279 | # Install dependencies, prepare apps & run dev server
280 | make start
281 |
282 | # Run dev server
283 | pnpm dev
284 |
285 | # Develop with playground, with bundled client ui
286 | pnpm play:prod
287 |
288 | # Run ESLint
289 | pnpm lint
290 |
291 | # Run Vitest
292 | pnpm test
293 | pnpm test:watch
294 | ```
295 |
296 | ## Release new version
297 |
298 | 1. Execute release command
299 |
300 | ⚠ This command should be executed only on the main branch
301 |
302 | This command will:
303 |
304 | - Generate the CHANGELOG.md and push it with a release commit
305 | - Bump the package version
306 | - Create and push the new tag
307 | - Create a github release to trigger the library publish pipeline
308 |
309 | ```bash
310 | pnpm release
311 | ```
312 |
313 | ---
314 |
315 | © Zadig&Voltaire is a registered trademark of ZV FRANCE
316 |
317 |
318 | [npm-version-src]: https://img.shields.io/npm/v/@zadigetvoltaire/nuxt-gtm/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
319 | [npm-version-href]: https://npmjs.com/package/@zadigetvoltaire/nuxt-gtm
320 |
321 | [npm-downloads-src]: https://img.shields.io/npm/dm/@zadigetvoltaire/nuxt-gtm.svg?style=flat&colorA=18181B&colorB=28CF8D
322 | [npm-downloads-href]: https://npmjs.com/package/@zadigetvoltaire/nuxt-gtm
323 |
324 | [license-src]: https://img.shields.io/npm/l/@zadigetvoltaire/nuxt-gtm.svg?style=flat&colorA=18181B&colorB=28CF8D
325 | [license-href]: https://npmjs.com/package/@zadigetvoltaire/nuxt-gtm
326 |
327 | [nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
328 | [nuxt-href]: https://nuxt.com
329 |
--------------------------------------------------------------------------------