From 7eac98f47d65b154cb1d79e4b83aae397f6a3ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dcaro=20Azevedo?= Date: Mon, 4 Jul 2022 12:44:40 -0300 Subject: [PATCH 1/5] docs(sdk): improve analytics sdk documentation --- apps/docs/docs/reference/sdk/Analytics.md | 105 ++---------------- .../sdk/analytics/how-to-extend-types.md | 48 ++++++++ .../analytics/how-to-send-custom-events.md | 95 ++++++++++++++++ .../sdk/analytics/sendAnalyticsEvent.md | 57 ++++++++++ .../sdk/analytics/useAnalyticsEvent.md | 30 +++++ apps/docs/docs/reference/sdk/faststore-sdk.md | 2 +- 6 files changed, 238 insertions(+), 99 deletions(-) create mode 100644 apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md create mode 100644 apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md create mode 100644 apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md create mode 100644 apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md diff --git a/apps/docs/docs/reference/sdk/Analytics.md b/apps/docs/docs/reference/sdk/Analytics.md index 70e9c50b9d..1f7a865d1e 100644 --- a/apps/docs/docs/reference/sdk/Analytics.md +++ b/apps/docs/docs/reference/sdk/Analytics.md @@ -1,104 +1,13 @@ -# Analytics +# Analytics module -The analytics module lets you manage analytics events based on [Google Analytics 4 (GA4) data model](https://developers.google.com/analytics/devguides/collection/ga4/reference/events). The events are wrapped and then sent over standard `postMessage` calls, which share the event only with the website's origin. The events are received via event listeners. It also supports sending and receiving custom events as the types on the helper functions can be overridden. +The analytics module lets you manage events in a simple way. You send an event using this module, the event is wrapped and then sent to the window over standard `postMessage` calls, which share the event only with the website's origin. This module provides a React Hook so it's possible to intercept the fired events. can be received via event listeners. -### Sending events +It's important to note that events sent using the analytics module are not directly sent to any analytics provider such as Google Analytics. This has to be done manually by using the provided hook. -Analytics events can be sent by using the `sendAnalyticsEvent` function and it's especially useful to send common ecommerce events such as `add_to_cart`. It enforces standard GA4 events via type check and IntelliSense suggestions, but this behavior can be altered via overriding the function's types. +The analytics module supports sending and receiving events of any shape, so you can implement your own types and override default ones. -To fire a standard GA4 event: +# Google Analytics support -```tsx -import { useCallback } from 'react' -import { sendAnalyticsEvent } from '@faststore/sdk' +Google Analytics is by far the industry leading analytics solution that most ecommerce websites use, and the analytics module was built with it in mind. All helper functions and hooks use the [Google Analytics 4 (GA4) data model](https://developers.google.com/analytics/devguides/collection/ga4/reference/events) by default, which means GA4 events will be suggested along with recommended properties and [IntelliSense](https://docs.microsoft.com/pt-br/visualstudio/ide/using-intellisense) support. -const MyComponent = () => { - const addToCartCallback = useCallback(() => { - /* ... */ - - const addToCartEvent = { - type: 'add_to_cart', - data: { - items: [ - /* ... */ - ], - }, - } - - sendAnalyticsEvent(addToCartEvent) - }, []) - - return -} -``` - -For custom events, define the type of the event and override the default type via `sendAnalyticsEvent` generics. Your custom event has to have a type and a data field of any kind. - -To fire a custom event: - -```tsx -import { useCallback } from 'react' -import { sendAnalyticsEvent } from '@faststore/sdk' - -interface CustomEvent { - type: 'custom_event' - data: { - customProperty?: string - } -} - -const MyComponent = () => { - const customEventCallback = useCallback(() => { - /* ... */ - - const customEvent = { - type: 'custom_event', - data: { - customProperty: 'value', - }, - } - - sendAnalyticsEvent(customEvent) - }, []) - - return -} -``` - -### Receiving events - -It's possible to receive analytics events by using the `useAnalyticsEvent` hook. It accepts a handler that will be called every time an event sent by `sendAnalyticsEvent` arrives. For that reason, it can fire both for standard GA4 events and for custom events that a library or a component might be sending. To help users be aware of that possibility, the event received by the handler is, by default, typed as `UnknownEvent`. You can assume it has another type by simply typing the callback function as you wish, but be careful with the unexpected events that might come to this handler. - -To use the `useAnalyticsEvent` hook: - -```tsx -import { useAnalyticsEvent } from '@faststore/sdk' -import type { AnalyticsEvent } from '@faststore/sdk' - -/** - * Notice that we typed it as AnalyticsEvent, but there may be events that are not from this type. - * - * Since we're dealing with it on a switch and we are providing an empty default clause, - * we're not gonna have issues receiving custom events sent by other components or libraries. - */ -function handler(event: AnalyticsEvent) { - switch (event.type) { - case 'add_to_cart': { - /* ... */ - } - - /* ... */ - - default: { - /* ... */ - } - } -} - -// In your component: -const MyComponent = () => { - useAnalyticsEvent(handler) - - /* ... */ -} -``` +To send the events to Google Analytics, you should listen to when they're sent - by using the [useAnalyticsEvent](/reference/sdk/analytics/useAnalyticsEvent) hook - and add them to the `dataLayer` in case you're using Google Tag Manager (recommended) or call the `gtag` function directly if you're using gtag's script directly. The analytics module doesn't do this automatically, so it has to be executed on the store. diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md b/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md new file mode 100644 index 0000000000..eee454dd00 --- /dev/null +++ b/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md @@ -0,0 +1,48 @@ +# How to extend and customize native types + +One of the major features the analytics module offers are its types. They're all based on [Google Analytics 4 (GA4) data model](https://developers.google.com/analytics/devguides/collection/ga4/reference/events), and they're especially focused on the [Enhanced Ecommerce](https://support.google.com/tagmanager/answer/6107169) capabilities. + +Although the recommended parameters by each analytics providers are often the most important ones, it's quite common to send additional properties to them in order to monitor specific behaviors that are uniquely valuable to a store or a store sectors. + +The analytics module supports this behavior natively and offers ways to make it easy to incorporate it without losing code safety features. It does that by accepting custom types and exporting its own types so that users don't have the need to rewrite all of them to add minor additions. Also, these types are built with generics, which means you can rewrite only a small part of them if you really need to. + +## Available types + +The types for all events are available for use and extension. Here's the list of the events the analytics module natively supports: `add_payment_info`, `purchase`, `signup`, `add_shipping_info`, `refund`, `add_to_cart`, `remove_from_cart`, `view_cart`, `add_to_wishlist`, `search`, `view_item`, `begin_checkout`, `select_item`, `view_item_list`, `select_promotion`, `view_promotion`, `login`, `share`. For each of these events, at least two types are exported: one being the type of the event params and the other being the event type itself. + +As an example, the `add_to_cart` has two exported types: `AddToCartParams` and `AddToCartEvent`. + +Also, there are types there are common to all events, such as the `Item` type. These types are particulary useful when overriding `Item` properties or a whole `Item` itself (usually via generics). + +## Extending types + +You can extend the available types by using common TS techniques such as [Type Aliases or Extended Interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces). + +```ts +import type { AddToCartEvent } from '@faststore/sdk' + +/** + * AddToCartExtended will have all the AddToCartEvent properties (name, params) plus the new properties (foo) + */ +interface AddToCartExtended extends AddToCartEvent { + foo: string +} +``` + +Also, when available, you can use [generics](https://www.typescriptlang.org/docs/handbook/2/generics.html) to override the Item property in events. + + +```ts +import type { AddToCartEvent, Item } from '@faststore/sdk' + +interface ItemExtension { + dimension10: string +} + +type ItemExtended = Item & ItemExtension + +/** + * AddToCartExtended will have the same properties as AddToCartEvent (name, params), but the items inside the params property will now have the ItemExtended type. + */ +type AddToCartWithExtendedItems = AddToCartEvent +``` diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md b/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md new file mode 100644 index 0000000000..27f942f650 --- /dev/null +++ b/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md @@ -0,0 +1,95 @@ +# How to send custom events + +Sometimes a store needs to track user behavior that's not covered by [GA's Enhanced Ecommerce](https://support.google.com/tagmanager/answer/6107169), which is natively supported by the analytics module. In those cases, you can still use the same functions and hooks to fire and intercept custom events. This way, you centralize all tracking-related events in a single tool, which helps you write code that's more consistant, readable, and maintainable. + +## sendAnalyticsEvent +You can use [extended types](/reference/sdk/analytics/how-to-extend-types) for sending custom events. You'll need to use the generics available on the [sendAnalyticsEvent](/reference/sdk/analytics/sendAnalyticsEvent) function. + +```ts +import type { AddToCartEvent } from '@faststore/sdk' +import { sendAnalyticsEvent } from '@faststore/sdk' + +interface AddToCartExtended extends AddToCartEvent { + foo: string +} + +/* ... */ + +sendAnalyticsEvent({ name, params, foo }) +``` + +### Send arbitrary event +The `sendAnalyticsEvent` function demands that the event object contains two properties: `name` and `type`. These two properties can be of any type and value, and don't have to follow any event name conventions related to the natively supported events. + +```ts +import type { AddToCartEvent } from '@faststore/sdk' +import { sendAnalyticsEvent } from '@faststore/sdk' + +interface ArbitraryEvent { + name: 'arbitrary-event', + params: string + foo: number + bar: boolean +} + +/* ... */ + +sendAnalyticsEvent({ name, params, foo, bar }) +``` + +### Override multiple types +If you have multiple types to override, you can do that all at once and re-export the `sendAnalyticsEvent` function with the desired types: + +```ts +/* types.ts */ +import { sendAnalyticsEvent } from '@faststore/sdk' + +type AddToCartExtended = /* ... */ +type RemoveFromCartExtended = /* ... */ +type ViewItemExtended = /* ... */ +type SelectItemExtended = /* ... */ + +type ExtendedEvents = + | AddToCartExtended + | RemoveFromCartExtended + | ViewItemExtended + | SelectItemExtended + +type SendExtendedAnalyticsEvent = (event: ExtendedEvents) => void + +export const sendExtendedAnalyticsEvent: SendExtendedAnalyticsEvent = (event) => + sendAnalyticsEvent(event) +``` + +```ts +/* MyComponent.tsx */ +import { sendExtendedAnalyticsEvent } from './types' + +/* ... */ + +sendExtendedAnalyticsEvent({ /* Extended event object */}) +``` + +## useAnalyticsEvent + +To target extended properties of events when intercepting them, you can configure the types of your [useAnalyticsEvent](/reference/sdk/analytics/useAnalyticsEvent) callback function to expect an event of such type. + +```ts +import { useAnalyticsEvent } from '@faststore/sdk' + +import type { ExtendedEvents } from './types' + +export const AnalyticsHandler = () => { + /** + * By typing the callback function with the extended types, you are able to + * reference properties that are not natively offered by the analytics module. + */ + useAnalyticsEvent((event: ExtendedEvents) => { + /* ... */ + }) + + /* ... */ + + return null +} +``` \ No newline at end of file diff --git a/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md b/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md new file mode 100644 index 0000000000..b2a5cade67 --- /dev/null +++ b/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md @@ -0,0 +1,57 @@ +# sendAnalyticsEvent + +The analytics module provides the `sendAnalyticsEvent` function as the way to fire events in the browser. These events are often related to ecommerce tracking capabilities. By default, the `sendAnalyticsEvent` suggests (via IntelliSense) and inforces (via TypeScript) [Google Analytics 4 (GA4) data model](https://developers.google.com/analytics/devguides/collection/ga4/reference/events). + +`sendAnalyticsEvent` does not send events to any analytics provider. It is merely a way to centralize and aggregate tracking events. To intercept events fired with this function, use the hook [useAnalyticsEvent](/reference/sdk/analytics/useAnalyticsEvent). This function also supports [sending custom events](/reference/sdk/analytics/how-to-send-custom-events). + +## How to use + +To fire a supported GA4 event: + +```tsx +import { useCallback } from 'react' +import { sendAnalyticsEvent } from '@faststore/sdk' + +const MyComponent = () => { + const addToCartCallback = useCallback(() => { + /* ... */ + + const addToCartEvent = { + type: 'add_to_cart', + data: { + items: [ + /* ... */ + ], + }, + } + + sendAnalyticsEvent(addToCartEvent) + }, []) + + return +} +``` + +## Generics + +The `sendAnalyticsEvent` function was built using [generics](https://www.typescriptlang.org/docs/handbook/2/generics.html), which means you can extend default types and override the default ones, obtaining the same suggestions and enforcements as you would with a natively supported event. + +To provide a custom type referecence for `sendAnalyticsEvent`, do the following + +```tsx +import { sendAnalyticsEvent } from '@faststore/sdk' + +interface CustomEvent { + name: 'custom_event' + params: { + customProperty?: string + } +} + +/** + * We're passing the CustomEvent to sendAnalyticsEvent. As you type, you'll receive code suggestions for all the properties of this type, including params subfields. + */ +sendAnalyticsEvent(/* ... */) +``` + +This is most commonly used to fire custom events or native events with custom properties in it. For more details, read the [How to extend and customize native types](/reference/sdk/analytics/how-to-extend-types) and [How to send custom events](/reference/sdk/analytics/how-to-send-custom-events) docs. diff --git a/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md b/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md new file mode 100644 index 0000000000..f252b68167 --- /dev/null +++ b/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md @@ -0,0 +1,30 @@ +# useAnalyticsEvent + +To intercept events that were fired using the analytics module, you should use the `useAnalyticsEvent` hook. It automatically detects which events were sent using the [sendAnalyticsEvent](/reference/sdk/analytics/sendAnalyticsEvent) function and provides a way to react to those events. The `useAnalyticsEvent` hook can be used to intercept both native and custom events. + +## How to use +The `useAnalyticsEvent` hook accepts a callback function that runs whenever an event is fired. + +The callback function you provide receives the event that triggered its execution as an argument. Ideally, this is the place you actually send the event to the analytics provider of you choice. + +```tsx +import type { AnalyticsEvent } from '@faststore/sdk' +import { useAnalyticsEvent } from '@faststore + +export const AnalyticsHandler = () => { + useAnalyticsEvent((event: AnalyticsEvent) => { + /** + * This is where you can send events to your analytics provider + * + * Example: + * window.dataLayer.push({ event: event.name, ecommerce: event.params }) + */ + }) + + /* ... */ +} +``` + +## External libraries + +External libraries can also send events using the analytics module. This means that you might come across unexpected events being intercepted by `useAnalyticsEvent`. This is usually not a problem, since most common analytics providers don't break if you send additional (irrelevant) data to them. If you're using one that does, make sure to filter the events by name, so only the expected events are sent to the provider. \ No newline at end of file diff --git a/apps/docs/docs/reference/sdk/faststore-sdk.md b/apps/docs/docs/reference/sdk/faststore-sdk.md index 2fdbe34dba..a46018edc9 100644 --- a/apps/docs/docs/reference/sdk/faststore-sdk.md +++ b/apps/docs/docs/reference/sdk/faststore-sdk.md @@ -10,7 +10,7 @@ FastStore SDK is a simple, framework-agnostic implementation of Commerce APIs to ### Analytics -The analytics data layer is based on [the official GA4 specification](https://developers.google.com/gtagjs/reference/ga4-events). +The analytics module helps you create a simple and extensive event system to feed your data pool. It is biased towards Google Analytics 4, but supports any other analytics provider. Go to the [Analytics](/reference/sdk/analytics) page to learn more. ## Get started From d98993331f16f82048d79575d8ce3f8691ef03d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dcaro=20Azevedo?= Date: Mon, 4 Jul 2022 13:21:54 -0300 Subject: [PATCH 2/5] docs: configure sidebar for new analytics sdk docs --- apps/docs/sidebars.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/docs/sidebars.js b/apps/docs/sidebars.js index c91e8e201d..fbb951a524 100644 --- a/apps/docs/sidebars.js +++ b/apps/docs/sidebars.js @@ -240,7 +240,18 @@ module.exports = { collapsed: true, link: { type: 'doc', id: 'reference/sdk/faststore-sdk' }, items: [ - 'reference/sdk/Analytics', + { + type: 'category', + label: 'Analytics', + link: { type: 'doc', id: 'reference/sdk/analytics' }, + collapsed: true, + items: [ + { + type: 'autogenerated', + dirName: 'reference/sdk/analytics', + }, + ], + }, { type: 'category', label: 'Cart', From 423a37c9402077f4d9d086049ff457fc0e220569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dcaro=20Azevedo?= Date: Mon, 4 Jul 2022 13:41:42 -0300 Subject: [PATCH 3/5] chore: test converting analytics files to mdx --- .../analytics/{how-to-extend-types.md => how-to-extend-types.mdx} | 0 ...how-to-send-custom-events.md => how-to-send-custom-events.mdx} | 0 .../analytics/{sendAnalyticsEvent.md => sendAnalyticsEvent.mdx} | 0 .../sdk/analytics/{useAnalyticsEvent.md => useAnalyticsEvent.mdx} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename apps/docs/docs/reference/sdk/analytics/{how-to-extend-types.md => how-to-extend-types.mdx} (100%) rename apps/docs/docs/reference/sdk/analytics/{how-to-send-custom-events.md => how-to-send-custom-events.mdx} (100%) rename apps/docs/docs/reference/sdk/analytics/{sendAnalyticsEvent.md => sendAnalyticsEvent.mdx} (100%) rename apps/docs/docs/reference/sdk/analytics/{useAnalyticsEvent.md => useAnalyticsEvent.mdx} (100%) diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md b/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.mdx similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md rename to apps/docs/docs/reference/sdk/analytics/how-to-extend-types.mdx diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md b/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.mdx similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md rename to apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.mdx diff --git a/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md b/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.mdx similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md rename to apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.mdx diff --git a/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md b/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.mdx similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md rename to apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.mdx From d1fbddf8324676a927117f78ce51d86ff246eb6d Mon Sep 17 00:00:00 2001 From: Carolina Menezes <60782333+carolinamenezes@users.noreply.github.com> Date: Mon, 4 Jul 2022 13:50:51 -0300 Subject: [PATCH 4/5] Update Analytics.md --- apps/docs/docs/reference/sdk/Analytics.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/docs/docs/reference/sdk/Analytics.md b/apps/docs/docs/reference/sdk/Analytics.md index 1f7a865d1e..8059373033 100644 --- a/apps/docs/docs/reference/sdk/Analytics.md +++ b/apps/docs/docs/reference/sdk/Analytics.md @@ -1,3 +1,7 @@ +--- +id: analytics +--- + # Analytics module The analytics module lets you manage events in a simple way. You send an event using this module, the event is wrapped and then sent to the window over standard `postMessage` calls, which share the event only with the website's origin. This module provides a React Hook so it's possible to intercept the fired events. can be received via event listeners. From 2a8977c88bc673c4a5da2bd86ba20c9c5de42a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dcaro=20Azevedo?= Date: Mon, 4 Jul 2022 13:53:05 -0300 Subject: [PATCH 5/5] chore: convert files back to .md --- .../analytics/{how-to-extend-types.mdx => how-to-extend-types.md} | 0 ...how-to-send-custom-events.mdx => how-to-send-custom-events.md} | 0 .../analytics/{sendAnalyticsEvent.mdx => sendAnalyticsEvent.md} | 0 .../sdk/analytics/{useAnalyticsEvent.mdx => useAnalyticsEvent.md} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename apps/docs/docs/reference/sdk/analytics/{how-to-extend-types.mdx => how-to-extend-types.md} (100%) rename apps/docs/docs/reference/sdk/analytics/{how-to-send-custom-events.mdx => how-to-send-custom-events.md} (100%) rename apps/docs/docs/reference/sdk/analytics/{sendAnalyticsEvent.mdx => sendAnalyticsEvent.md} (100%) rename apps/docs/docs/reference/sdk/analytics/{useAnalyticsEvent.mdx => useAnalyticsEvent.md} (100%) diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.mdx b/apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/how-to-extend-types.mdx rename to apps/docs/docs/reference/sdk/analytics/how-to-extend-types.md diff --git a/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.mdx b/apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.mdx rename to apps/docs/docs/reference/sdk/analytics/how-to-send-custom-events.md diff --git a/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.mdx b/apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.mdx rename to apps/docs/docs/reference/sdk/analytics/sendAnalyticsEvent.md diff --git a/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.mdx b/apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md similarity index 100% rename from apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.mdx rename to apps/docs/docs/reference/sdk/analytics/useAnalyticsEvent.md