Skip to content

Commit

Permalink
Fix analytics bugs (#2249)
Browse files Browse the repository at this point in the history
  • Loading branch information
wizardlyhel authored Jun 14, 2024
1 parent 13f3adf commit 593dd30
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 6 deletions.
7 changes: 7 additions & 0 deletions .changeset/dirty-humans-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@shopify/create-hydrogen': patch
'@shopify/hydrogen-react': patch
'@shopify/hydrogen': patch
---

Fix shopify cookie creation and add auto top-level domain detection
97 changes: 97 additions & 0 deletions packages/hydrogen-react/src/useShopifyCookies.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,101 @@ describe(`useShopifyCookies`, () => {

expect(Object.keys(cookieJar).length).toBe(0);
});

it('sets domain to top level domain when checkoutDomain is supplied', () => {
const cookieJar: MockCookieJar = mockCookie();
const domain = 'myshop.com';
const checkoutDomain = 'checkout.myshop.com';

renderHook(() =>
useShopifyCookies({hasUserConsent: true, domain, checkoutDomain}),
);

const cookies = getShopifyCookies(document.cookie);

expect(cookies).toEqual({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_s: expect.any(String),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_y: expect.any(String),
});
expect(cookies['_shopify_s']).not.toBe('');
expect(cookies['_shopify_y']).not.toBe('');

expect(cookieJar['_shopify_s'].value).not.toBe(
cookieJar['_shopify_y'].value,
);
expect(cookieJar['_shopify_s']).toMatchObject({
domain: `.myshop.com`,
maxage: 1800,
});
expect(cookieJar['_shopify_y']).toMatchObject({
domain: `.myshop.com`,
maxage: 31104000,
});
});

it('sets domain to top level domain when domain and checkoutDomain are both subdomains', () => {
const cookieJar: MockCookieJar = mockCookie();
const domain = 'ca.myshop.com';
const checkoutDomain = 'checkout.myshop.com';

renderHook(() =>
useShopifyCookies({hasUserConsent: true, domain, checkoutDomain}),
);

const cookies = getShopifyCookies(document.cookie);

expect(cookies).toEqual({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_s: expect.any(String),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_y: expect.any(String),
});
expect(cookies['_shopify_s']).not.toBe('');
expect(cookies['_shopify_y']).not.toBe('');

expect(cookieJar['_shopify_s'].value).not.toBe(
cookieJar['_shopify_y'].value,
);
expect(cookieJar['_shopify_s']).toMatchObject({
domain: `.myshop.com`,
maxage: 1800,
});
expect(cookieJar['_shopify_y']).toMatchObject({
domain: `.myshop.com`,
maxage: 31104000,
});
});

it('does not set domain on localhost if checkoutDomain is supplied', () => {
const cookieJar: MockCookieJar = mockCookie();
const domain = 'localhost:3000';
const checkoutDomain = 'checkout.myshop.com';

renderHook(() =>
useShopifyCookies({hasUserConsent: true, domain, checkoutDomain}),
);

const cookies = getShopifyCookies(document.cookie);

expect(cookies).toEqual({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_s: expect.any(String),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
_shopify_y: expect.any(String),
});
expect(cookies['_shopify_s']).not.toBe('');
expect(cookies['_shopify_y']).not.toBe('');

expect(cookieJar['_shopify_s'].value).not.toBe(
cookieJar['_shopify_y'].value,
);
expect(cookieJar['_shopify_s']).toMatchObject({
maxage: 1800,
});
expect(cookieJar['_shopify_y']).toMatchObject({
maxage: 31104000,
});
});
});
25 changes: 23 additions & 2 deletions packages/hydrogen-react/src/useShopifyCookies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ type UseShopifyCookiesOptions = {
* The domain scope of the cookie. Defaults to empty string.
**/
domain?: string;
/**
* The checkout domain of the shop. Defaults to empty string. If set, the cookie domain will check if it can be set with the checkout domain.
*/
checkoutDomain?: string;
};

export function useShopifyCookies(options?: UseShopifyCookiesOptions): void {
const {hasUserConsent = false, domain = ''} = options || {};
const {
hasUserConsent = false,
domain = '',
checkoutDomain = '',
} = options || {};
useEffect(() => {
const cookies = getShopifyCookies(document.cookie);

Expand All @@ -34,6 +42,19 @@ export function useShopifyCookies(options?: UseShopifyCookiesOptions): void {
// Use override domain or current host
let currentDomain = domain || window.document.location.host;

if (checkoutDomain) {
const checkoutDomainParts = checkoutDomain.split('.').reverse();
const currentDomainParts = currentDomain.split('.').reverse();
const sameDomainParts: Array<string> = [];
checkoutDomainParts.forEach((part, index) => {
if (part === currentDomainParts[index]) {
sameDomainParts.push(part);
}
});

currentDomain = sameDomainParts.reverse().join('.');
}

// Reset domain if localhost
if (/^localhost/.test(currentDomain)) currentDomain = '';

Expand Down Expand Up @@ -64,7 +85,7 @@ export function useShopifyCookies(options?: UseShopifyCookiesOptions): void {
setCookie(SHOPIFY_Y, '', 0, domainWithLeadingDot);
setCookie(SHOPIFY_S, '', 0, domainWithLeadingDot);
}
}, [options, hasUserConsent, domain]);
}, [options, hasUserConsent, domain, checkoutDomain]);
}

function setCookie(
Expand Down
6 changes: 3 additions & 3 deletions packages/hydrogen/src/analytics-manager/CartAnalytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {flattenConnection} from '@shopify/hydrogen-react';
function logMissingField(fieldName: string) {
// eslint-disable-next-line no-console
console.error(
`[h2:error:CartAnalytics] Unable to set up cart analytics events: ${fieldName} is missing.`,
`[h2:error:CartAnalytics] Can't set up cart analytics events because the \`cart.${fieldName}\` value is missing from your GraphQL cart query. In standard Hydrogen projects, the cart query is contained in \`app/lib/fragments.js\`. Make sure it includes \`cart.${fieldName}\`. Check the Hydrogen Skeleton template for reference: https://github.com/Shopify/hydrogen/blob/main/templates/skeleton/app/lib/fragments.ts#L59.`,
);
}

Expand All @@ -35,11 +35,11 @@ export function CartAnalytics({
Promise.resolve(currentCart).then((updatedCart) => {
if (updatedCart && updatedCart.lines) {
if (!updatedCart.id) {
logMissingField('cart.id');
logMissingField('id');
return;
}
if (!updatedCart.updatedAt) {
logMissingField('cart.updatedAt');
logMissingField('updatedAt');
return;
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/hydrogen/src/analytics-manager/ShopifyAnalytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ export function ShopifyAnalytics({
});

useShopifyCookies({
hasUserConsent: canTrack(),
hasUserConsent: shopifyReady && privacyReady ? canTrack() : true,
domain,
checkoutDomain,
});

useEffect(() => {
Expand Down

0 comments on commit 593dd30

Please sign in to comment.