From c99a80765364924c279ee7931c51f316cb15617c Mon Sep 17 00:00:00 2001 From: hjick Date: Wed, 13 Mar 2024 15:08:14 +0900 Subject: [PATCH 1/5] Update GA send event function params and add docs example --- packages/third-parties/README.md | 23 +++++++++++++++++++++++ packages/third-parties/src/google/ga.tsx | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/third-parties/README.md b/packages/third-parties/README.md index f325e42a4e341..27b0a360cbd01 100644 --- a/packages/third-parties/README.md +++ b/packages/third-parties/README.md @@ -40,4 +40,27 @@ export default function Page() { } ``` +### Google Analytics Event + +The `sendGAEvent` function can be used to send an event to Google Analytics. This function uses the [gtag.js](https://developers.google.com/analytics/devguides/collection/gtagjs/events) library under the hood. + +```js +import { sendGAEvent } from '@next/third-parties/google' + +export default function Page() { + return ( + + ) +} +``` + To get a better idea of how these components work, take a look at this [demo](https://test-next-script-housseindjirdeh.vercel.app/). diff --git a/packages/third-parties/src/google/ga.tsx b/packages/third-parties/src/google/ga.tsx index 5949477f455df..07d411ef86544 100644 --- a/packages/third-parties/src/google/ga.tsx +++ b/packages/third-parties/src/google/ga.tsx @@ -54,14 +54,14 @@ export function GoogleAnalytics(props: GAParams) { ) } -export function sendGAEvent(..._args: Object[]) { +export function sendGAEvent(eventName: string, eventParameters: {[key: string]: string | number}) { if (currDataLayerName === undefined) { console.warn(`@next/third-parties: GA has not been initialized`) return } if (window[currDataLayerName]) { - window[currDataLayerName].push(arguments) + window[currDataLayerName].push({0: 'event', 1: eventName, 2: eventParameters}) } else { console.warn( `@next/third-parties: GA dataLayer ${currDataLayerName} does not exist` From 7319e58e148135013035f4b134056d06fbe651fb Mon Sep 17 00:00:00 2001 From: hjick Date: Wed, 13 Mar 2024 15:11:59 +0900 Subject: [PATCH 2/5] Update docs gtag link to GA4 --- packages/third-parties/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/third-parties/README.md b/packages/third-parties/README.md index 27b0a360cbd01..21819008adb4a 100644 --- a/packages/third-parties/README.md +++ b/packages/third-parties/README.md @@ -42,7 +42,7 @@ export default function Page() { ### Google Analytics Event -The `sendGAEvent` function can be used to send an event to Google Analytics. This function uses the [gtag.js](https://developers.google.com/analytics/devguides/collection/gtagjs/events) library under the hood. +The `sendGAEvent` function can be used to send an event to Google Analytics. This function uses the [gtag.js](https://developers.google.com/analytics/devguides/collection/ga4/events) library under the hood. ```js import { sendGAEvent } from '@next/third-parties/google' From df9302979544351b9ff52719760d15e4d08268a9 Mon Sep 17 00:00:00 2001 From: hjick Date: Fri, 15 Mar 2024 12:33:25 +0900 Subject: [PATCH 3/5] Update next GAEvent docs example --- .../06-optimizing/12-third-party-libraries.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx index 93224009cad61..15029e06bbdfd 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx @@ -294,7 +294,9 @@ export function EventButton() { return (
@@ -314,7 +316,9 @@ export function EventButton() { return (
From c077f70d93406f553cb6a52157a0211e4f9ca136 Mon Sep 17 00:00:00 2001 From: hjick Date: Sat, 13 Apr 2024 16:46:22 +0900 Subject: [PATCH 4/5] refactor: add more strict types on sendGAEvent function parameters --- packages/third-parties/src/google/ga.tsx | 19 ++- packages/third-parties/src/types/google.ts | 188 +++++++++++++++++++++ 2 files changed, 204 insertions(+), 3 deletions(-) diff --git a/packages/third-parties/src/google/ga.tsx b/packages/third-parties/src/google/ga.tsx index 07d411ef86544..0f3e3c1a3d34d 100644 --- a/packages/third-parties/src/google/ga.tsx +++ b/packages/third-parties/src/google/ga.tsx @@ -3,7 +3,11 @@ import React, { useEffect } from 'react' import Script from 'next/script' -import type { GAParams } from '../types/google' +import type { + GAParams, + GARecommendedEventName, + GARecommendedEventParams, +} from '../types/google' declare global { interface Window { @@ -54,14 +58,23 @@ export function GoogleAnalytics(props: GAParams) { ) } -export function sendGAEvent(eventName: string, eventParameters: {[key: string]: string | number}) { +export function sendGAEvent( + eventName: T, + eventParameters: T extends GARecommendedEventName + ? GARecommendedEventParams[T] + : { [key: string]: string | number } +) { if (currDataLayerName === undefined) { console.warn(`@next/third-parties: GA has not been initialized`) return } if (window[currDataLayerName]) { - window[currDataLayerName].push({0: 'event', 1: eventName, 2: eventParameters}) + window[currDataLayerName].push({ + 0: 'event', + 1: eventName, + 2: eventParameters, + }) } else { console.warn( `@next/third-parties: GA dataLayer ${currDataLayerName} does not exist` diff --git a/packages/third-parties/src/types/google.ts b/packages/third-parties/src/types/google.ts index 30a4e9f28a464..c413a8209fc50 100644 --- a/packages/third-parties/src/types/google.ts +++ b/packages/third-parties/src/types/google.ts @@ -43,3 +43,191 @@ export type YouTubeEmbed = { params?: string style?: string } + +// https://developers.google.com/tag-platform/gtagjs/reference/events +type GAEventItemParam = { + item_id: string + item_name: string + affiliation?: string + coupon?: string + discount?: number + index?: number + item_brand?: string + item_category?: string + item_category2?: string + item_category3?: string + item_category4?: string + item_category5?: string + item_list_id?: string + item_list_name?: string + item_variant?: string + location_id?: string + price?: number + quantity?: number + [x: string]: any // can add item-scoped custom parameters +} + +export type GARecommendedEventParams = { + add_payment_info: { + currency: string + value: number + coupon?: string + payment_type?: string + items: GAEventItemParam[] + } + add_shipping_info: { + currency: string + value: number + coupon?: string + shipping_tier?: string + items: GAEventItemParam[] + } + add_to_cart: { + currency: string + value: number + items: GAEventItemParam[] + } + add_to_wishlist: { + currency: string + value: number + items: GAEventItemParam[] + } + begin_checkout: { + currency: string + value: number + coupon?: string + items: GAEventItemParam[] + } + earn_virtual_currency: { + virtual_currency_name?: string + value?: number + } + exception: { + description?: string + fatal?: boolean + } + generate_lead: { + currency: string + value: number + } + join_group: { + group_id?: string + } + level_end: { + level_name?: string + success?: boolean + } + level_start: { + level_name?: string + } + level_up: { + level?: number + character?: string + } + login: { + method?: string + } + page_view: { + page_location?: string + client_id?: string + language?: string + page_encoding?: string + page_title?: string + user_agent?: string + } + post_score: { + score: number + level?: number + character?: string + } + purchase: { + currency: string + value: number + transaction_id: string + coupon?: string + shipping?: number + tax?: number + items: GAEventItemParam[] + } + refund: { + currency: string + transaction_id: string + value: number + coupon?: string + shipping?: number + tax?: number + items?: GAEventItemParam[] + } + remove_from_cart: { + currency: string + value: number + items: GAEventItemParam[] + } + search: { + search_term: string + } + select_content: { + content_type?: string + content_id?: string + } + select_item: { + item_list_id?: string + item_list_name?: string + // * The items array is expected to have a single element, representing the selected item. If multiple elements are provided, only the first element in items will be used. https://developers.google.com/tag-platform/gtagjs/reference/events#select_item + items: [GAEventItemParam] + } + select_promotion: { + creative_name?: string + creative_slot?: string + promotion_id?: string + promotion_name?: string + items?: GAEventItemParam[] + } + share: { + method?: string + content_type?: string + item_id?: string + } + sign_up: { + method?: string + } + spend_virtual_currency: { + value: number + virtual_currency_name: string + item_name?: string + } + // tutorial begin has no parameters + tutorial_begin: {} + tutorial_complete: {} + unlock_achievement: { + achievement_id: string + } + view_cart: { + currency: string + value: number + items: GAEventItemParam[] + } + view_item: { + currency: string + value: number + items: GAEventItemParam[] + } + view_item_list: { + item_list_id?: string + item_list_name?: string + items: GAEventItemParam[] + } + view_promotion: { + creative_name?: string + creative_slot?: string + promotion_id?: string + promotion_name?: string + // * The items array is expected to have a single element, representing the item associated with the promotion. If multiple elements are provided, only the first element in items will be used. https://developers.google.com/tag-platform/gtagjs/reference/events#view_promotion + items: [GAEventItemParam] + } + view_search_results: { + search_term?: string + } +} + +export type GARecommendedEventName = keyof GARecommendedEventParams From db8e87f8712f46e244118ac85affd714aea3790c Mon Sep 17 00:00:00 2001 From: hjick Date: Sat, 13 Apr 2024 17:25:48 +0900 Subject: [PATCH 5/5] chore: run pnpm prettier-fix --- .../06-optimizing/12-third-party-libraries.mdx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx index f52cffef35c68..556fd4f5a9f35 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx @@ -294,9 +294,11 @@ export function EventButton() { return (
@@ -316,9 +318,11 @@ export function EventButton() { return (