Skip to content
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

Analytics Provider, Customer Privacy API and Privacy Banner #1789

Merged
merged 135 commits into from
Apr 10, 2024

Conversation

wizardlyhel
Copy link
Contributor

@wizardlyhel wizardlyhel commented Feb 22, 2024

Support for Customer Privacy API and better Analytics DX

Proposed developer experience

1. Return the consent configuration

In your root.tsx loader return the consent configuration

export async function loader({context}: LoaderFunctionArgs) {
  return defer({
      // ...other root loader data
+     consent: {
+       checkoutRootDomain: env.PUBLIC_CHECKOUT_DOMAIN,
+       storefrontAccessToken: env.PUBLIC_STOREFRONT_API_TOKEN,
+     }
  });
});

2. Add the <Analytics> for facilitating analytics events and instrumenting page view and cart events.

<Analytics> props

  • canTrack - defaults to Shopify.customerPrivacy.userCanBeTracked
  • cart - can be a deferred promise or an object. If this is defined, cart events will be published
  • consent - configuration for the consent API banner
  • shop - can be a deferred promise or object. If this is defined, Shopify will send analytics
  • customPayload - data to be made available on any analytics events
+ import { Analytics } from '@shopify/hydrogen';

export default function App() {
  const data = useLoaderData<typeof loader>();

  return (
    <html lang="en">
      <body>
+        <Analytics.Provider
+           cart={data.cart}
+           consent={data.consent}
+           shop={data.shop}
+           customData={{foo: 'bar'}} // (optional) will be added to all event payloads
+        >
          <Layout {...data}>
            <Outlet />
          </Layout>
+        </Analytics.Provider>
      </body>
    </html>
  );
}

3. Add page view event for product, collection, cart, search views.

In your product route files,

+ import { Analytics } from '@shopify/hydrogen';

export default function Product() {
  const {product, variants} = useLoaderData<typeof loader>();
  const {selectedVariant} = product;
  return (
    <div className="product">
      <ProductImage image={selectedVariant?.image} />
      <ProductMain
        selectedVariant={selectedVariant}
        product={product}
        variants={variants}
      />
+      <Analytics.ProductView 
+        data={{
+          product: {
+            id: product.id,
+.           title: product.title,
+.           handle: product.handle,
+          }
+         }}
+      />
    </div>
  );
}

4. Publish your own custom events

Anywhere within <AnalyticsProvider>, use the useAnalyticsProvider hook to give you the function to publish additional events.

+ import { useAnalytics } from '@shopify/hydrogen';

export function AnalyticsCheckbox({name}) {
  const {publish} = useAnalytics();
  return (
    <input type="checkbox"
+      onChange={(event) => {
+         publish('custom_checkbox_updated', {
+           name,
+           value: event.targetSrc.checked
+         })
+      }}
    />
  );
}

5. Subscribe to analytics events

Anywhere within <AnalyticsProvider>, use the useAnalyticsProvider hook to give you the function to subscribe to analytics events published within the provider.

+ import { useAnalytics } from '@shopify/hydrogen';

+ export function CustomAnalytics() {
+   const {subscribe} = useAnalytics();
+   useEffect(() => {
+     subscribe('page_viewed', (data) => {
+       console.log('CustomAnalytics - Page viewed:', data);
+     });
+     subscribe('product_viewed', (data) => {
+       console.log('CustomAnalytics - Product viewed:', data);
+     });
+     subscribe('checkbox_updated', (payload) => {
+       console.log('CustomAnalytics - Checkbox updated:', data);
+     });
+     subscribe('cart_updated', (data) => {
+       console.log('CustomAnalytics - cart updated:', data);  // {previousCart, currentCart}
+     });
+     subscribe('product_removed_from_cart', (data) => {
+       console.log('CustomAnalytics - Product removed from cart:', data);
+     });
+   }, []);
+ 
+   return null;
+ }

WHAT is this pull request doing?

HOW to test your changes?

Post-merge steps

Checklist

  • I've read the Contributing Guidelines
  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've added a changeset if this PR contains user-facing or noteworthy changes
  • I've added tests to cover my changes
  • I've added or updated the documentation

@wizardlyhel wizardlyhel changed the title POC - analytics manager POC - analytics provider, customer privacy api and privacy banner Mar 1, 2024
Copy link
Contributor

@frandiox frandiox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! 🔥

@wizardlyhel wizardlyhel merged commit f4d6e5b into main Apr 10, 2024
10 of 13 checks passed
@wizardlyhel wizardlyhel deleted the hl-analytics-manager branch April 10, 2024 17:53
@jonrrivera
Copy link

so how do we implement this ? :)

@wizardlyhel
Copy link
Contributor Author

@jonrrivera Please follow the readme in example https://github.com/Shopify/hydrogen/tree/main/examples/analytics

We are working on an official tutorial on shopify.dev

@j-Riv
Copy link

j-Riv commented May 13, 2024

@wizardlyhel the analytics example that you linked above is marked unstable, is this still the case or are we ok to use this in production? I'm trying to get Google Analytics and Meta Pixel running on our Hydrogen Store. Thank you.

@wizardlyhel
Copy link
Contributor Author

We are just ironing out some bugs when used with 3p consent management tools. Other than that, the api interface is fairly stable . We don't anticipate any more big changes

@j-Riv
Copy link

j-Riv commented May 15, 2024

@wizardlyhel is there any way to test that custom pixels are actually firing?

@wizardlyhel
Copy link
Contributor Author

@j-Riv You can use this as an example to see console logs when the events are firing https://github.com/Shopify/hydrogen/blob/main/examples/analytics/app/components/CustomAnalytics.tsx

Make sure to include this component in your root.tsx within <Analytics.Provider>

@shubhambitqit
Copy link

@wizardlyhel I tried following the example but still unable to see any logs.

@wizardlyhel
Copy link
Contributor Author

The unstable version didn't have much error warnings. The stable version will let you know what's missing. Double check the following:

  1. Check that you have the customer privacy cookie banner turned on in your Shopify admin (This won't be a requirement in the next release)
  2. Make sure you have PUBLIC_STOREFRONT_API_TOKEN, PUBLIC_STORE_DOMAIN, PUBLIC_CHECKOUT_DOMAIN defined in your local .env. Do not use the private token's value in place of the PUBLIC_STOREFRONT_API_TOKEN's value. If you are testing in production, make sure PUBLIC_CHECKOUT_DOMAIN is in the storefront's environment variables.
  3. If you are overriding <Analytics.Provider>'s canTrack property, make sure this callback returns a true at some point. If it doesn't return true, no analytics will be sent
  4. Make sure there is no content security error or network error to the checkout domain url in console log

@shubhambitqit
Copy link

@wizardlyhel Thanks for the reply.
I am following all the points but I am getting a unauthorized error in my console.log though, for this url https://checkout.hydrogen.shop/api/unstable/graphql.json
Screenshot from 2024-05-29 12-14-08

@wizardlyhel
Copy link
Contributor Author

Make sure the PUBLIC_CHECKOUT_DOMAIN in your .env file and also in storefront custom environment variables isn't set to checkout.hydrogen.shop but instead to the domain url of your own checkout.

If you don't know what that is, navigate to the checkout of your own store and copy that domain value and set it for PUBLIC_CHECKOUT_DOMAIN

@johnark88
Copy link

johnark88 commented Jun 4, 2024

I am currently trying to implement this and have a few questions,

  • Is this the updated example? - https://github.com/Shopify/hydrogen/tree/main/examples/gtm Looks like some of your links above are 404ing.

  • From the comments above, its sounds like this should work on our local enviroment (localhost:3000) is that correct?

  • I just updated to 2024.4.2 and the component is still being exported as UNSTABLE_Analytics is it still Unstable or did I mess something up?

  • If I want to capture consent using the banner does Analytics.Provider require that I follow the steps on this link https://shopify.dev/docs/api/customer-privacy#installation-on-a-custom-storefront or is there a function in Analytics to capture consent and have a banner?

  • If our site is not live yet, can I use an Hydrogen staging URL for my PUBLIC_STORE_DOMAIN ?

Thank you!

@wizardlyhel
Copy link
Contributor Author

Is this the updated example? - https://github.com/Shopify/hydrogen/tree/main/examples/gtm Looks like some of your links above are 404ing.
I just updated to 2024.4.2 and the component is still being exported as UNSTABLE_Analytics is it still Unstable or did I mess something up?

We will be releasing in a day or two. That would bring the <Analytics> component stable. Official docs will be replacing the previous examples. You can access the old example from this commit

From the comments above, its sounds like this should work on our local enviroment (localhost:3000) is that correct?

The GTM example won't work exactly on localhost:3000 .. since the link to the gtm file isn't real. Once you replace that with your own, then it should work.

If I want to capture consent using the banner does Analytics.Provider require that I follow the steps on this link https://shopify.dev/docs/api/customer-privacy#installation-on-a-custom-storefront or is there a function in Analytics to capture consent and have a banner?

You don't have to follow that Shopify doc for customer privacy api integration. The <Analytics> component will handle that for you once you supply all required props.

If our site is not live yet, can I use an Hydrogen staging URL for my PUBLIC_STORE_DOMAIN ?

PUBLIC_STORE_DOMAIN is a read-only variable. You won't be able to change this variable value in Oxygen preview or in production. If you are just working locally, you can always use mock.shop like how we setup initially in the skeleton template

@wizardlyhel
Copy link
Contributor Author

Released 2024.4.3 that contains the stable <Analytics> component.

Official docs: https://shopify.dev/docs/storefronts/headless/hydrogen/analytics.

Run h2 upgrade command to bring your project to latest version.

Make sure to replace imports for Unstable_Analytics as Analytics to Analytics, otherwise, you might hit infinite loop loading when viewing app locally.

@mattrosno
Copy link

Hi @wizardlyhel - I can open an issue if I need to, but when setting customData in the provider like:

<Analytics.Provider
  cart={data.cart}
  shop={data.shop}
  consent={data.consent}
  customData={{foo: 'bar'}}
>

I'm getting undefined in the data in all subscribed events (I tested page_viewed and product_viewed so far.)

image

Any recommendations? Thanks!

@wizardlyhel
Copy link
Contributor Author

that indeed is a bug - please create an issue so we can track it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants