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 afc3badd11fc9..aba24ac1db60c 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,11 @@ export function EventButton() { return (
@@ -314,7 +318,11 @@ export function EventButton() { return (
diff --git a/packages/third-parties/README.md b/packages/third-parties/README.md index f325e42a4e341..21819008adb4a 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/ga4/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 40b00a685f3a0..010876dede6f4 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 { @@ -56,14 +60,23 @@ export function GoogleAnalytics(props: GAParams) { ) } -export function sendGAEvent(..._args: Object[]) { +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(arguments) + 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 808d60cc6387c..de9111b22bbb4 100644 --- a/packages/third-parties/src/types/google.ts +++ b/packages/third-parties/src/types/google.ts @@ -54,3 +54,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