Skip to main content

Integrate third-party consent management with Hydrogen

If you use a third-party service to track customer consent, then you'll need to connect it to Shopify’s Customer Privacy API. You can also use Shopify's built-in cookie banner to get consent from your customers.


Remove the Shopify cookie banner while keeping the consent regions active. This allows you to use your third-party banner.

  1. From your Shopify admin, go to Settings > Customer Privacy > Cookie banner.

  2. Click More actions and select Remove cookie banner.

    Remove cookie banner selected in the More actions menu
  3. Click Remove.

    Confirmation modal to remove cookie banners

Anchor to Step 2: Load the Customer Privacy API in HydrogenStep 2: Load the Customer Privacy API in Hydrogen

Switch to your Hydrogen codebase and load the Customer Privacy API to track consent:

Note

You're responsible for ensuring that all analytics you're sending from your Hydrogen site are compliant with consent laws.

We recommend using Hydrogen's built-in <Analytics.Provider> component. It automatically handles publishing and subscribing to analytics events, and it loads the Customer Privacy API for you.

<Analytics.Provider> loads the Customer Privacy API, but components that call customerPrivacy methods should use useCustomerPrivacy() to access the API object. Use useAnalytics() for analytics registration.

Set up analytics provider with your third-party consent management tool

/app/routes/root.jsx
<Analytics.Provider
...
>
...
<ThirdPartyConsent />
</Analytics.Provider>

You can access the Customer Privacy API with the useCustomerPrivacy hook.

Use the Customer Privacy API with a hook

/app/components/Your3PConsentManagementTool.jsx
import {useAnalytics, useCustomerPrivacy} from '@shopify/hydrogen';
import {useEffect} from 'react';

export function ThirdPartyConsent() {
const {register} = useAnalytics();
const {customerPrivacy} = useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
});
const {ready} = register('ThirdPartyConsent');

useEffect(() => {
if (!customerPrivacy?.setTrackingConsent) {
return;
}

customerPrivacy.setTrackingConsent(
{
marketing: getThirdPartyConsentStatus('marketing'),
analytics: getThirdPartyConsentStatus('analytics'),
preferences: getThirdPartyConsentStatus('preferences'),
sale_of_data: getThirdPartyConsentStatus('sale_of_data'),
},
(result) => {
if (result?.error) {
console.error(
'Error syncing ThirdParty with Shopify customer privacy',
result,
);
return;
}

ready();
},
);
}, [customerPrivacy, ready]);

return null;
}

Anchor to Set up a Storefront API proxy for custom implementations (Optional)Set up a Storefront API proxy for custom implementations (Optional)

Shopify uses HTTP-only cookies to securely track consent and analytics. For these cookies to work correctly, your storefront must be able to query the Storefront API under the same origin (your store domain).

If you're using Hydrogen's createRequestHandler, then it sets up this proxy for you, and the <Analytics.Provider> component detects it automatically.

If you're using a custom proxy instead, then pass sameDomainForStorefrontApi: true in the consent prop:

Use custom Storefront API proxy

/app/routes/root.jsx
<Analytics.Provider
consent={{
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
sameDomainForStorefrontApi: true,
}}
>
...
</Analytics.Provider>

Because the ThirdPartyConsent component calls useCustomerPrivacy() directly, you also need to pass sameDomainForStorefrontApi: true to that hook. The hook is configured independently and doesn't inherit the consent prop from <Analytics.Provider>. If you don't pass the flag, then the hook defaults to detecting the proxy automatically and can send consent requests to the wrong domain:

Use custom Storefront API proxy with the hook

/app/components/Your3PConsentManagementTool.jsx
const {customerPrivacy} = useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
sameDomainForStorefrontApi: true,
});

Anchor to Method 2: Load the API manually with the ,[object Object], hookMethod 2: Load the API manually with the useCustomerPrivacy hook

If you need to handle loading the Customer Privacy API yourself, then Hydrogen's useCustomerPrivacy() hook gives you a method for awaiting the API. Using this hook avoids race conditions caused by loading multiple scripts asynchronously.

Hydrogen's useCustomerPrivacy() hook takes checkoutDomain and storefrontAccessToken. Don't pass the raw Customer Privacy API parameters headlessStorefront, checkoutRootDomain, or storefrontRootDomain to the hook. Hydrogen derives and passes the lower-level root-domain configuration for you. If you use a custom Storefront API proxy, then pass sameDomainForStorefrontApi: true as shown in the following example.

Load the Customer Privacy API with a hook

/app/components/Your3PConsentManagementTool.jsx
const [customerPrivacyReady, setCustomerPrivacyReady] = useState(false);

useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
onReady: () => {
setCustomerPrivacyReady(true);
},
});

Anchor to Set up a Storefront API proxy for custom implementations (Optional)Set up a Storefront API proxy for custom implementations (Optional)

Shopify uses HTTP-only cookies to securely track consent and analytics. For these cookies to work correctly, your storefront must be able to query the Storefront API under the same origin (your store domain).

If you're using Hydrogen's createRequestHandler, then it sets up this proxy for you, and the useCustomerPrivacy hook detects it automatically.

If you're using a custom proxy instead, then pass sameDomainForStorefrontApi: true to the useCustomerPrivacy hook:

Use custom Storefront API proxy

/app/components/Your3PConsentManagementTool.jsx
useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
sameDomainForStorefrontApi: true,
onReady: () => {
setCustomerPrivacyReady(true);
},
});

Anchor to Listen for the Customer Privacy API ready event (Optional)Listen for the Customer Privacy API ready event (Optional)

You can listen for the shopifyCustomerPrivacyApiLoaded document event to check when the Customer Privacy API is ready.

Listen for the Customer Privacy API ready event

/app/components/Your3PConsentManagementTool.jsx
useEffect(() => {
const logCustomerPrivacyReady = () => {
console.log('Shopify Customer Privacy API loaded');
};

document.addEventListener(
'shopifyCustomerPrivacyApiLoaded',
logCustomerPrivacyReady,
);

return () => {
document.removeEventListener(
'shopifyCustomerPrivacyApiLoaded',
logCustomerPrivacyReady,
);
};
}, []);

Anchor to Step 3: Sync your third-party settings with ShopifyStep 3: Sync your third-party settings with Shopify

After the Customer Privacy API is loaded, you can integrate your consent provider's SDK and pass consent preferences to Shopify. Check your provider's documentation for specific details on retrieving the data you need.

Anchor to Example implementationExample implementation

The following example shows how you can integrate a third-party consent management tool with Shopify Analytics in Hydrogen:

Sync consent settings with Shopify

/app/components/ThirdPartyConsent.jsx

import {
useAnalytics,
useCustomerPrivacy,
useLoadScript,
} from '@shopify/hydrogen';
import {useCallback, useEffect} from 'react';

const thirdPartyConsentSdkUrl = `https://cdn.thirdpartyconsent.com/sdk.js`;

export function ThirdPartyConsent() {
const {register} = useAnalytics();
const {customerPrivacy} = useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
});
const {ready} = register('ThirdPartyConsent');
const thirdPartyConsentSdkStatus = useLoadScript(thirdPartyConsentSdkUrl);

const thirdPartyConsentCallback = useCallback(() => {
if (!customerPrivacy?.setTrackingConsent) {
return;
}

const trackingConsent = {
marketing: getThirdPartyConsentStatus('marketing'),
analytics: getThirdPartyConsentStatus('analytics'),
preferences: getThirdPartyConsentStatus('preferences'),
sale_of_data: getThirdPartyConsentStatus('sale_of_data'),
};

customerPrivacy.setTrackingConsent(
trackingConsent,
(result) => {
if (result?.error) {
console.error(
'Error syncing ThirdParty with Shopify customer privacy',
result,
);
return;
}

ready();
},
);
}, [customerPrivacy, ready]);

useEffect(() => {
if (thirdPartyConsentSdkStatus !== 'done') {
return;
}

window.ThirdPartyConsent.onChange = thirdPartyConsentCallback;
thirdPartyConsentCallback();
}, [thirdPartyConsentCallback, thirdPartyConsentSdkStatus]);

return null;
}

export function getThirdPartyConsentStatus(type) {
try {
return window.ThirdPartyConsent.types.includes(type);
} catch {
return false;
}
}
import {
useAnalytics,
useCustomerPrivacy,
useLoadScript,
} from '@shopify/hydrogen';
import {useCallback, useEffect} from 'react';

type ThirdPartyConsentType =
| 'marketing'
| 'analytics'
| 'preferences'
| 'sale_of_data';

declare global {
interface Window {
ThirdPartyConsent: {
onChange: () => void;
types: Array<ThirdPartyConsentType>;
};
}
}

const thirdPartyConsentSdkUrl = `https://cdn.thirdpartyconsent.com/sdk.js`;

export function ThirdPartyConsent() {
const {register} = useAnalytics();
const {customerPrivacy} = useCustomerPrivacy({
storefrontAccessToken: '<YOUR_PUBLIC_STOREFRONT_API_TOKEN>',
checkoutDomain: '<YOUR_CHECKOUT_DOMAIN>',
});
const {ready} = register('ThirdPartyConsent');
const thirdPartyConsentSdkStatus = useLoadScript(thirdPartyConsentSdkUrl);

const thirdPartyConsentCallback = useCallback(() => {
if (!customerPrivacy?.setTrackingConsent) {
return;
}

const trackingConsent = {
marketing: getThirdPartyConsentStatus('marketing'),
analytics: getThirdPartyConsentStatus('analytics'),
preferences: getThirdPartyConsentStatus('preferences'),
sale_of_data: getThirdPartyConsentStatus('sale_of_data'),
};

customerPrivacy.setTrackingConsent(
trackingConsent,
(result: {error: string} | undefined) => {
if (result?.error) {
console.error(
'Error syncing ThirdParty with Shopify customer privacy',
result,
);
return;
}

ready();
},
);
}, [customerPrivacy, ready]);

useEffect(() => {
if (thirdPartyConsentSdkStatus !== 'done') {
return;
}

window.ThirdPartyConsent.onChange = thirdPartyConsentCallback;
thirdPartyConsentCallback();
}, [thirdPartyConsentCallback, thirdPartyConsentSdkStatus]);

return null;
}

export function getThirdPartyConsentStatus(
type: ThirdPartyConsentType,
): boolean {
try {
return window.ThirdPartyConsent.types.includes(type);
} catch {
return false;
}
}

At this point, your Hydrogen storefront should be connected to both your third-party provider and Shopify's Customer Privacy API. This setup synchronizes customer preferences.

Check with your provider for documentation on testing your integration. Not all consent management tools can be tested locally.


Anchor to Overriding tracking with ,[object Object], (Optional)Overriding tracking with canTrack (Optional)

You can customize the <Analytics.Provider> component with the canTrack prop, which controls whether analytics events can be published for the current session.

By default, canTrack returns the value of window.Shopify.customerPrivacy.analyticsProcessingAllowed(). You can also pass a custom function if needed. Make sure that this function only renders on the client and not on the server:

Override canTrack

/app/routes/root.jsx
<Analytics.Provider
canTrack={() => {
try {
return window.some3PConsentTool.getConsent(); // Boolean
} catch {
return false;
}
}}
>
{ /* ... */ }
</Analytics.Provider>

Alternatively, pass your consent service's setter function to canTrack.

Override canTrack alternate

/app/routes/root.jsx
import {getThirdPartyConsentStatus} from '~/components/ThirdPartyConsent';

<Analytics.Provider
canTrack={() => {
return getThirdPartyConsentStatus('analytics');
}}
>
{ /* ... */ }
</Analytics.Provider>

  • Make sure that source maps are enabled. This makes it easier to debug any issues with analytics tracking.
  • If analytics tracking fails when users navigate to the checkout page, make sure that the _tracking_consent cookie is set to your checkout domain. For example, if your checkout domain is checkout.your-site.com then your _tracking_consent cookie should be .your-site.com.


Was this page helpful?