Skip to content

Commit

Permalink
feat: Adding gclid support (#37)
Browse files Browse the repository at this point in the history
* feat: adding gclid support

* chore: fix gclid update on same session
  • Loading branch information
JosueDiaz1722 authored Jan 27, 2025
1 parent e5e3fa5 commit 5a72a2d
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 15 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ That's it! You can now use Nuxt UTM in your Nuxt app ✨

## Usage

You can use ```useNuxtUTM``` composable to access the UTM object:
You can use `useNuxtUTM` composable to access the UTM object:

```vue
<script setup>
const utm = useNuxtUTM();
</script>
```

> Remember: You don't need to import the composable because nuxt imports it automatically.
Alternatively, you can get the UTM information through the Nuxt App with the following instructions:
Expand Down Expand Up @@ -95,6 +96,10 @@ Regardless of the option you choose to use the module, the `utm' object will con
},
},
sessionId: "beai1gx7dg",
gclidParams: {
gclid: "CjklsefawEFRfeafads",
gad_source: "1",
},
}, // the first item in this array is the most recent
// ... old items
];
Expand All @@ -106,7 +111,7 @@ In the `$utm` array, each entry provides a `timestamp` indicating when the UTM p

### Devenv

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.
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.

```bash
# Install dependencies
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuxt-utm",
"version": "0.2.2",
"version": "0.2.3",
"description": "A Nuxt 3 module for tracking UTM parameters.",
"keywords": [
"nuxt",
Expand Down Expand Up @@ -61,4 +61,4 @@
"playwright-core": "^1.39.0",
"vitest": "^0.33.0"
}
}
}
6 changes: 6 additions & 0 deletions src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
getUtmParams,
getAdditionalInfo,
isRepeatedEntry,
urlHasGCLID,
getGCLID,
} from "./utm";
import { ref } from "vue";
import { defineNuxtPlugin } from "#app";
Expand Down Expand Up @@ -40,6 +42,10 @@ export default defineNuxtPlugin((nuxtApp) => {
sessionId,
};

if (urlHasGCLID) {
dataObject.gclidParams = getGCLID(query);
}

// Exit if the last entry is the same as the new entry
if (isRepeatedEntry(data, dataObject)) return;

Expand Down
23 changes: 19 additions & 4 deletions src/runtime/utm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Ref } from "vue";
import { LocationQuery } from "vue-router";
import { UTMParams, AdditionalInfo, DataObject } from "nuxt-utm";
import { UTMParams, AdditionalInfo, DataObject, GCLIDParams } from "nuxt-utm";

export const generateSessionId = () => {
return Math.random().toString(36).substring(2, 15);
Expand Down Expand Up @@ -35,7 +35,7 @@ export const urlHasUtmParams = (query: LocationQuery): boolean => {
query.utm_medium ||
query.utm_campaign ||
query.utm_term ||
query.utm_content
query.utm_content,
);
};

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

export const urlHasGCLID = (query: LocationQuery): boolean => {
return Boolean(query.gclid || query.gad_source);
};

export const getGCLID = (query: LocationQuery): GCLIDParams => {
return {
gclid: query.gclid?.toString(),
gad_source: query.gad_source?.toString(),
};
};

export const getAdditionalInfo = (): AdditionalInfo => {
return {
referrer: document.referrer,
Expand All @@ -64,11 +75,13 @@ export const getAdditionalInfo = (): AdditionalInfo => {

export const isRepeatedEntry = (
data: Ref<DataObject[]>,
currentEntry: DataObject
currentEntry: DataObject,
): boolean => {
const lastEntry = data.value?.[0];
const lastUtm = lastEntry?.utmParams;
const newUtm = currentEntry.utmParams;
const lastGCLID = lastEntry?.gclidParams;
const newGCLID = currentEntry.gclidParams;

return (
lastEntry &&
Expand All @@ -77,6 +90,8 @@ export const isRepeatedEntry = (
lastUtm.utm_medium === newUtm.utm_medium &&
lastUtm.utm_source === newUtm.utm_source &&
lastUtm.utm_term === newUtm.utm_term &&
lastEntry.sessionId === currentEntry.sessionId
lastEntry.sessionId === currentEntry.sessionId &&
lastGCLID?.gad_source === newGCLID?.gad_source &&
lastGCLID?.gclid === newGCLID?.gclid
);
};
62 changes: 55 additions & 7 deletions test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ describe("ssr", async () => {

beforeEach(async () => {
page = await createPage(
"/?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content"
"/?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",
);
const rawData = await page.evaluate(() =>
window.localStorage.getItem("nuxt-utm-data")
window.localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
});
Expand Down Expand Up @@ -70,7 +70,7 @@ describe("ssr", async () => {
it("Doesn't store anything after a page reload with the same UTM params and session", async () => {
await page.reload();
const rawData = await page?.evaluate(() =>
window.localStorage.getItem("nuxt-utm-data")
window.localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries.length).toEqual(1);
Expand All @@ -79,10 +79,10 @@ describe("ssr", async () => {
it("Stores a new value if the UTM params are different but the session is the same", async () => {
const urlBase = page.url().split("?")[0];
await page.goto(
`${urlBase}/?utm_source=test_source2&utm_medium=test_medium2&utm_campaign=test_campaign2&utm_term=test_term2&utm_content=test_content2`
`${urlBase}/?utm_source=test_source2&utm_medium=test_medium2&utm_campaign=test_campaign2&utm_term=test_term2&utm_content=test_content2`,
);
const rawData = await page.evaluate(() =>
localStorage.getItem("nuxt-utm-data")
localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries[0].utmParams).toEqual({
Expand All @@ -96,11 +96,11 @@ describe("ssr", async () => {

it("Stores a new value if the UTM params are the same but the session is different", async () => {
await page.evaluate(() =>
sessionStorage.setItem("nuxt-utm-session-id", "old-session")
sessionStorage.setItem("nuxt-utm-session-id", "old-session"),
);
await page.reload();
const rawData = await page.evaluate(() =>
localStorage.getItem("nuxt-utm-data")
localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries[0].utmParams).toEqual({
Expand All @@ -112,4 +112,52 @@ describe("ssr", async () => {
});
});
});

describe("GCLID params", () => {
it("Stores GCLID params", () => {
expect(entries?.[0].gclidParams).toEqual({
gclid: "testKey",
gad_source: "1",
});
});

it("Doesn't store anything after a page reload with the same UTM params and session", async () => {
await page.reload();
const rawData = await page?.evaluate(() =>
window.localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries.length).toEqual(1);
});

it("Stores a new value if the GCLID params are different but the session is the same", async () => {
const urlBase = page.url().split("?")[0];
await page.goto(
`${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`,
);
const rawData = await page.evaluate(() =>
localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries?.[0].gclidParams).toEqual({
gclid: "testKey2",
gad_source: "2",
});
});

it("Stores a new value if the GCLID params are the same but the session is different", async () => {
await page.evaluate(() =>
sessionStorage.setItem("nuxt-utm-session-id", "old-session"),
);
await page.reload();
const rawData = await page.evaluate(() =>
localStorage.getItem("nuxt-utm-data"),
);
entries = await JSON.parse(rawData ?? "[]");
expect(entries?.[0].gclidParams).toEqual({
gclid: "testKey",
gad_source: "1",
});
});
});
});
6 changes: 6 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ declare module "nuxt-utm" {
utm_content?: string;
}

interface GCLIDParams {
gclid?: string;
gad_source?: string;
}

interface AdditionalInfo {
referrer: string;
userAgent: string;
Expand All @@ -23,5 +28,6 @@ declare module "nuxt-utm" {
utmParams: UTMParams;
additionalInfo: AdditionalInfo;
sessionId: string;
gclidParams?: GCLIDParams;
}
}

0 comments on commit 5a72a2d

Please sign in to comment.