Skip to content

Commit 009ed8c

Browse files
authored
Call trackViewInSiteById API endpoint when tracking view for sites (#2350)
1 parent 106cbbd commit 009ed8c

File tree

3 files changed

+92
-22
lines changed

3 files changed

+92
-22
lines changed

src/app/(space)/(content)/[[...pathname]]/page.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ export default async function Page(props: { params: PagePathParams }) {
2323
const { params } = props;
2424

2525
const rawPathname = getPathnameParam(params);
26-
const { contentTarget, space, customization, pages, page, document } =
27-
await fetchPageData(params);
26+
const {
27+
content: contentPointer,
28+
contentTarget,
29+
space,
30+
customization,
31+
pages,
32+
page,
33+
document,
34+
} = await fetchPageData(params);
2835
const linksContext: PageHrefContext = {};
2936

3037
if (!page) {
@@ -63,6 +70,7 @@ export default async function Page(props: { params: PagePathParams }) {
6370
<div className={tcls('flex', 'flex-row')}>
6471
<PageBody
6572
space={space}
73+
contentPointer={contentPointer}
6674
contentTarget={contentTarget}
6775
customization={customization}
6876
context={contentRefContext}

src/components/PageBody/PageBody.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React from 'react';
99

1010
import { getSpaceLanguage } from '@/intl/server';
1111
import { t } from '@/intl/translate';
12-
import { ContentTarget, api } from '@/lib/api';
12+
import { ContentPointer, ContentTarget, SiteContentPointer, api } from '@/lib/api';
1313
import { hasFullWidthBlock, isNodeEmpty } from '@/lib/document';
1414
import { ContentRefContext, resolveContentRef } from '@/lib/references';
1515
import { tcls } from '@/lib/tailwind';
@@ -25,20 +25,33 @@ import { DateRelative } from '../primitives';
2525

2626
export function PageBody(props: {
2727
space: Space;
28+
contentPointer: ContentPointer | SiteContentPointer;
2829
contentTarget: ContentTarget;
2930
customization: CustomizationSettings | SiteCustomizationSettings;
3031
page: RevisionPageDocument;
3132
document: JSONDocument | null;
3233
context: ContentRefContext;
3334
withPageFeedback: boolean;
3435
}) {
35-
const { space, contentTarget, customization, context, page, document, withPageFeedback } =
36-
props;
36+
const {
37+
space,
38+
contentPointer,
39+
contentTarget,
40+
customization,
41+
context,
42+
page,
43+
document,
44+
withPageFeedback,
45+
} = props;
3746

3847
const asFullWidth = document ? hasFullWidthBlock(document) : false;
3948
const language = getSpaceLanguage(customization);
4049
const updatedAt = page.updatedAt ?? page.createdAt;
4150
const shouldHighlightCode = createHighlightingContext();
51+
const sitePointer =
52+
'siteId' in contentPointer
53+
? { organizationId: contentPointer.organizationId, siteId: contentPointer.siteId }
54+
: undefined;
4255

4356
return (
4457
<>
@@ -129,7 +142,12 @@ export function PageBody(props: {
129142
</div>
130143
</main>
131144
<React.Suspense fallback={null}>
132-
<TrackPageView spaceId={space.id} pageId={page.id} apiHost={api().endpoint} />
145+
<TrackPageView
146+
sitePointer={sitePointer}
147+
spaceId={space.id}
148+
pageId={page.id}
149+
apiHost={api().endpoint}
150+
/>
133151
</React.Suspense>
134152
</>
135153
);

src/components/PageBody/TrackPageView.tsx

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,80 @@
11
'use client';
22

3-
import type { RequestSpaceTrackPageView } from '@gitbook/api';
3+
import type { RequestSiteTrackPageView, RequestSpaceTrackPageView } from '@gitbook/api';
44
import cookies from 'js-cookie';
55
import * as React from 'react';
66

77
import { getVisitorId } from '@/lib/analytics';
8+
import { SiteContentPointer } from '@/lib/api';
89

910
/**
1011
* Track the page view for the current page to integrations.
1112
*/
1213
export function TrackPageView(props: {
1314
apiHost: string;
15+
sitePointer?: Pick<SiteContentPointer, 'siteId' | 'organizationId'>;
1416
spaceId: string;
1517
pageId: string | undefined;
1618
}) {
17-
const { apiHost, spaceId, pageId } = props;
19+
const { apiHost, sitePointer, spaceId, pageId } = props;
1820

1921
React.useEffect(() => {
20-
trackPageView(apiHost, spaceId, pageId);
21-
}, [apiHost, spaceId, pageId]);
22+
trackPageView({ apiHost, sitePointer, spaceId, pageId });
23+
}, [apiHost, spaceId, pageId, sitePointer]);
2224

2325
return null;
2426
}
2527

28+
async function sendSpaceTrackPageViewRequest(args: {
29+
apiHost: string;
30+
spaceId: string;
31+
body: RequestSpaceTrackPageView;
32+
}) {
33+
const { apiHost, spaceId, body } = args;
34+
const url = new URL(apiHost);
35+
url.pathname = `/v1/spaces/${spaceId}/insights/track_view`;
36+
37+
await fetch(url, {
38+
method: 'POST',
39+
headers: {
40+
'Content-Type': 'application/json',
41+
},
42+
body: JSON.stringify(body),
43+
});
44+
}
45+
46+
async function sendSiteTrackPageViewRequest(args: {
47+
apiHost: string;
48+
sitePointer: Pick<SiteContentPointer, 'siteId' | 'organizationId'>;
49+
body: RequestSiteTrackPageView;
50+
}) {
51+
const { apiHost, sitePointer, body } = args;
52+
const url = new URL(apiHost);
53+
url.pathname = `/v1/orgs/${sitePointer.organizationId}/sites/${sitePointer.siteId}/insights/track_view`;
54+
55+
await fetch(url, {
56+
method: 'POST',
57+
headers: {
58+
'Content-Type': 'application/json',
59+
},
60+
body: JSON.stringify(body),
61+
});
62+
}
63+
2664
let latestPageId: string | undefined | null = null;
2765

2866
/**
2967
* Track the page view for the current page to GitBook.
3068
* We don't use the API client to avoid shipping 80kb of JS to the client.
3169
* And instead use a simple fetch.
3270
*/
33-
async function trackPageView(apiHost: string, spaceId: string, pageId: string | undefined) {
71+
async function trackPageView(args: {
72+
apiHost: string;
73+
sitePointer?: Pick<SiteContentPointer, 'siteId' | 'organizationId'>;
74+
spaceId: string;
75+
pageId: string | undefined;
76+
}) {
77+
const { apiHost, sitePointer, pageId, spaceId } = args;
3478
if (pageId === latestPageId) {
3579
// The hook can be called multiple times, we only want to track once.
3680
return;
@@ -39,7 +83,7 @@ async function trackPageView(apiHost: string, spaceId: string, pageId: string |
3983
latestPageId = pageId;
4084

4185
const visitorId = await getVisitorId();
42-
const body: RequestSpaceTrackPageView = {
86+
const sharedTrackedProps = {
4387
url: window.location.href,
4488
pageId,
4589
visitor: {
@@ -51,17 +95,17 @@ async function trackPageView(apiHost: string, spaceId: string, pageId: string |
5195
referrer: document.referrer,
5296
};
5397

54-
const url = new URL(apiHost);
55-
url.pathname = `/v1/spaces/${spaceId}/insights/track_view`;
56-
5798
try {
58-
await fetch(url, {
59-
method: 'POST',
60-
headers: {
61-
'Content-Type': 'application/json',
62-
},
63-
body: JSON.stringify(body),
64-
});
99+
sitePointer
100+
? await sendSiteTrackPageViewRequest({
101+
apiHost,
102+
sitePointer,
103+
body: {
104+
...sharedTrackedProps,
105+
spaceId,
106+
},
107+
})
108+
: await sendSpaceTrackPageViewRequest({ apiHost, spaceId, body: sharedTrackedProps });
65109
} catch (error) {
66110
console.error('Failed to track page view', error);
67111
}

0 commit comments

Comments
 (0)