-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Added Shopify Analytics #1318
base: main
Are you sure you want to change the base?
Conversation
@oybek-daniyarov is attempting to deploy a commit to the Vercel Solutions Team on Vercel. A member of the Team first needs to authorize it. |
# Conflicts: # package.json # pnpm-lock.yaml
just implemented this on my ecommerce, and worked as intended. thanks |
Great solution. Do you happen to know how to implement the privacy consent banner? I think it can be done in a similar fashion... |
@Itisfilipe You need to do a few steps inside the GTM and on the component level. Inside the GTM container, you need to enable consent, and for all the tags you should change them from page view to custom event "cookie_consent_update" Here is the base script. I hope it will help. and inside your shopify analytics script you need to check the localConsent value i'm working on the tutorial at the moment i will publish it in a few days I'm using
Consent.tsx 'use client';
import { XIcon } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { useCookies } from 'next-client-cookies';
import React, { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
type Props = {
message: string;
labels: {
accept: string;
deny: string;
};
};
function updateConsent(access: 'granted' | 'denied') {
gtag('consent', 'update', {
ad_storage: access,
analytics_storage: access,
ad_user_data: access,
personalization_storage: access,
ad_personalization: access,
functionality_storage: access,
security_storage: access,
});
}
function Consent({ message, labels }: Props) {
const pathname = usePathname();
const [consent, setConsent] = useState(true);
const cookies = useCookies();
const handleAccept = () => {
setConsent(true);
cookies.set('localConsent', 'true');
};
const handleClose = () => {
setConsent(true);
};
const handleDeny = () => {
setConsent(true);
cookies.set('localConsent', 'false');
};
// Check if user has given consent
useEffect(() => {
const consentStatus = cookies.get('localConsent') === 'true';
setConsent(consentStatus);
if (consentStatus) {
updateConsent('granted');
} else {
updateConsent('denied');
}
}, [cookies]);
// Update consent status on page change
useEffect(() => {
if (consent) {
gtag('event', 'cookie_consent_update');
}
}, [pathname, consent]);
return !consent ? (
<div
id='banner'
tabIndex={-1}
aria-hidden='false'
className='fixed bottom-0 z-50 w-full overflow-y-auto overflow-x-hidden drop-shadow-2xl md:inset-x-0'
>
<div className='relative size-full md:h-auto'>
<div className='relative bg-white shadow'>
<div className='items-center justify-between p-5 lg:flex'>
{message && (
<div className='mb-4 text-dark-blue lg:mb-0'>
{message}
</div>
)}
<div className='flex shrink-0 items-center gap-1 sm:flex lg:pl-10'>
<Button size='sm' type='button' onClick={handleDeny}>
{labels.deny}
</Button>
<Button size='sm' type='button' onClick={handleAccept}>
{labels.accept}
</Button>
<button
onClick={handleClose}
aria-label='Close banner'
id='close-modal'
type='button'
className='ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 md:flex'
>
<XIcon className='size-5' />
</button>
</div>
</div>
</div>
</div>
</div>
) : null;
}
export default Consent; GoogleTagManager.tsx import Script from 'next/script';
import type { FC } from 'react';
type Props = {
id: string;
};
const GoogleTagManager: FC<Props> = ({ id }) => {
return (
<Script
id='gtm-init'
strategy='afterInteractive'
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${id}');
`,
}}
/>
);
};
export default GoogleTagManager; |
Thank you! I was talking about the Shopify consent form but this helped me to use the one they provide and even configure GTM. Another question: you said you configured the other events
Did you do that with the same hydrogen-react library? Those events aren't mentioned in the official docs 🤔 |
Their documentation sucks. They don't want us to use anything outside of the remix :), so I had to inspect their demo store using the developer tools to understand how it works. but I'm not 100% sure if that is accurate or not |
This is pretty neat. Thanks for making the PR. They might give you a bit of a hard time with your code formatter (i.e. breaking the README lines into multiple shorter lines) but the feat is great. |
Implementation of Shopify analytics with verce/commerce
Analytics have been enabled for the following events.
✅ Page view
✅ Add to cart (add to cart event, it will also enable tracking on checkout page and purchase event)
Todo
(I already have ready solution, but I'm afraid PR will get larger) I can do it in follow-up PR
For Shopify's ADD_TO_CART analytics to function correctly, it's important to note that they will not work with localhost
links directly due to cookie handling.
To enable these analytics features during local development, we can use
ngrok
your localhost, making it accessible over the internet.
it ensures URL consistency, which helps maintain the cookies required for Shopify analytics.
expose it to the internet with the following ngrok command:
Screenshot from Shopify dashboard
a4a16dba-bc68-44c3-852e-e8445b4bba7c.mp4