Skip to content

Commit

Permalink
fix: resolve runtime options in client
Browse files Browse the repository at this point in the history
  • Loading branch information
johannschopplich committed Feb 9, 2024
1 parent aedc6e4 commit 49f9a3c
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 33 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Done! Google tag will now run in your application's client.

If you want to send data to multiple destinations, you can add more than one Google tag ID to your Nuxt configuration in the `tags` module option.

The following example shows how to load a second Google tag that is connected to a Floodlight destination. To send data to Floodlight (tag ID `DC-ZZZZZZ`), add another config command after initializing the first Google tag (tag ID `GT-XXXXXX`):
The following example shows how to load a second Google tag that is connected to a Floodlight destination. To send data to Floodlight (tag ID `DC-ZZZZZZZZZZ`), add another config command after initializing the first Google tag (tag ID `GT-XXXXXXXXXX`):

```ts
// `nuxt.config.ts`
Expand All @@ -70,8 +70,8 @@ export default defineNuxtConfig({

gtag: {
tags: [
'GT-XXXXXX', // Google Ads and GA4
'DC-ZZZZZZ' // Floodlight
'GT-XXXXXXXXXX', // Google Ads and GA4
'DC-ZZZZZZZZZZ' // Floodlight
]
}
})
Expand All @@ -87,15 +87,15 @@ export default defineNuxtConfig({
gtag: {
tags: [
{
id: 'GT-XXXXXX',
id: 'GT-XXXXXXXXXX',
config: {
page_title: 'My Custom Page Title'
page_title: 'GA4'
}
},
{
id: 'DC-ZZZZZZ',
id: 'DC-ZZZZZZZZZZ',
config: {
page_title: 'My Custom Page Title'
page_title: 'Floodlight'
}
}
]
Expand All @@ -119,10 +119,10 @@ export default defineNuxtConfig({
page_title: 'My Custom Page Title'
},

// Or use the tags option to send data to multiple destinations
// To send data to multiple destinations, use this option
tags: [
'GT-XXXXXX', // Google Ads and GA4
'DC-ZZZZZZ' // Floodlight
'DC-ZZZZZZZZZZ' // Floodlight
]
}
})
Expand Down Expand Up @@ -183,8 +183,8 @@ function acceptTracking() {
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | `undefined` | The Google tag ID to use for tracking. |
| `tags` | `string[] \| GoogleTagOptions[]` | `[]` | Google tag IDs to send data to multiple destinations. |
| `config` | `Record<string, any>` | `undefined` | The [configuration parameters](https://developers.google.com/analytics/devguides/collection/ga4/reference/config) to be passed to `gtag.js` on initialization. |
| `tags` | `string[] \| GoogleTagOptions[]` | `[]` | Google tag IDs to send data to multiple destinations. |
| `initialConsent` | `boolean` | `true` | Whether to initially consent to tracking. |
| `loadingStrategy` | `'async' \| 'defer'` | `'defer'` | The loading strategy to be used for the `gtag.js` script. |
| `url` | `string` | `'https://www.googletagmanager.com/gtag/js'` | The URL to the `gtag.js` script. Use this option to load the script from a custom URL. |
Expand Down
1 change: 1 addition & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default defineNuxtConfig({
modules: ['../src/module.ts'],

gtag: {
tags: ['G-ZZZZZZZZZZ'],
initialConsent: false,
},

Expand Down
14 changes: 2 additions & 12 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ export interface ModuleOptions {
url?: string
}

export interface ResolvedModuleOptions extends ModuleOptions {
tags: GoogleTagOptions[]
}

export default defineNuxtModule<ModuleOptions>({
meta: {
name,
Expand All @@ -77,6 +73,8 @@ export default defineNuxtModule<ModuleOptions>({
},
},
defaults: {
id: undefined,
config: undefined,
tags: [],
initialConsent: true,
loadingStrategy: 'defer',
Expand All @@ -85,14 +83,6 @@ export default defineNuxtModule<ModuleOptions>({
setup(options, nuxt) {
const { resolve } = createResolver(import.meta.url)

// Normalize options
options.tags = options.tags!.filter(Boolean).map(
i => typeof i === 'string' ? { id: i } : i,
)

if (options.id)
options.tags.unshift({ id: options.id, config: options.config })

// Add module options to public runtime config
nuxt.options.runtimeConfig.public.gtag = defu(
nuxt.options.runtimeConfig.public.gtag as Required<ModuleOptions>,
Expand Down
16 changes: 10 additions & 6 deletions src/runtime/composables/useGtag.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { withQuery } from 'ufo'
import { disableGtag, enableGtag, gtag, initGtag } from '../gtag'
import type { ResolvedModuleOptions } from '../../module'
import type { ModuleOptions } from '../../module'
import type { Gtag, UseGtagConsentOptions } from '../types'
import { resolveTags } from '../utils'
import { useHead, useRuntimeConfig } from '#imports'

export function useGtag() {
const { tags, url } = useRuntimeConfig().public.gtag as Required<ResolvedModuleOptions>
const options = useRuntimeConfig().public.gtag as Required<ModuleOptions>
const tags = resolveTags(options)

let _gtag: Gtag
// Return a noop function if this composable is called on the server.
Expand All @@ -14,10 +16,12 @@ export function useGtag() {
else if (process.client)
_gtag = gtag

const setConsent = (options: UseGtagConsentOptions) => {
const setConsent = ({
id,
hasConsent = true,
}: UseGtagConsentOptions) => {
if (process.client) {
const hasConsent = options.hasConsent ?? true
const tag = tags?.find(tag => tag.id === options.id) ?? tags?.[0] ?? { id: options.id }
const tag = tags?.find(tag => tag.id === id) ?? (id ? { id } : tags[0])

if (!tag) {
console.error('[nuxt-gtag] Missing Google tag ID')
Expand All @@ -44,7 +48,7 @@ export function useGtag() {

// Inject the Google tag script.
useHead({
script: [{ src: withQuery(url, { id: tag.id }) }],
script: [{ src: withQuery(options.url, { id: tag.id }) }],
})
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/runtime/plugin.client.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { withQuery } from 'ufo'
import type { ResolvedModuleOptions } from '../module'
import type { ModuleOptions } from '../module'
import { initGtag } from './gtag'
import { resolveTags } from './utils'
import { defineNuxtPlugin, useHead, useRuntimeConfig } from '#imports'

export default defineNuxtPlugin({
parallel: true,
setup() {
const { tags, initialConsent, loadingStrategy, url } = useRuntimeConfig().public.gtag as Required<ResolvedModuleOptions>
const options = useRuntimeConfig().public.gtag as Required<ModuleOptions>
const tags = resolveTags(options)

if (!tags.length)
return

initGtag({ tags })

if (!initialConsent)
if (!options.initialConsent)
return

// Sanitize loading strategy to be either `async` or `defer`
const strategy = loadingStrategy === 'async' ? 'async' : 'defer'
const strategy = options.loadingStrategy === 'async' ? 'async' : 'defer'

useHead({
script: [
{
src: withQuery(url, { id: tags[0].id }),
src: withQuery(options.url, { id: tags[0].id }),
[strategy]: true,
},
],
Expand Down
13 changes: 13 additions & 0 deletions src/runtime/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ModuleOptions } from '../module'
import type { GoogleTagOptions } from './types'

export function resolveTags(options: Required<ModuleOptions>) {
// Normalize tags
const tags: GoogleTagOptions[] = [...options.tags].filter(Boolean)
.map(i => typeof i === 'string' ? { id: i } : i)

if (options.id)
tags.unshift({ id: options.id, config: options.config })

return tags
}

0 comments on commit 49f9a3c

Please sign in to comment.