> ## Documentation Index
> Fetch the complete documentation index at: https://developers.appstle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript events for Appstle Loyalty on Shopify themes

> The AppstleLoyalty:AppliedDiscountCode event that Appstle Loyalty fires on a Shopify theme when a customer applies a reward from a loyalty widget: what it carries, when it fires and when it doesn't, the merchant settings that affect it, and how to refresh a custom cart from it.

On a Shopify theme, the Appstle Loyalty app embed fires one JavaScript event: `AppstleLoyalty:AppliedDiscountCode`. It tells your theme code that a loyalty widget has just put a customer's reward code on their cart. Use it to refresh a custom cart or cart drawer, to show the discount in your own design, or to send an analytics event.

The event exists only on a Shopify theme where the **Appstle Loyalty** app embed is on, and only for actions the customer takes in the Appstle widgets. If you build your own loyalty UI with the [Storefront API](https://developers.appstle.com/loyalty/build-your-own-frontend.md), or run a headless storefront, nothing fires the event: update your own UI when your own calls return.

> [!WARNING]
>
> **Build on this event, not on the widgets' markup.** The HTML structure, CSS class names and element IDs of the loyalty widgets aren't part of this interface. They can change whenever a widget's design is updated, so code that selects widget elements can stop working after an update. For changes to the event, see the [API changelog](https://developers.appstle.com/loyalty/api-changelog.md).

## The event

| | |
| - | - |
| Name | `AppstleLoyalty:AppliedDiscountCode` |
| Type | `CustomEvent` |
| Dispatched on | `document` and `window`, one event each |
| Bubbles | No |

`event.detail` is an object with three fields:

| Field | Type | Description |
| - | - | - |
| `discountCode` | string | The reward's discount code, as it was sent to the cart. |
| `description` | string | The reward's description, for example `$5.00 off`. |
| `customerId` | number | The numeric Shopify customer ID of the signed-in customer, for example `7123456789012`. |

The embed dispatches one event on `document` and another on `window`, so a listener on both runs twice for one apply. Listen on one of them.

```javascript theme={null}
document.addEventListener(
  'AppstleLoyalty:AppliedDiscountCode',
  (event) => {
    const { discountCode, description, customerId } = event.detail;
    console.log(discountCode, description, customerId);
  }
);
```

You can add the listener at any time, because the event fires only after a customer acts. Add it early, for example in a script with `defer`, so it's in place before the customer opens the widget.

## When it fires

The event fires when a customer applies one of their loyalty rewards from an Appstle widget, and both of these are true:

* The embed's request to the store's discount link, `/discount/{discountCode}`, succeeds. That request puts the code on the customer's cart.
* The code is one of the customer's rewards that the page had when it loaded. A reward the customer redeems after the page loads isn't one of them until the next page load.

On the demo store, clicking **Apply Code** in the popup fired the event once on `document` and once on `window`, with this `detail`:

```json theme={null}
{
  "discountCode": "AL_EXAMPLE12345",
  "description": "$5.00 off",
  "customerId": 7123456789012
}
```

In the popup and on the loyalty page, these actions apply a code:

* The **Apply Code** button in a reward's detail view. The merchant can change its label.
* The **Add to cart** button of a free product reward. The widget adds the product to the cart while the code is being applied, so the event can fire before the product is in the cart.
* On the **Legacy** design of the loyalty page, a click on a code in the customer's list of rewards.

The copy icon next to the code in a reward's detail view only copies the code: it never fires the event or touches the cart.

### When it doesn't fire

| Situation | Why |
| - | - |
| **Add the code to the cart after redeeming** puts a newly redeemed code on the cart | That setting adds the code a different way, and that path sends no event. |
| A customer applies a reward in the popup or on the loyalty page while **Add the code to the cart when copied** is off | The widget only copies the code. |
| A customer applies a reward they redeemed after the page loaded | The code goes on the cart, but the reward isn't in the list the page loaded. After the next page load, applying it fires the event. |
| The code isn't one of the customer's loyalty rewards, for example a membership discount the widget shows | The embed still requests the discount link, but sends no event. |
| The page is a headless storefront, or your own front end built on the Storefront API | The Appstle widget and its scripts aren't running. |

## Merchant settings that affect the event

Four settings in the Loyalty app, under **Design** > **Behavior**, change whether the event fires and how long your listener has before the page unloads.

* **Add the code to the cart when copied**, in **Codes and cart**, on by default. When it's on, applying a reward in the popup or on the loyalty page puts the code on the customer's cart, and the event fires. When it's off, those actions only copy the code.
* **Add the code to the cart after redeeming**, in **Codes and cart**, off by default. When it's on, the widget puts a newly redeemed discount code on the customer's cart and reloads the page once the code is there. No event fires. Store credit rewards aren't affected.
* **Reload after adding a free product**, in **Codes and cart**, off by default. When it's on, the page reloads one second after a customer applies a free product reward or adds it to the cart. The reload can come before the event.
* **Page to open after copying a code**, in **Links**, empty by default. When it's set, that page opens two seconds after a customer applies a code.

When the page reloads or opens another page soon after the event, work your listener starts asynchronously can be cut off. Keep the listener short, and rely on the cart after the next page load.

## Example: refresh a custom cart

The embed sends the code to Shopify, but it doesn't redraw your cart. Read the cart again when the event fires, and check whether the code applies to what's in it:

```javascript theme={null}
document.addEventListener(
  'AppstleLoyalty:AppliedDiscountCode',
  async (event) => {
    const { discountCode, description } = event.detail;

    const response = await fetch('/cart.js');
    const cart = await response.json();

    const entry = cart.discount_codes.find(
      (item) => item.code.toLowerCase() === discountCode.toLowerCase()
    );

    renderCartDiscount({
      code: discountCode,
      label: description,
      applies: Boolean(entry && entry.applicable),
    });
  }
);
```

`renderCartDiscount` stands for your own function that updates the cart. Shopify lists the code in `discount_codes` as soon as the discount link succeeds, even when the cart is empty or the code doesn't apply to its items. On the demo store, an empty cart listed the code with `"applicable": false`. Check `applicable` before you tell the customer a discount is in place.

## Further reading

> [card] [Build your own frontend](https://developers.appstle.com/loyalty/build-your-own-frontend.md)
>
> Show points and rewards in your own design with the Storefront API.

> [card] [Metafields and tags](https://developers.appstle.com/loyalty/metafields-and-tags.md)
>
> The rules, settings and customer data the app publishes to your theme.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.