|
1 | | -import { useScript } from "@tracktor/react-utils"; |
2 | | -import { createContext, ReactNode, useMemo } from "react"; |
| 1 | +import { useIsomorphicLayoutEffect, useScript } from "@tracktor/react-utils"; |
| 2 | +import { createContext, ReactNode, useMemo, useRef } from "react"; |
| 3 | +import { injectDataLayer, createNoScript } from "@/utils/utilsGTM"; |
3 | 4 |
|
4 | 5 | interface GoogleTagManagerProviderProps { |
5 | | - id: string; |
| 6 | + id?: `GTM-${string}` | string; |
6 | 7 | options?: { |
7 | 8 | scriptUrl?: string; |
8 | 9 | dataLayerName?: string; |
9 | 10 | }; |
10 | 11 | children: ReactNode; |
11 | 12 | } |
12 | 13 |
|
13 | | -const DEFAULT_SCRIPT_URL = "https://www.googletagmanager.com/gtag/js"; |
14 | | -const DEFAULT_DATA_LAYER_NAME = "dataLayer"; |
| 14 | +interface DefaultContextValue { |
| 15 | + id?: GoogleTagManagerProviderProps["id"]; |
| 16 | + options: { |
| 17 | + scriptUrl: string; |
| 18 | + dataLayerName: string; |
| 19 | + }; |
| 20 | +} |
15 | 21 |
|
16 | | -export const GoogleTagManagerContext = createContext({ |
17 | | - id: "", |
| 22 | +const defaultContextValue = { |
| 23 | + id: undefined, |
18 | 24 | options: { |
19 | | - dataLayerName: DEFAULT_DATA_LAYER_NAME, |
20 | | - scriptUrl: DEFAULT_SCRIPT_URL, |
| 25 | + dataLayerName: "dataLayer", |
| 26 | + scriptUrl: "https://www.googletagmanager.com/gtm.js", |
21 | 27 | }, |
22 | | -}); |
| 28 | +}; |
| 29 | + |
| 30 | +export const GoogleTagManagerContext = createContext<DefaultContextValue>(defaultContextValue); |
23 | 31 |
|
24 | 32 | const GoogleTagManagerProvider = ({ children, id, options }: GoogleTagManagerProviderProps) => { |
| 33 | + const { dataLayerName, scriptUrl } = { ...options, ...defaultContextValue.options }; |
| 34 | + const isInitialized = useRef<boolean>(false); |
| 35 | + |
25 | 36 | const value = useMemo( |
26 | 37 | () => ({ |
27 | 38 | id, |
28 | 39 | options: { |
29 | | - dataLayerName: options?.dataLayerName || DEFAULT_DATA_LAYER_NAME, |
30 | | - scriptUrl: options?.scriptUrl || DEFAULT_SCRIPT_URL, |
| 40 | + dataLayerName, |
| 41 | + scriptUrl, |
31 | 42 | }, |
32 | 43 | }), |
33 | | - [id, options] |
| 44 | + [dataLayerName, id, scriptUrl] |
34 | 45 | ); |
35 | 46 |
|
| 47 | + // Initialize GTM |
| 48 | + useIsomorphicLayoutEffect(() => { |
| 49 | + if (!id || isInitialized.current) { |
| 50 | + return; |
| 51 | + } |
| 52 | + |
| 53 | + isInitialized.current = true; |
| 54 | + |
| 55 | + injectDataLayer(dataLayerName); |
| 56 | + createNoScript(id); |
| 57 | + }, [dataLayerName, id]); |
| 58 | + |
36 | 59 | // Load the script asynchronously |
37 | | - useScript(`${value.options.scriptUrl}?id=${value.id}`, !!value.id); |
| 60 | + useScript(`${value.options.scriptUrl}?id=${value.id}`, { enable: !!value.id, position: "head-start" }); |
38 | 61 |
|
39 | 62 | return <GoogleTagManagerContext.Provider value={value}>{children}</GoogleTagManagerContext.Provider>; |
40 | 63 | }; |
|
0 commit comments