Skip to content

Commit 5a72a2d

Browse files
feat: Adding gclid support (#37)
* feat: adding gclid support * chore: fix gclid update on same session
1 parent e5e3fa5 commit 5a72a2d

File tree

6 files changed

+95
-15
lines changed

6 files changed

+95
-15
lines changed

README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ That's it! You can now use Nuxt UTM in your Nuxt app ✨
5353

5454
## Usage
5555

56-
You can use ```useNuxtUTM``` composable to access the UTM object:
56+
You can use `useNuxtUTM` composable to access the UTM object:
5757

5858
```vue
5959
<script setup>
6060
const utm = useNuxtUTM();
6161
</script>
6262
```
63+
6364
> Remember: You don't need to import the composable because nuxt imports it automatically.
6465
6566
Alternatively, you can get the UTM information through the Nuxt App with the following instructions:
@@ -95,6 +96,10 @@ Regardless of the option you choose to use the module, the `utm' object will con
9596
},
9697
},
9798
sessionId: "beai1gx7dg",
99+
gclidParams: {
100+
gclid: "CjklsefawEFRfeafads",
101+
gad_source: "1",
102+
},
98103
}, // the first item in this array is the most recent
99104
// ... old items
100105
];
@@ -106,7 +111,7 @@ In the `$utm` array, each entry provides a `timestamp` indicating when the UTM p
106111

107112
### Devenv
108113

109-
You can take advantage of [devenv.sh](https://devenv.sh) to quickly create the development environment for this this project. Use it in combination with [direnv](https://direnv.net/) to quickly load all the environment while navigating into the project directory in your shell.
114+
You can take advantage of [devenv.sh](https://devenv.sh) to quickly create the development environment for this this project. Use it in combination with [direnv](https://direnv.net/) to quickly load all the environment while navigating into the project directory in your shell.
110115

111116
```bash
112117
# Install dependencies

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nuxt-utm",
3-
"version": "0.2.2",
3+
"version": "0.2.3",
44
"description": "A Nuxt 3 module for tracking UTM parameters.",
55
"keywords": [
66
"nuxt",
@@ -61,4 +61,4 @@
6161
"playwright-core": "^1.39.0",
6262
"vitest": "^0.33.0"
6363
}
64-
}
64+
}

src/runtime/plugin.ts

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
getUtmParams,
77
getAdditionalInfo,
88
isRepeatedEntry,
9+
urlHasGCLID,
10+
getGCLID,
911
} from "./utm";
1012
import { ref } from "vue";
1113
import { defineNuxtPlugin } from "#app";
@@ -40,6 +42,10 @@ export default defineNuxtPlugin((nuxtApp) => {
4042
sessionId,
4143
};
4244

45+
if (urlHasGCLID) {
46+
dataObject.gclidParams = getGCLID(query);
47+
}
48+
4349
// Exit if the last entry is the same as the new entry
4450
if (isRepeatedEntry(data, dataObject)) return;
4551

src/runtime/utm.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Ref } from "vue";
22
import { LocationQuery } from "vue-router";
3-
import { UTMParams, AdditionalInfo, DataObject } from "nuxt-utm";
3+
import { UTMParams, AdditionalInfo, DataObject, GCLIDParams } from "nuxt-utm";
44

55
export const generateSessionId = () => {
66
return Math.random().toString(36).substring(2, 15);
@@ -35,7 +35,7 @@ export const urlHasUtmParams = (query: LocationQuery): boolean => {
3535
query.utm_medium ||
3636
query.utm_campaign ||
3737
query.utm_term ||
38-
query.utm_content
38+
query.utm_content,
3939
);
4040
};
4141

@@ -49,6 +49,17 @@ export const getUtmParams = (query: LocationQuery): UTMParams => {
4949
};
5050
};
5151

52+
export const urlHasGCLID = (query: LocationQuery): boolean => {
53+
return Boolean(query.gclid || query.gad_source);
54+
};
55+
56+
export const getGCLID = (query: LocationQuery): GCLIDParams => {
57+
return {
58+
gclid: query.gclid?.toString(),
59+
gad_source: query.gad_source?.toString(),
60+
};
61+
};
62+
5263
export const getAdditionalInfo = (): AdditionalInfo => {
5364
return {
5465
referrer: document.referrer,
@@ -64,11 +75,13 @@ export const getAdditionalInfo = (): AdditionalInfo => {
6475

6576
export const isRepeatedEntry = (
6677
data: Ref<DataObject[]>,
67-
currentEntry: DataObject
78+
currentEntry: DataObject,
6879
): boolean => {
6980
const lastEntry = data.value?.[0];
7081
const lastUtm = lastEntry?.utmParams;
7182
const newUtm = currentEntry.utmParams;
83+
const lastGCLID = lastEntry?.gclidParams;
84+
const newGCLID = currentEntry.gclidParams;
7285

7386
return (
7487
lastEntry &&
@@ -77,6 +90,8 @@ export const isRepeatedEntry = (
7790
lastUtm.utm_medium === newUtm.utm_medium &&
7891
lastUtm.utm_source === newUtm.utm_source &&
7992
lastUtm.utm_term === newUtm.utm_term &&
80-
lastEntry.sessionId === currentEntry.sessionId
93+
lastEntry.sessionId === currentEntry.sessionId &&
94+
lastGCLID?.gad_source === newGCLID?.gad_source &&
95+
lastGCLID?.gclid === newGCLID?.gclid
8196
);
8297
};

test/integration.test.ts

+55-7
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ describe("ssr", async () => {
1515

1616
beforeEach(async () => {
1717
page = await createPage(
18-
"/?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content"
18+
"/?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content&gad_source=1&gclid=testKey",
1919
);
2020
const rawData = await page.evaluate(() =>
21-
window.localStorage.getItem("nuxt-utm-data")
21+
window.localStorage.getItem("nuxt-utm-data"),
2222
);
2323
entries = await JSON.parse(rawData ?? "[]");
2424
});
@@ -70,7 +70,7 @@ describe("ssr", async () => {
7070
it("Doesn't store anything after a page reload with the same UTM params and session", async () => {
7171
await page.reload();
7272
const rawData = await page?.evaluate(() =>
73-
window.localStorage.getItem("nuxt-utm-data")
73+
window.localStorage.getItem("nuxt-utm-data"),
7474
);
7575
entries = await JSON.parse(rawData ?? "[]");
7676
expect(entries.length).toEqual(1);
@@ -79,10 +79,10 @@ describe("ssr", async () => {
7979
it("Stores a new value if the UTM params are different but the session is the same", async () => {
8080
const urlBase = page.url().split("?")[0];
8181
await page.goto(
82-
`${urlBase}/?utm_source=test_source2&utm_medium=test_medium2&utm_campaign=test_campaign2&utm_term=test_term2&utm_content=test_content2`
82+
`${urlBase}/?utm_source=test_source2&utm_medium=test_medium2&utm_campaign=test_campaign2&utm_term=test_term2&utm_content=test_content2`,
8383
);
8484
const rawData = await page.evaluate(() =>
85-
localStorage.getItem("nuxt-utm-data")
85+
localStorage.getItem("nuxt-utm-data"),
8686
);
8787
entries = await JSON.parse(rawData ?? "[]");
8888
expect(entries[0].utmParams).toEqual({
@@ -96,11 +96,11 @@ describe("ssr", async () => {
9696

9797
it("Stores a new value if the UTM params are the same but the session is different", async () => {
9898
await page.evaluate(() =>
99-
sessionStorage.setItem("nuxt-utm-session-id", "old-session")
99+
sessionStorage.setItem("nuxt-utm-session-id", "old-session"),
100100
);
101101
await page.reload();
102102
const rawData = await page.evaluate(() =>
103-
localStorage.getItem("nuxt-utm-data")
103+
localStorage.getItem("nuxt-utm-data"),
104104
);
105105
entries = await JSON.parse(rawData ?? "[]");
106106
expect(entries[0].utmParams).toEqual({
@@ -112,4 +112,52 @@ describe("ssr", async () => {
112112
});
113113
});
114114
});
115+
116+
describe("GCLID params", () => {
117+
it("Stores GCLID params", () => {
118+
expect(entries?.[0].gclidParams).toEqual({
119+
gclid: "testKey",
120+
gad_source: "1",
121+
});
122+
});
123+
124+
it("Doesn't store anything after a page reload with the same UTM params and session", async () => {
125+
await page.reload();
126+
const rawData = await page?.evaluate(() =>
127+
window.localStorage.getItem("nuxt-utm-data"),
128+
);
129+
entries = await JSON.parse(rawData ?? "[]");
130+
expect(entries.length).toEqual(1);
131+
});
132+
133+
it("Stores a new value if the GCLID params are different but the session is the same", async () => {
134+
const urlBase = page.url().split("?")[0];
135+
await page.goto(
136+
`${urlBase}/?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content&gad_source=2&gclid=testKey2`,
137+
);
138+
const rawData = await page.evaluate(() =>
139+
localStorage.getItem("nuxt-utm-data"),
140+
);
141+
entries = await JSON.parse(rawData ?? "[]");
142+
expect(entries?.[0].gclidParams).toEqual({
143+
gclid: "testKey2",
144+
gad_source: "2",
145+
});
146+
});
147+
148+
it("Stores a new value if the GCLID params are the same but the session is different", async () => {
149+
await page.evaluate(() =>
150+
sessionStorage.setItem("nuxt-utm-session-id", "old-session"),
151+
);
152+
await page.reload();
153+
const rawData = await page.evaluate(() =>
154+
localStorage.getItem("nuxt-utm-data"),
155+
);
156+
entries = await JSON.parse(rawData ?? "[]");
157+
expect(entries?.[0].gclidParams).toEqual({
158+
gclid: "testKey",
159+
gad_source: "1",
160+
});
161+
});
162+
});
115163
});

types/index.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ declare module "nuxt-utm" {
77
utm_content?: string;
88
}
99

10+
interface GCLIDParams {
11+
gclid?: string;
12+
gad_source?: string;
13+
}
14+
1015
interface AdditionalInfo {
1116
referrer: string;
1217
userAgent: string;
@@ -23,5 +28,6 @@ declare module "nuxt-utm" {
2328
utmParams: UTMParams;
2429
additionalInfo: AdditionalInfo;
2530
sessionId: string;
31+
gclidParams?: GCLIDParams;
2632
}
2733
}

0 commit comments

Comments
 (0)