Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 25 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
![npm](https://img.shields.io/npm/v/@magicul/next-google-tag-manager)
![GitHub Repo stars](https://img.shields.io/github/stars/XD2Sketch/next-google-tag-manager?style=social)

A lightweight Next 13 library to easily implement Google Tag Manager in your projects. This package forwards all of the page changes to Google Tag Manager so you can easily track your users.
A lightweight Next 13 library to easily implement Google Tag Manager
in your projects. This package forwards all of the page changes to
Google Tag Manager so you can easily track your users.

## Installation

Expand All @@ -24,29 +26,36 @@ yarn add @magicul/next-google-tag-manager

## Usage

### Setting up the environment variables
### Using the GoogleTagManager component

Create a `.env.local` file in the root of your project and add the following variables:

```env
NEXT_PUBLIC_GTM_ID=<YOUR-GTM-ID>
```

### Importing the component

To initialize Google Tag Manager, add `<GoogleTagManager />` to `app/layout.tsx` like this:
To initialize Google Tag Manager, add `<GoogleTagManager />`
to `app/layout.tsx` like this:

```tsx
import GoogleTagManager from '@magicul/next-google-tag-manager';

const RootLayout = ({ children }) => (
<html lang="en">
<body>
<GoogleTagManager />
{children}
</body>
<body>
<GoogleTagManager id="GTM-XXXXX" />
{children}
</body>
</html>
);
```

This package utilizes [next/script](https://nextjs.org/docs/basic-features/script), which means you **can't** place it inside a `next/head`.
Note: This package
utilizes [next/script](https://nextjs.org/docs/basic-features/script),
which means you **can't** place it inside a `next/head`.

### Configuring

To customize the way you load Google Tag Manager, you can pass the
following props to the component:

| Prop name | Type | Default value | Description |
|-------------|--------|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| id | string | - | The ID of your Google Tag Manager container |
| server | string | www.googletagmanager.com | The tagging server that is used, you can configure your own server here or use the default Google Tag Manager server by default. This is used for server side tagging. Please only put the domain, subdomain and top level domain here to make it work correctly. |
| auth | string | - | Authentication string for the container configuration. |
| environment | string | - | The environment that is used, see [Environments - Tag Manager Help](https://support.google.com/tagmanager/answer/6311518?hl=en) for more information |
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@magicul/next-google-tag-manager",
"description": "A lightweight Next 13 compatible Google Tag Manager package.",
"version": "1.0.0",
"version": "2.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"homepage": "https://github.com/XD2Sketch/next-google-tag-manager#readme",
Expand Down
22 changes: 16 additions & 6 deletions src/components/GoogleTagManager.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
'use client';

import React, { useEffect } from 'react';
import React, { FC, useEffect } from 'react';
import Script from "next/script";
import { GTM_ID, pageview } from '../utils/gtm';
import {
getIFrameURL,
getScriptQueryString,
GoogleTagManagerArgs,
pageview,
} from '../utils/gtm';
import { usePathname, useSearchParams } from 'next/navigation';

const GoogleTagManager = () => {
const GoogleTagManager: FC<GoogleTagManagerArgs> = ({
id,
server = 'www.googletagmanager.com',
auth,
environment,
}) => {
const pathname = usePathname();
const searchParams = useSearchParams();

Expand All @@ -18,7 +28,7 @@ const GoogleTagManager = () => {
<noscript>
<iframe
title="gtm"
src={`https://www.googletagmanager.com/ns.html?id=${GTM_ID}`}
src={getIFrameURL({ id, server, auth, environment })}
height="0"
width="0"
style={{ display: 'none', visibility: 'hidden' }}
Expand All @@ -32,8 +42,8 @@ const GoogleTagManager = () => {
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer', '${GTM_ID}');
'https://${server}/gtm.js?id='+i+dl ${getScriptQueryString(auth, environment)};f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer', '${id}');
`,
}}
/>
Expand Down
37 changes: 36 additions & 1 deletion src/utils/gtm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,42 @@ interface ICustomWindow extends Window {

declare let window: ICustomWindow;

export const GTM_ID = process.env.NEXT_PUBLIC_GTM_ID;
export type GoogleTagManagerArgs = {
id: string;
server?: string;
auth?: string;
environment?: string;
}

export const getIFrameURL = ({ id, server, environment, auth }: GoogleTagManagerArgs) => {
const BASE_URL = `https://${server}/ns.html`;

if (!id) {
console.warn('next-google-tag-manager: It looks like you forgot to configure your Google Tag Manager. For more information please check https://github.com/XD2Sketch/next-google-tag-manager#usage');
}

const queryParams = new URLSearchParams({ id });

if (auth) {
queryParams.append('gtm_auth', auth);
}

if (environment) {
queryParams.append('gtm_preview', `env-${environment}`);
queryParams.append('gtm_cookies_win', 'x');
}

return `${BASE_URL}?${queryParams.toString()}`;
}

export const getScriptQueryString = (auth?: string, environment?: string) => {
const string = '';

if (auth) string.concat(`&gtm_auth=${auth}`);
if (environment) string.concat(`&gtm_preview=env-${environment}&gtm_cookies_win=x`);

return string;
}

export const pageview = (url: string) => {
if (!window.dataLayer) return;
Expand Down