Skip to content

Commit d270b4a

Browse files
authored
Don't track events if a special middleware header is set. (#3511)
1 parent ccfbd3c commit d270b4a

File tree

6 files changed

+36
-13
lines changed

6 files changed

+36
-13
lines changed

.changeset/kind-bulldogs-draw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"gitbook": patch
3+
---
4+
5+
All tracking is now disabled for dynamic routes such as the site preview.

packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/(content)/layout.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import {
55
generateSiteLayoutMetadata,
66
generateSiteLayoutViewport,
77
} from '@/components/SiteLayout';
8-
import { GITBOOK_DISABLE_TRACKING } from '@/lib/env';
98
import { getThemeFromMiddleware } from '@/lib/middleware';
9+
import { shouldTrackEvents } from '@/lib/tracking';
10+
import { headers } from 'next/headers';
1011

1112
interface SiteDynamicLayoutProps {
1213
params: Promise<RouteLayoutParams>;
@@ -18,13 +19,14 @@ export default async function SiteDynamicLayout({
1819
}: React.PropsWithChildren<SiteDynamicLayoutProps>) {
1920
const { context, visitorAuthClaims } = await getDynamicSiteContext(await params);
2021
const forcedTheme = await getThemeFromMiddleware();
22+
const withTracking = shouldTrackEvents(await headers());
2123

2224
return (
2325
<CustomizationRootLayout forcedTheme={forcedTheme} customization={context.customization}>
2426
<SiteLayout
2527
context={context}
2628
forcedTheme={forcedTheme}
27-
withTracking={!GITBOOK_DISABLE_TRACKING}
29+
withTracking={withTracking}
2830
visitorAuthClaims={visitorAuthClaims}
2931
>
3032
{children}

packages/gitbook/src/app/sites/static/[mode]/[siteURL]/[siteData]/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
generateSiteLayoutMetadata,
66
generateSiteLayoutViewport,
77
} from '@/components/SiteLayout';
8-
import { GITBOOK_DISABLE_TRACKING } from '@/lib/env';
8+
import { shouldTrackEvents } from '@/lib/tracking';
99

1010
interface SiteStaticLayoutProps {
1111
params: Promise<RouteLayoutParams>;
@@ -16,12 +16,13 @@ export default async function SiteStaticLayout({
1616
children,
1717
}: React.PropsWithChildren<SiteStaticLayoutProps>) {
1818
const { context, visitorAuthClaims } = await getStaticSiteContext(await params);
19+
const withTracking = shouldTrackEvents();
1920

2021
return (
2122
<CustomizationRootLayout customization={context.customization}>
2223
<SiteLayout
2324
context={context}
24-
withTracking={!GITBOOK_DISABLE_TRACKING}
25+
withTracking={withTracking}
2526
visitorAuthClaims={visitorAuthClaims}
2627
>
2728
{children}

packages/gitbook/src/components/SiteLayout/SiteLayout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export async function SiteLayout(props: {
3030
}) {
3131
const { context, nonce, forcedTheme, withTracking, visitorAuthClaims, children } = props;
3232

33-
const { scripts, customization } = context;
33+
const { customization } = context;
34+
// Scripts are disabled when tracking is disabled
35+
const scripts = withTracking ? context.scripts : [];
3436

3537
ReactDOM.preconnect(GITBOOK_API_PUBLIC_URL);
3638
ReactDOM.preconnect(GITBOOK_ICONS_URL);

packages/gitbook/src/lib/tracking.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
import { headers } from 'next/headers';
1+
import type { headers as nextHeaders } from 'next/headers';
2+
import { GITBOOK_DISABLE_TRACKING } from './env';
23

34
/**
45
* Return true if events should be tracked on the site.
6+
* Can be called from the static context or the dynamic context.
7+
* In the static context, only an env variable is checked.
8+
* In the dynamic context, the request headers are checked - this allows the middleware
9+
* to disable tracking for preview requests.
510
*/
6-
export async function shouldTrackEvents(): Promise<boolean> {
7-
const headersList = await headers();
11+
export function shouldTrackEvents(headers?: Awaited<ReturnType<typeof nextHeaders>>): boolean {
12+
if (GITBOOK_DISABLE_TRACKING) {
13+
return false;
14+
}
15+
16+
const disableTrackingHeader = headers?.get('x-gitbook-disable-tracking');
817

9-
if (
10-
process.env.NODE_ENV === 'development' ||
11-
(process.env.GITBOOK_BLOCK_PAGE_VIEWS_TRACKING &&
12-
!headersList.has('x-gitbook-track-page-views'))
13-
) {
18+
if (disableTrackingHeader === 'true') {
1419
return false;
1520
}
1621

packages/gitbook/src/middleware.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) {
141141
url: siteRequestURL,
142142
});
143143

144+
//
145+
// Strip the tracking header to prevent users providing it themselves.
146+
//
147+
request.headers.delete('x-gitbook-disable-tracking');
148+
144149
const withAPIToken = async (apiToken: string | null) => {
145150
const siteURLData = await throwIfDataError(
146151
lookupPublishedContentByUrl({
@@ -340,6 +345,9 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) {
340345

341346
// For https://preview/<siteURL> requests,
342347
if (siteRequestURL.hostname === 'preview') {
348+
// Do not track page views for preview requests
349+
request.headers.set('x-gitbook-disable-tracking', 'true');
350+
343351
return serveWithQueryAPIToken(
344352
// We scope the API token to the site ID.
345353
`${siteRequestURL.hostname}/${requestURL.pathname.slice(1).split('/')[0]}`,

0 commit comments

Comments
 (0)