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.


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.

    Selecting
  3. Click Remove.

    Confirmation modal to remove cookie banners

Anchor to Step 3: Load the Customer Privacy API in HydrogenStep 3: 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 handles loading the Customer Privacy API for you.

Set up analytics provider with your 3p consent management tool

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

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

Use the Customer Privacy API with a hook

/app/components/Your3PConsentManagementTool.jsx
export function ThirdPartyConsent() {
const { register, customerPrivacy } = useAnalytics();
const { ready } = register('ThirdPartyConsent');

// Set up your 3P consent management tool

useEffect(() => {
// If you're having race condition on when this function is available,
// you can consider wrapping this function call inside a document event listener,
// listening for `shopifyCustomerPrivacyApiLoaded` event
customerPrivacy.setTrackingConsent(
{
marketing: getThirdPartyConsentStatus('marketing'),
analytics: getThirdPartyConsentStatus('analytics'),
preferences: getThirdPartyConsentStatus('preferences'),
sale_of_data: getThirdPartyConsentStatus('sale_of_data'),
},
(result: { error: string } | undefined) => {
if (result?.error) {
console.error(
'Error syncing ThirdParty with Shopify customer privacy',
result,
);
return;
}

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

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, Hydrogen's useCustomerPrivacy() hook gives you a method for awaiting the API. This avoids race conditions caused by loading multiple scripts asynchronously:

Load the Customer Privacy API via hook

/app/components/Your3PConsentManagementTool.jsx
const [customerPrivacyReady, setCustomerPrivacyReady] = useState(false);
useCustomerPrivacy({
checkoutDomain: <YOUR_CHECKOUT_DOMAIN>,
storefrontAccessToken: <YOUR_PUBLIC_STOREFRONT_API_TOKEN>
onReady: () => {
setCustomerPrivacyReady(true);
}
});

Anchor to (Optional) Listen to the Customer Privacy on ready event(Optional) Listen to the Customer Privacy on ready event

You can listen to the Customer Privacy API on ready event by listening to the shopifyCustomerPrivacyApiLoaded document event.

Listen to customer privacy on ready event

/app/components/Your3PConsentManagementTool.jsx
useEffect(() => {
document.addEventListener('shopifyCustomerPrivacyApiLoaded', () => {
console.log('Shopify Customer Privacy API loaded');
});
})

Anchor to Step 4: Sync your third-party settings with ShopifyStep 4: 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,
useLoadScript,
} from '@shopify/hydrogen';
import { useEffect, useCallback } from 'react';

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

export function ThirdPartyConsent() {
const { register, customerPrivacy } = useAnalytics();
const { ready } = register('ThirdPartyConsent');
const thirdPartyConsentSdkStatus = useLoadScript(thirdPartyConsentSdkUrl);

const thirdPartyConsentCallback = useCallback(() => {
if (!consent || !consent?.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): boolean {
try {
return window.ThirdPartyConsent.types.includes(type);
} catch (e) {
return false;
}
}
import {
useAnalytics,
useLoadScript,
} from '@shopify/hydrogen';
import { useEffect, useCallback } from 'react';

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

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

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

export function ThirdPartyConsent() {
const { register, customerPrivacy } = useAnalytics();
const { ready } = register('ThirdPartyConsent');
const thirdPartyConsentSdkStatus = useLoadScript(thirdPartyConsentSdkUrl);

const thirdPartyConsentCallback = useCallback(() => {
if (!consent || !consent?.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 (e) {
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 helps synchronize customer preferences seamlessly.

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 (e) {
return false;
}
}}
>
{ /* ... */ }
</Analytics.Provider>

Alternatively, pass your consent services setter function to canTrack

Override canTrack alternate

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

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


Was this page helpful?