Skip to content

Commit 253085d

Browse files
authored
feat: support manual script deduping (#148)
1 parent 4c35f73 commit 253085d

22 files changed

+113
-27
lines changed

docs/content/docs/1.guides/1.registry-scripts.md

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,51 @@ of the script, so that it will never load.
9797
You can do this by providing a `mock` value to the registry script.
9898

9999
```ts [nuxt.config.ts]
100-
import { isDevelopment } from 'std-env'
100+
export default defineNuxtConfig({
101+
$production: {
102+
scripts: {
103+
registry: {
104+
googleAnalytics: {
105+
id: 'YOUR_ID',
106+
},
107+
}
108+
}
109+
},
110+
})
111+
```
112+
113+
### Loading multiple of the same script
114+
115+
You may have a setup where you need to load the same registry script multiple times
116+
using different configuration.
117+
118+
By default, they will be deduped and only loaded once, to load multiple instances of the same script, you can provide a unique `key` to the script.
119+
120+
```ts
121+
const { gtag, $script } = useScriptGoogleAnalytics({
122+
id: 'G-TR58L0EF8P',
123+
})
101124

125+
const { gtag: gtag2, $script: $script2 } = useScriptGoogleAnalytics({
126+
// without a key the first script instance will be returned
127+
key: 'gtag2',
128+
id: 'G-1234567890',
129+
})
130+
```
131+
132+
It's important to note that when modifying the key, any environment variables you're using will break.
133+
134+
For example, with `gtag2` as the key, you'd need to provide runtime config as following:
135+
136+
```ts
102137
export default defineNuxtConfig({
103-
scripts: {
104-
registry: {
105-
googleAnalytics: isDevelopment
106-
? 'mock' // script won't load unless manually calling load()
107-
: {
108-
id: 'YOUR_ID',
109-
},
138+
runtimeConfig: {
139+
public: {
140+
scripts: {
141+
gtag2: {
142+
id: '', // NUXT_PUBLIC_SCRIPTS_GTAG2_ID
143+
},
144+
},
110145
},
111146
},
112147
})
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script lang="ts" setup>
2+
import { useHead, useScriptGoogleAnalytics } from '#imports'
3+
4+
useHead({
5+
title: 'Google Analytics',
6+
})
7+
8+
// composables return the underlying api as a proxy object and a $script with the script state
9+
const { gtag: gtag1, $script: $script1 } = useScriptGoogleAnalytics({
10+
key: 'gtag1',
11+
id: 'G-TR58L0EF8P',
12+
})
13+
14+
const { gtag: gtag2, $script: $script2 } = useScriptGoogleAnalytics({
15+
key: 'gtag2',
16+
id: 'G-1234567890',
17+
})
18+
19+
// id set via nuxt scripts module config
20+
gtag1('event', 'page_view', {
21+
page_title: 'Google Analytics',
22+
page_location: 'https://harlanzw.com/third-parties/google-analytics',
23+
page_path: '/third-parties/google-analytics',
24+
})
25+
26+
function triggerConversion() {
27+
gtag2('event', 'conversion')
28+
}
29+
</script>
30+
31+
<template>
32+
<div>
33+
<ClientOnly>
34+
<div>
35+
1 status: {{ $script1.status.value }}
36+
</div>
37+
</ClientOnly>
38+
<ClientOnly>
39+
<div>
40+
2 status: {{ $script2.status.value }}
41+
</div>
42+
</ClientOnly>
43+
<button @click="triggerConversion">
44+
Trigger Conversion
45+
</button>
46+
</div>
47+
</template>

src/runtime/registry/clarity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function useScriptClarity<T extends ClarityApi>(
4949
_options?: ClarityInput,
5050
) {
5151
return useRegistryScript<T, typeof ClarityOptions>(
52-
'clarity',
52+
_options?.key || 'clarity',
5353
options => ({
5454
scriptInput: {
5555
src: `https://www.clarity.ms/tag/${options.id}`,

src/runtime/registry/cloudflare-web-analytics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const CloudflareWebAnalyticsOptions = object({
3838
export type CloudflareWebAnalyticsInput = RegistryScriptInput<typeof CloudflareWebAnalyticsOptions>
3939

4040
export function useScriptCloudflareWebAnalytics<T extends CloudflareWebAnalyticsApi>(_options?: CloudflareWebAnalyticsInput) {
41-
return useRegistryScript<T, typeof CloudflareWebAnalyticsOptions>('cloudflareWebAnalytics', options => ({
41+
return useRegistryScript<T, typeof CloudflareWebAnalyticsOptions>(_options?.key || 'cloudflareWebAnalytics', options => ({
4242
scriptInput: {
4343
'src': 'https://static.cloudflareinsights.com/beacon.min.js',
4444
'data-cf-beacon': JSON.stringify({ token: options.token, spa: options.spa || true }),

src/runtime/registry/crisp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ declare global {
6464

6565
export function useScriptCrisp<T extends CrispApi>(_options?: CrispInput) {
6666
let readyPromise: Promise<void> = Promise.resolve()
67-
return useRegistryScript<T, typeof CrispOptions>('crisp', options => ({
67+
return useRegistryScript<T, typeof CrispOptions>(_options?.key || 'crisp', options => ({
6868
scriptInput: {
6969
src: 'https://client.crisp.chat/l.js', // can't be bundled
7070
},

src/runtime/registry/fathom-analytics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ declare global {
4747
}
4848

4949
export function useScriptFathomAnalytics<T extends FathomAnalyticsApi>(_options?: FathomAnalyticsInput) {
50-
return useRegistryScript<T, typeof FathomAnalyticsOptions>('fathomAnalytics', options => ({
50+
return useRegistryScript<T, typeof FathomAnalyticsOptions>(_options?.key || 'fathomAnalytics', options => ({
5151
scriptInput: {
5252
src: 'https://cdn.usefathom.com/script.js', // can't be bundled
5353
// append the data attr's

src/runtime/registry/google-adsense.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ declare global {
3131
*/
3232
export function useScriptGoogleAdsense<T extends GoogleAdsenseApi>(_options?: GoogleAdsenseInput) {
3333
// Note: inputs.useScriptInput is not usable, needs to be normalized
34-
return useRegistryScript<T, typeof GoogleAdsenseOptions>('googleAdsense', options => ({
34+
return useRegistryScript<T, typeof GoogleAdsenseOptions>(_options?.key || 'googleAdsense', options => ({
3535
scriptInput: {
3636
src: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js',
3737
},

src/runtime/registry/google-maps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ declare global {
3838

3939
export function useScriptGoogleMaps<T extends GoogleMapsApi>(_options?: GoogleMapsInput) {
4040
let readyPromise: Promise<void> = Promise.resolve()
41-
return useRegistryScript<T, typeof GoogleMapsOptions>('googleMaps', (options) => {
41+
return useRegistryScript<T, typeof GoogleMapsOptions>(_options?.key || 'googleMaps', (options) => {
4242
const libraries = options?.libraries || ['places']
4343
return {
4444
scriptInput: {

src/runtime/registry/hotjar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const HotjarOptions = object({
2222
export type HotjarInput = RegistryScriptInput<typeof HotjarOptions>
2323

2424
export function useScriptHotjar<T extends HotjarApi>(_options?: HotjarInput) {
25-
return useRegistryScript<T, typeof HotjarOptions>('hotjar', options => ({
25+
return useRegistryScript<T, typeof HotjarOptions>(_options?.key || 'hotjar', options => ({
2626
scriptInput: {
2727
src: `https://static.hotjar.com/c/hotjar-${options?.id}.js?sv=${options?.sv || 6}`,
2828
},

src/runtime/registry/intercom.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ declare global {
5050
}
5151

5252
export function useScriptIntercom<T extends IntercomApi>(_options?: IntercomInput) {
53-
return useRegistryScript<T, typeof IntercomOptions>('intercom', options => ({
53+
return useRegistryScript<T, typeof IntercomOptions>(_options?.key || 'intercom', options => ({
5454
scriptInput: {
5555
src: joinURL(`https://widget.intercom.io/widget`, options?.app_id || ''),
5656
},

0 commit comments

Comments
 (0)