mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-25 20:03:16 +00:00
Add Global Privacy Control (GPC) support (#4023)
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
"@gitbook/browser-types": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Global Privacy Control (GPC) support
|
||||||
@@ -90,6 +90,12 @@ export type GitBookGlobal = {
|
|||||||
* and `undefined` when the tracking preference is unknown or not yet determined.
|
* and `undefined` when the tracking preference is unknown or not yet determined.
|
||||||
*/
|
*/
|
||||||
isCookiesTrackingDisabled: () => boolean | undefined;
|
isCookiesTrackingDisabled: () => boolean | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether global privacy control is enabled for the current user.
|
||||||
|
* Returns `true` when global privacy control is enabled, `false` when it is disabled.
|
||||||
|
*/
|
||||||
|
isGlobalPrivacyControlEnabled: () => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import { tcls } from '@/lib/tailwind';
|
|||||||
|
|
||||||
import { useCustomCookieBanner, useIntegrationsLoaded } from '@/components/Integrations';
|
import { useCustomCookieBanner, useIntegrationsLoaded } from '@/components/Integrations';
|
||||||
import { isAIUserAgent } from '@/lib/browser';
|
import { isAIUserAgent } from '@/lib/browser';
|
||||||
import { isCookiesTrackingDisabled, setCookiesTracking } from '../Insights';
|
import {
|
||||||
|
isCookiesTrackingDisabled,
|
||||||
|
isGlobalPrivacyControlEnabled,
|
||||||
|
setCookiesTracking,
|
||||||
|
} from '../Insights';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toast to accept or reject the use of cookies.
|
* Toast to accept or reject the use of cookies.
|
||||||
@@ -20,8 +24,15 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
|
|||||||
const integrationsLoaded = useIntegrationsLoaded();
|
const integrationsLoaded = useIntegrationsLoaded();
|
||||||
const { hasCustomCookieBanner } = useCustomCookieBanner();
|
const { hasCustomCookieBanner } = useCustomCookieBanner();
|
||||||
const isAI = isAIUserAgent();
|
const isAI = isAIUserAgent();
|
||||||
|
const hasGlobalPrivacyControl = isGlobalPrivacyControlEnabled();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
// If global privacy control is enabled, reject cookies
|
||||||
|
if (hasGlobalPrivacyControl && !isCookiesTrackingDisabled()) {
|
||||||
|
setCookiesTracking(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Always wait for integrations to load, and if a custom banner is registered, hide the built-in banner
|
// Always wait for integrations to load, and if a custom banner is registered, hide the built-in banner
|
||||||
if (!integrationsLoaded || hasCustomCookieBanner || isAI) {
|
if (!integrationsLoaded || hasCustomCookieBanner || isAI) {
|
||||||
setShow(false);
|
setShow(false);
|
||||||
@@ -29,7 +40,7 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setShow(isCookiesTrackingDisabled() === undefined);
|
setShow(isCookiesTrackingDisabled() === undefined);
|
||||||
}, [hasCustomCookieBanner, integrationsLoaded, isAI]);
|
}, [hasCustomCookieBanner, integrationsLoaded, isAI, hasGlobalPrivacyControl]);
|
||||||
|
|
||||||
if (!show) {
|
if (!show) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -31,3 +31,22 @@ export function isCookiesTrackingDisabled() {
|
|||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cachedIsGlobalPrivacyControlEnabled: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Get the global privacy control settings of the user.
|
||||||
|
* Return `true` if global privacy control is enabled
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/globalPrivacyControl
|
||||||
|
*/
|
||||||
|
export function isGlobalPrivacyControlEnabled(): boolean {
|
||||||
|
if (cachedIsGlobalPrivacyControlEnabled !== undefined) {
|
||||||
|
return cachedIsGlobalPrivacyControlEnabled;
|
||||||
|
}
|
||||||
|
if (typeof navigator === 'undefined' || !('globalPrivacyControl' in navigator)) {
|
||||||
|
cachedIsGlobalPrivacyControlEnabled = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cachedIsGlobalPrivacyControlEnabled = Boolean(navigator.globalPrivacyControl);
|
||||||
|
return cachedIsGlobalPrivacyControlEnabled;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { isCookiesTrackingDisabled, setCookiesTracking } from '@/components/Insights';
|
import {
|
||||||
|
isCookiesTrackingDisabled,
|
||||||
|
isGlobalPrivacyControlEnabled,
|
||||||
|
setCookiesTracking,
|
||||||
|
} from '@/components/Insights';
|
||||||
import { isAIUserAgent } from '@/lib/browser';
|
import { isAIUserAgent } from '@/lib/browser';
|
||||||
import type {
|
import type {
|
||||||
GitBookGlobal,
|
GitBookGlobal,
|
||||||
@@ -109,6 +113,7 @@ if (typeof window !== 'undefined') {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
isCookiesTrackingDisabled: isCookiesTrackingDisabled,
|
isCookiesTrackingDisabled: isCookiesTrackingDisabled,
|
||||||
|
isGlobalPrivacyControlEnabled: isGlobalPrivacyControlEnabled,
|
||||||
};
|
};
|
||||||
window.GitBook = gitbookGlobal;
|
window.GitBook = gitbookGlobal;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
declare global {
|
||||||
|
interface Navigator {
|
||||||
|
globalPrivacyControl: boolean | undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
Reference in New Issue
Block a user