Joy Loyalty Help Center
WebsiteDevDocsStatusBook a demo
[Old] Joy Loyalty
[Old] Joy Loyalty
  • 🚀Getting started
    • Getting started
      • How to enable Joy's app embed
      • Show Shopify customer account
      • Quick search
      • Name your points currency
    • 🌟What's New?
  • 🎁Rewards program
    • Rewards programs overview
    • Earning programs
      • Sign up
      • Place order
      • Birthday rewards
      • Customers reviews
      • Social media
      • Whatsapp
      • Pinterest
      • Fill out a survey
      • Visit website
      • Google Reviews
      • Custom Program
    • Redeeming programs
      • Discount program
      • Customize discount code prefix
      • Redeeming rewards at checkout
      • Coupon list at checkout
    • Milestone
    • Membership
      • Member exclusive deal
      • VIP Tier
        • ⭐Set up VIP Tiers
        • ⬇️Tier Assessment 🆕
        • 💎Tier Privileges
        • FAQs
    • Advanced settings
      • Point Expiration
      • Pending Points
      • Refund points
      • Discounts Combination
      • Channels for reward programs
      • Set up coupon codes for referrals
    • Rule Engine 🆕
  • 🧑‍🤝‍🧑Referrals
    • Getting started with referral campaigns
    • Referral flow explained
    • Product Referral Block
    • Managing referrals with tags
  • 🚀Migration
    • Migration to Joy Loyalty
    • Migrations from apps
      • Migration from Stamped to Joy Loyalty
      • Migration from Smile to Joy Loyalty
      • Migration from Rivo to Joy Loyalty
      • Migration from Appstle℠ Loyalty & Rewards to Joy Loyalty
      • Migration from Loyalty Lion to Joy Loyalty
      • Migration from BON Loyalty to Joy Loyalty
      • Migration from Yotpo Loyalty to Joy Loyalty
    • Migrate Tiers
  • 👨‍👩‍👧‍👦Customers' activities
    • Customers' activities
      • Customers' activities
      • Import & Export customer data
      • Customers' types and segment
      • Generate Customer QR Code
    • Email notification
      • Automated notifications
      • Custom sender for email notifications
    • Analytics
  • 🛍️Store design with Joy
    • Widget
      • Setting up a Loyalty widget that brands
      • Sign up & Referrals Widget
      • Sign up block
      • Advanced widget settings and customization
    • Deeplink
    • Account page
      • Referral block
    • Point calculator
    • Translation
      • Translate Widget Contents
      • Change Language in app
    • Customer login
    • Reward Reminder
  • 🚀Loyalty Page
    • Loyalty landing page
    • Loyalty page block
      • Hero Banner
      • “FAQs” block
      • “How it works” block
      • “Way to earn” block
      • “Way to redeem”
      • "VIP Tiers" block
      • In-line Banner
      • Redeem at checkout
      • Rewards activity block
      • Referral block
      • “Coming soon” block
      • My reward block
  • 🧩Integrations
    • Review Apps
      • Joy and Air Reviews
      • Joy and Judge.me
      • Joy and Fera Product Reviews
      • Joy and Yotpo Product Reviews
    • Email Marketing Apps
      • Joy and Klaviyo
      • Joy and PushOwl
      • Joy and Mailchimp
      • Joy and Omnisend
      • Joy and Sendlane
      • Joy and Drip
    • Subscription Apps
      • Joy and Joy Subscription
      • Shopify Subscription Integration
      • Recharge Subscription
    • Survey Apps
      • Joy and SEA Survey
    • Chat apps
      • Gorgias
  • 🌀Shopify Flow
    • Get started + Joy's Triggers 🆕
    • Integrate with Shopify flow
      • Shopify Flow: Klaviyo
      • Shopify Flow: Growave
      • Shopify Flow: Loox
      • Shopify Flow: Okendo
      • Shopify Flow: Reviews.io
      • Shopify Flow: Stamped.io
      • Shopify Flow: Tydal
      • Shopify Flow: Yotpo
  • 💸POS
    • Add Joy to Shopify POS
    • Use Joy in POS workflow
  • Knowledge Hub
    • Ultimate guide to setting up your loyalty program with Joy
  • Dev Docs
    • Magic tagging for manipulating customer balance
    • Integrate Joy Loyalty widget to Hydrogen
  • FAQs
    • Common questions
      • Remove Joy customers' meta fields
      • Features without the Checkout Extensibility upgrade
      • Exclude custom products from earning points
      • Exclude on-sales items from loyalty program redeeming
      • Exclude customers
    • ⁉️FAQs
    • 🔏Privacy policy
Powered by GitBook
On this page
  • Enable Custom Storefront Development
  • Setting up your Hydrogen store
  • Integrating Joy Widget
  • Test the widget
  • Check Content Security Policy
  • More from here

Was this helpful?

  1. Dev Docs

Integrate Joy Loyalty widget to Hydrogen

Hand-on guide on how to integrate Joy Loyalty seamlessly with Shopify Headless Commerce or Custom Storefront.

PreviousMagic tagging for manipulating customer balanceNextCommon questions

Last updated 8 months ago

Was this helpful?

If you're building with Shopify's Hydrogen and want to level up your store with a loyalty program, you've come to the right place. Joy Loyalty is a great way to keep your customers coming back, and integrating it into your Hydrogen store is easier than you might think. In this guide, I’ll walk you through the steps to get Joy Loyalty up and running in your custom storefront, so you can start rewarding your customers in no time.

Enable Custom Storefront Development

Before diving in further, you must first enable our Custom Storefront Development in Settings > General. With this enabled, Shopify Storefront API can now access the Joy Metafield data.

Setting up your Hydrogen store

If you are not on Shopify Plus plan but still want to test this out with development store first. You can update your .env file with Storefront API key from your Custom App

SESSION_SECRET="foobar"
PUBLIC_STOREFRONT_API_TOKEN="YOUR_KEY"
PUBLIC_STOREFRONT_API_VERSION="2023-04"
PUBLIC_STORE_DOMAIN="YOUR_STORE.myshopify.com"

Integrating Joy Widget

In this guide, we will use the latest Hydrogen default template, if you are using an older version of Hydrogen, we hope that you can understand the idea of the code implementing and do it accordingly. If you still have a problem, feel free to reach out to our support team, our support team will get our developer team involved to assist.

To display our Joy Loyalty program widget on the store, we will need a global variable AVADA_JOY and the avada-joy.min.js file to run on your storefront. The AVADA_JOY variable will use the value of the Joy loyalty metafield.

In the root.jsx file, you need to update the root loader, which is the loader function that runs on every page. This loader runs to request global data. Since our Joy loyalty SDK run on every pages, so we will need to use the root loader.

Here is the Graphql query for all the Joy loyalty program data at app/graphql/joy-loyalty/JoyShopDataQuery.js

export const JOY_SHOP_DATA_QUERY = `#graphql
query {
    localization {
        language {
            name
            isoCode
        }
        country {
            currency {
                isoCode
            }
            isoCode
        }
    }
    shop {
        metafield (namespace: "joy_loyalty_avada", key: "data"){
            value
        }
    }
}
`;

Then, you can update the loadCriticalData function to the below code snippet. This function will look different between different versions of Hydrogen, but the idea remains the same. Find the root loader functions, and call the storefront API to retrieve the metafield value of Joy Loyalty there along with Shop information about currency, locale, and country.

/**
 * Load data necessary for rendering content above the fold. This is the critical data
 * needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
 * @param {LoaderFunctionArgs}
 */
async function loadCriticalData({context}) {
  const {storefront} = context;

  const [header, joyApiData] = await Promise.all([
    storefront.query(HEADER_QUERY, {
      cache: storefront.CacheLong(),
      variables: {
        headerMenuHandle: 'main-menu', // Adjust to your header menu handle
      },
    }),
    storefront.query(JOY_SHOP_DATA_QUERY, {variables: {}}),
    // Add other queries here, so that they are loaded in parallel
  ]);

  const {shop, localization} = joyApiData;
  const countryCode = localization.language.isoCode;
  const currencyCode = localization.country.currency.isoCode;
  const locale = localization.language.isoCode;

  const joyData = shop.metafield ? JSON.parse(shop.metafield.value) : null;

  return {
    header,
    joyData,
    joyShopData: {
      countryCode,
      locale,
      currencyCode,
    },
  };
}
import {useEffect} from 'react';

const joySdk = `https://cdn.shopify.com/extensions/5e2b8eb3-5720-4075-8ce3-fe9c434c4cf2/0.0.0/assets/avada-joy.min.js?v=${new Date().getTime()}`;

/**
 *
 * @param joyData
 * @param joyShopData
 * @param cart
 * @param customer
 * @param publicStoreDomain
 */
export function useJoyLoyalty({
  joyData,
  joyShopData,
  cart,
  customer,
  publicStoreDomain,
}) {
  useEffect(() => {
    try {
      window.AVADA_JOY = window.AVADA_JOY || {};
      window.AVADA_JOY.customer = customer
        ? {
            ...customer,
            first_name: customer.firstName,
            last_name: customer.lastName,
            id: parseFloat(customer.id.replace('gid://shopify/Customer/', '')),
          }
        : {email: null, first_name: null, last_name: null, id: null};
      window.AVADA_JOY = {
        ...window.AVADA_JOY,
        placeOrder: {
          ...joyData.placeOrder,
        },
      };
      window.AVADA_JOY = {
        ...window.AVADA_JOY,
        tierSettings: {
          ...joyData.tierSettings,
        },
      };
      window.AVADA_JOY = {
        ...window.AVADA_JOY,
        allTiers: joyData.allTiers,
      };
      window.AVADA_JOY = {
        ...window.AVADA_JOY,
        pointCalculator: joyData.pointCalculator,
      };
      window.AVADA_JOY.account_enabled = 'true';
      window.AVADA_JOY.login_url = '/account/login';
      window.AVADA_JOY.register_url = '/account/register';
      window.AVADA_JOY.cartProducts =
        cart?.lines?.edges?.map(({node}) => node) || [];
      window.AVADA_JOY.shopId = joyData.shopId;

      window.Shopify = window.Shopify || {};
      window.Shopify.currency = window.Shopify.currency || {
        active: joyShopData?.currencyCode,
        rate: '1.0',
      };
      window.Shopify.locale = joyShopData?.locale?.toLowerCase() || null;
      window.Shopify.country = joyShopData?.countryCode || null;
      window.Shopify.shop = publicStoreDomain || null;

      loadScript({
        id: 'avada-joy-script',
        url: joySdk,
      });
    } catch (e) {
      console.log('Cannot initialize Joy Loyalty', e);
    }
  }, []);
}

/**
 *
 * @param {Object} options
 * @param {string | null} [options.id=null]
 * @param {string | null} [options.url=null]
 */
function loadScript({id = null, url = null} = {}) {
  const hasScript = document.querySelector(`#${id}`);
  if (!hasScript) {
    const script = document.createElement('script');
    script.id = id;
    script.setAttribute('src', url);
    script.async = true;
    document.body.appendChild(script);
  }
}

Once done, invoke the hook inside the root.jsx file (just pay attention to the hook call, you site content may look different).

/**
 * @param {{children?: React.ReactNode}}
 */
export function Layout({children}) {
  const nonce = useNonce();
  /** @type {RootLoader} */
  const data = useRouteLoaderData('root');
  useJoyLoyalty(data);

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        {data ? (
          <Analytics.Provider
            cart={data.cart}
            shop={data.shop}
            consent={data.consent}
          >
            <PageLayout {...data}>{children}</PageLayout>
          </Analytics.Provider>
        ) : (
          children
        )}
        <ScrollRestoration nonce={nonce} />
        <Scripts nonce={nonce} />
      </body>
    </html>
  );
}

Test the widget

After these are implemented, you will see the widget display on your custom storefront according to your settings. However, you can compare the widgets on the custom storefront and the Online Store channel to make sure both are working properly. With the widget, you can earn points, redeem points, and use coupons seamlessly on your store.

Check Content Security Policy

If you cannot see our widget running because of the Content Security Policy, you may need to go to app/entry.server.jsx to update your policy to whitelist our files and domains.

Customer accounts

There is a workaround for this. You can assign the customer data to the AVADA_JOY for testing on your store. Use this from your corresponding customer account on your store.

   window.AVADA_JOY.customer = {
        default_address: null,
        email: 'mytesting@gmail.com',
        first_name: null,
        id: 8502697394488, // your testing Shopify customer ID
        last_name: null,
      };

More from here

Our app has other features such as Joy Point Calculator, Joy Rewards Page, etc. If you want to build your own Rewards page using Hydrogen, we will have another post showing how to implement this Rewards page using our Public API and Javascript SDK. We hope that this guide provides you with the first step on how to integrate Joy Loyalty Program widget into your Headless Commerce store.

If you've already developed your Hydrogen store, you're all set! However, if you haven't started yet or are looking to test a Hydrogen store with Joy Loyalty, don't worry. You can easily set up a quick-start Hydrogen store by following this guide: .

You can find all the codes related to this guide on

Once done, create the useJoyLoyalty React hooks inside app/hooks folder with the following content. This hook will take the data from the main loader function, register the global AVADA_JOY variables, and attach more information to the global Shopify variable. The global Shopify variable will by default have the registered.

By default, the Hydrogen template will not have the enabled. You will need to enable them in the Hydrogen sales channel setting. However, if you are not on Shopify Plus or using a development store, you cannot enable this setting to test the Joy Loyalty before implementing these Customer Accounts.

Getting Started with Hydrogen
this GitHub repository.
Customer Privacy API
Customer Account API
Custom Storefront Development setting