From 0668d8a287f947670abf523947b8f3a4bf493554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Fri, 29 Dec 2023 15:28:49 +0100 Subject: [PATCH] Track page view (#42) * Track page view using a server action * Track the page view * Format * Track it once * Support no page an pass language * Update API client --- bun.lockb | Bin 448752 -> 448752 bytes package.json | 2 +- src/components/PageBody/PageBody.tsx | 5 ++ src/components/PageBody/TrackPageView.tsx | 64 ++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/components/PageBody/TrackPageView.tsx diff --git a/bun.lockb b/bun.lockb index ff8211a495c78d753f87914d69bde6447cfebfd4..946566f15333174c31cfebcdeb629040f59eda08 100755 GIT binary patch delta 166 zcmV;X09pU=u^aHQ8;~v_{7z#~&x|7!bu8strzvFl1f!Cs)?BI@LDzIAmpal5u}=1j z0U48lQ7e;hNC<;?jJJ4<0lj}fmG@Fyxmi185R8kc>y@~2~;EitwD9~hjk1Bhjk1Cw{;8zQ>6hlhsm)7 Ux5=>uh9&_uhfvrBmr&RSplCr%BLDyZ delta 160 zcmV;R0AK&`u^aHQ8;~v_osjc)?f$e=Y;$v0`r;en03=;;zGVgV>DMcu!SnXOgLsU$c#HwPe?W3{rD$`eJ{}_ND0*nT1IY!4e5yk!B|N`8*cH@YbA9~rO+dRE zz$aM%(*Bh$6r>5>&M9rj=p;LpS6H@qm5hgV3<8IB3`ltu?2=E O0W^nD*aeqR*ao2Q?n-U| diff --git a/package.json b/package.json index 2b605a6c7..19a31fb98 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@geist-ui/icons": "^1.0.2", - "@gitbook/api": "^0.24.0", + "@gitbook/api": "^0.25.0", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-popover": "^1.0.7", "@readme/openapi-parser": "^2.5.0", diff --git a/src/components/PageBody/PageBody.tsx b/src/components/PageBody/PageBody.tsx index 88e4f5759..19c0e55ac 100644 --- a/src/components/PageBody/PageBody.tsx +++ b/src/components/PageBody/PageBody.tsx @@ -1,6 +1,7 @@ import { CustomizationSettings, JSONDocument, RevisionPageDocument, Space } from '@gitbook/api'; import React from 'react'; +import { api } from '@/lib/api'; import { hasFullWidthBlock } from '@/lib/document'; import { ContentRefContext, resolveContentRef } from '@/lib/references'; import { tcls } from '@/lib/tailwind'; @@ -9,6 +10,7 @@ import { PageCover } from './PageCover'; import { PageFooterNavigation } from './PageFooterNavigation'; import { PageHeader } from './PageHeader'; import { TogglePageFullWidth } from './TogglePageFullWidth'; +import { TrackPageView } from './TrackPageView'; import { DocumentView } from '../DocumentView'; import { PageFeedbackForm } from '../PageFeedback'; @@ -88,6 +90,9 @@ export function PageBody(props: { ) : null} + + + ); } diff --git a/src/components/PageBody/TrackPageView.tsx b/src/components/PageBody/TrackPageView.tsx new file mode 100644 index 000000000..f9302b743 --- /dev/null +++ b/src/components/PageBody/TrackPageView.tsx @@ -0,0 +1,64 @@ +'use client'; + +import type { RequestSpaceTrackPageView } from '@gitbook/api'; +import cookies from 'js-cookie'; +import * as React from 'react'; + +import { getVisitorId } from '@/lib/analytics'; + +/** + * Track the page view for the current page to integrations. + */ +export function TrackPageView(props: { + apiHost: string; + spaceId: string; + pageId: string | undefined; +}) { + const { apiHost, spaceId, pageId } = props; + + React.useEffect(() => { + trackPageView(apiHost, spaceId, pageId); + }, [apiHost, spaceId, pageId]); + + return null; +} + +let latestPageId: string | undefined | null = null; + +/** + * Track the page view for the current page to GitBook. + * We don't use the API client to avoid shipping 80kb of JS to the client. + * And instead use a simple fetch. + */ +async function trackPageView(apiHost: string, spaceId: string, pageId: string | undefined) { + if (pageId === latestPageId) { + // The hook can be called multiple times, we only want to track once. + return; + } + + latestPageId = pageId; + + const visitorId = await getVisitorId(); + const body: RequestSpaceTrackPageView = { + url: window.location.href, + pageId, + visitor: { + anonymousId: visitorId, + userAgent: window.navigator.userAgent, + language: window.navigator.language, + cookies: cookies.get(), + }, + referrer: document.referrer, + }; + + const url = new URL(apiHost); + url.pathname = `/v1/spaces/${spaceId}/insights/track_view`; + + await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); +}