From 84fa2b019d49c024a148b50c618e4b937725b103 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Wed, 1 Mar 2023 02:29:03 +0800 Subject: [PATCH] Push `doc` to datalayer once on `dataLoaded` GTM event --- README.md | 3 +-- lib/gtm.ts | 11 +++++++---- pages/article/[id].js | 7 +++---- pages/reply/[id].js | 7 +++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ea214122..8f6b66a3 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,7 @@ The application will fire the following custom events in GTM `dataLayer`: Also, it will push the following custom variable to `dataLayer`; - `CURRENT_USER` - Current user object, set by `useCurrentUser`. -- `docType` - Set when `dataLoaded` event fires. Can be either `article` or `reply`. -- `docId` - Set when `dataLoaded` event fires. The ID of loaded content. +- `doc` - Set when `dataLoaded` event fires. The loaded content itself in object, including its `__typename`. Lastly, in Google Tag Manager we use `data-ga` property to track clicks. If user clicks a decendant of an React element with `data-ga` property, diff --git a/lib/gtm.ts b/lib/gtm.ts index a4fc8142..1627e31c 100644 --- a/lib/gtm.ts +++ b/lib/gtm.ts @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; /** * Google tag manager related utility functions @@ -16,12 +16,15 @@ export function pushToDataLayer(...args: unknown[]) { /** * @param trigger - trigger useEffect() after trigger turns truthy - * @param args - data to send to pushDataLayer on trigger change + * @param args - data to send to pushDataLayer on trigger change. It's sent only once. + * Changes to args afterwards does not trigger push anymore. */ -export function usePushToDataLayer(trigger: unknown, args: object) { +export function usePushToDataLayerOnce(trigger: unknown, args: object) { + const triggeredRef = useRef(false); const dontTrigger = !trigger; useEffect(() => { - if (dontTrigger) return; + if (dontTrigger || triggeredRef.current) return; + triggeredRef.current = true; pushToDataLayer(args); }, [dontTrigger, args]); } diff --git a/pages/article/[id].js b/pages/article/[id].js index 161e6dd7..6ea8019b 100644 --- a/pages/article/[id].js +++ b/pages/article/[id].js @@ -13,7 +13,7 @@ import Head from 'next/head'; import withData from 'lib/apollo'; import useCurrentUser from 'lib/useCurrentUser'; import { nl2br, linkify, ellipsis } from 'lib/text'; -import { usePushToDataLayer } from 'lib/gtm'; +import { usePushToDataLayerOnce } from 'lib/gtm'; import getTermsString from 'lib/terms'; import { useIsUserBlocked } from 'lib/isUserBlocked'; @@ -297,10 +297,9 @@ function ArticlePage() { const article = data?.GetArticle; - usePushToDataLayer(!!article, { + usePushToDataLayerOnce(!!article, { event: 'dataLoaded', - docType: 'article', - docId: query.id, + doc: article, }); if (loading && !article) { diff --git a/pages/reply/[id].js b/pages/reply/[id].js index e027faa8..6e3e51ff 100644 --- a/pages/reply/[id].js +++ b/pages/reply/[id].js @@ -11,7 +11,7 @@ import Typography from '@material-ui/core/Typography'; import withData from 'lib/apollo'; import useCurrentUser from 'lib/useCurrentUser'; -import { usePushToDataLayer } from 'lib/gtm'; +import { usePushToDataLayerOnce } from 'lib/gtm'; import getTermsString from 'lib/terms'; import ExpandableText from 'components/ExpandableText'; @@ -158,10 +158,9 @@ function ReplyPage() { }, [currentUser]); const reply = data?.GetReply; - usePushToDataLayer(!!reply, { + usePushToDataLayerOnce(!!reply, { event: 'dataLoaded', - docType: 'article', - docId: query.id, + doc: reply, }); if (loading) {