├── 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 | 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 | 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 | 8 | 9 | 13 | 17 | 18 | -------------------------------------------------------------------------------- /assets/icon-logo-dark.svg: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 17 | 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 | 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 | 32 | 33 | 63 | -------------------------------------------------------------------------------- /client/pages/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 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 | 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 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /assets/zadigetvoltaire-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 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 |
2 |
3 | 4 | Click to see the source 5 | 6 |
7 |
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 | 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 | --------------------------------------------------------------------------------