Events
Events are the primary way to interact with the Promotion Engine. The app publishes events when data becomes available and subscribes to a number of events that can be published by third parties.
API ready
Details
Event
la:dn:api:ready
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Signals that the script has loaded and interaction with the API is possible.
Syntax
function performActionWhenApiIsReady() {
//Add your logic here
console.log('API ready');
}
//Check if the API is ready
if (typeof discountNinja === 'undefined' ||
typeof discountNinja.api === 'undefined') {
//The API is not ready, wait for it
document.addEventListener("la:dn:api:ready", function(event) {
performActionWhenApiIsReady();
});
}
else {
//The API was already available, no need to wait
performActionWhenApiIsReady();
}
Promotions loaded
Details
Event
la:dn:promotions:loaded
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published after promotions have been loaded, processed and filtered by the app. It allows the consumer to inspect which promotions are available for the user during the browsing session.
Event properties
The event data contains a promotions object.
Syntax
document.addEventListener("la:dn:promotions:loaded", function(event) {
const promotions = event.detail.data[0];
console.log('Promotions loaded', promotions);
});
Product discount calculated
Details
Event
la:dn:product:discount:calculated
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
This event is published when the (discounted) price of any marked product on the page has been calculated.
The app will attempt to find all products on a page based on markers in the HTML. It then applies the available promotions to those products and publishes one event per product variant with the results.
For the current product, this event is published when the page is loaded and is published again when the selected variant or selected selling plan changes. For other products, this event is published only once per product and per page load.
Event properties
Syntax
document.addEventListener("la:dn:product:discount:calculated", function(event) {
const productVariantPriceInfo = event.detail.data[0];
console.log('Product variant price calculated', productVariantPriceInfo);
});
Cart updated
Details
Event
la:dn:cart:updated
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when a change to the cart has been detected and promotions have been evaluated.
This event is published when the page is loaded and is published again when the content of the cart changes or the set of applied promotions changes.
Event properties
Syntax
document.addEventListener("la:dn:cart:updated", function(event) {
const discountedCart = event.detail.data[0];
console.log('Discounted cart available', discountedCart);
});
Cart discounted
Details
Event
la:dn:cart:discounted
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when a discount has been applied to the cart.
This event is published when the page is loaded and is published again when the content of the cart changes or the set of applied promotions changes.
Event properties
Syntax
document.addEventListener("la:dn:cart:discounted", function(event) {
const discountedCart = event.detail.data[0];
console.log('Discount applied to the cart', discountedCart);
});
Cart mutations processing
Details
Event
la:dn:cart-mutations:processing
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when the store is making updates to the cart.
Syntax
// Add this HTML element to your (drawer) cart Liquid template
// It can be placed, for example, near the checkout button
<div id="cart-mutations-processing-label" style="display:none">
Processing cart changes...
</div>
// Add this code to your theme.liquid in the body
<script>
document.addEventListener("la:dn:cart-mutations:processing", function() {
console.log('Cart mutations are processing...');
// Optionally, show an HTML element
// The HTML element can be used to communicate this process to the visitor
const cartMutationsProcessingLabel = document.getElementById("cart-mutations-processing-label");
if (cartMutationsProcessingLabel) cartMutationsProcessingLabel.style.display = 'block'
});
</script>
Cart mutations processed
Details
Event
la:dn:cart-mutations:processed
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when the store has finished making updates to the cart.
Syntax
// Add this HTML element to your (drawer) cart Liquid template
// It can be placed, for example, near the checkout button
<div id="cart-mutations-processing-label" style="display:none">
Processing cart changes...
</div>
// Add this code to your theme.liquid in the body
<script>
document.addEventListener("la:dn:cart-mutations:processed", function() {
console.log('Cart mutations are processed...');
// Optionally, hide an HTML element
// The HTML element can be used to communicate this process to the visitor
const cartMutationsProcessingLabel = document.getElementById("cart-mutations-processing-label");
if (cartMutationsProcessingLabel) cartMutationsProcessingLabel.style.display = 'none';
});
</script>
Trigger checkout
Details
Event
la:dn:checkout:initiate
Direction
This event is subscribed to by the app. To publish it, use the following syntax:
Behavior
This approach is useful if you need to trigger checkout programmatically without bypassing Discount Ninja.
Syntax
/// The markup below shows a custom button for illustration purposes
/// (i.e. not a button of type="submit" with name="checkout")
/// Note: we advise against using a custom checkout button
<button name="customcheckout" onclick="handleCustomCheckout()">
Check out
</button>
/// This function should be called by a custom checkout button
/// such as the one described above
function handleCustomCheckout() {
if (canAdvanceToCheckout() === true) {
// Checks if Discount Ninja is available
if (discountNinja) {
// Check if a Discount Ninja offer is applied to the cart
discountNinja.api.checkout.isDiscounted().then(function(requiresAdvancedCheckout) {
if (requiresAdvancedCheckout === true) {
// DN needs to handle the checkout
advanceToCheckoutUsingDiscountNinja():
}
else {
handleNonDiscountNinjaCheckout();
}
});
}
else {
handleNonDiscountNinjaCheckout();
}
}
else {
//Custom logic to explain why the user cannot advance
}
}
/// This optional function returns true if the user
/// can advance to the checkout
function canAdvanceToCheckout() {
return true;
}
/// This function instructs Discount Ninja
/// to advance to the checkout and apply offers
function advanceToCheckoutUsingDiscountNinja() {
document.dispatchEvent(new CustomEvent('la:dn:checkout:initiate'));
}
/// This function should redirect the user to the checkout
/// when a checkout with Discount Ninja is not required
function handleNonDiscountNinjaCheckout() {
//Custom logic to handle checkout
}
Redirect to checkout
Discount Ninja expects users to transfer from the cart to the checkout using a checkout button or link. See this article for more information: https://support.discountninja.io/en/articles/3505661-discount-ninja-checkout-button
As a result, any code that redirects the user to the checkout using window.location
is not supported. The following example shows what such an implementation would look like:
/// The markup below shows a custom button for illustration purposes
/// (i.e. not a button of type="submit" with name="checkout")
/// Note: we advise against using a custom checkout button
<button name="customcheckout" onclick="handleCustomCheckout()">
Check out
</button>
/// This function is called by a custom checkout button
function handleCustomCheckout() {
window.location = "/checkout";
}
Redirecting a user to the checkout by setting the window.location
causes problems with Discount Ninja. Additionally, it causes other integration issues for the merchant since redirecting without submitting the form has numerous flaws:
The order note field is not submitted if it was changed during this session (and not updated using cart.js)
The locale may not be passed
The discount code present in the cart form is not passed
...
To resolve this, either use a standard checkout button (a button of type="submit" with name="checkout") or change your checkout logic as follows:
/// This function is called by a custom checkout button
function handleCustomCheckout() {
if (discountNinja) {
document.dispatchEvent(new CustomEvent('la:dn:checkout:initiate'));
}
else {
// Your fallback logic
// Note: we do not recommend redirecting to the checkout this way
// (see documentation), preferably resubmit the cart form
window.location = window.Shopify.routes.root + "checkout";
}
}
Convert money fields
Details
Event
la:dn:money:convert
Direction
This event is subscribed to by the app. To publish it, use the syntax explained in the example below.
Behavior
Most currency conversion mechanisms are supported out-of-the-box by Discount Ninja. This means there is no need to implement custom logic in most cases.
In case the currency conversion mechanism of your theme (or supporting app) is not automatically triggered, you can publish this event after the theme has updated prices to let Discount Ninja know that it should re-render prices.
Syntax
function test() {
// Custom logic that overrides prices
document.dispatchEvent(new CustomEvent('la:dn:money:convert'));
}
Collection products updated
Details
Event
la:dn:collection:updated
Direction
This event is subscribed to by the app. To publish it, use the syntax explained in the example below.
Behavior
When collection products are added, removed or updated the app must recalculate the discounted prices and render the price.
Most mechanisms used to update collections are supported out-of-the-box by Discount Ninja. This means there is no need to implement custom logic in most cases.
In case the app is not automatically detecting a situation where collection products are updated, you can publish this event after the theme has updated the products to let Discount Ninja know that it should re-render prices.
Syntax
function test() {
// Custom logic that updates collection products
document.dispatchEvent(new CustomEvent('la:dn:collection:updated'));
}
Product changed
Details
Event
la:dn:product:changed
Direction
This event is subscribed to by the app. To publish it, use the syntax explained in the example below.
Behavior
When a product page is rendered, the app calculates the discounted price for the selected variant of that product. If the same product page is re-used to render a different product (without navigating or reloading the page), this event can be used to inform Discount Ninja of that.
This event is only required in unusual cases where the same product page is used to render the product details of different products (usually variations of the same product that are not modeled as product variants).
Parameters
detail.data.product.id (number)
: the id of the product
detail.data.product.handle (string)
: the handle of the product
Syntax
function test() {
// Custom logic that informs Discount Ninja that a different
// product is rendered on the product page
const productId = 123456;
const productHandle = "my-product";
document.dispatchEvent(new CustomEvent("la:dn:product:changed", {
detail: {
data: {
product: {
id: productId,
handle: productHandle
}
}
}
}));
}
Variant changed
Details
Event
la:dn:variant:changed
Direction
This event is subscribed to by the app. To publish it, use the syntax explained in the example below.
Behavior
When a different variant is selected, the app must recalculate the discounted price and render the price.
Most mechanisms used to change variants are supported out-of-the-box by Discount Ninja. This means there is no need to implement custom logic in most cases.
In case the app is not automatically detecting a situation where the product variant is changed, you can publish this event to let Discount Ninja know that it should re-render prices.
Parameters
detail.data.variant.id (number)
: the id of the selected variant
Syntax
function test() {
// Custom logic that changes the selected variant
const variantId = 123456;
document.dispatchEvent(new CustomEvent("la:dn:variant:changed", {
detail: {
data: {
variant: {
id: variantId
}
}
}
}));
}
Drawer cart opened
Details
Event
la:dn:drawercart:opened
Direction
This event is subscribed to by the app. To publish it, use the following syntax:
Behavior
When a drawer cart is opened the app may need to render discounted prices.
In case the app is not automatically detecting a situation where the drawer cart is opened, you can publish this event to let Discount Ninja know that it should re-render the line item prices and subtotal in the drawer cart.
Syntax
function test() {
//Custom logic that opens the drawer cart
//And renders the content (including prices)
document.dispatchEvent(new CustomEvent('la:dn:drawercart:opened'));
}
Entitlements calculated
Details
Event
la:dn:entitlements:calculated
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when the (discounted) cart and the associated entitlements have been calculated.
This event is published when the page is loaded and is published again when the content of the cart changes or the set of applied promotions changes.
Event properties
Syntax
document.addEventListener("la:dn:entitlements:calculated", function(event) {
const entitlements = event.detail.data[0];
console.log('Entitlements calculated', entitlements);
});
Promotion code added
Details
Event
la:dn:promotioncode:added
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when the a promotion code is redeemed using the promotion code field.
Event properties
The event data contains:
- promotionCode
: the promotion code that is applied
- success
: a boolean indicating that the code was added successfully
- manual
: a boolean indicating if the code was added manually or by the system
Syntax
document.addEventListener("la:dn:promotioncode:added", function(event) {
const eventData = event.detail.data[0];
console.log('Promotion code added', eventData);
});
Promotion code removed
Details
Event
la:dn:promotioncode:removed
Direction
This event is published by the app. You can optionally subscribe to it.
Behavior
Published when the a promotion code is removed using the promotion code field.
Event properties
The event data contains:
- promotionCode
: the promotion code that is removed
- success
: a boolean indicating that the code was removed successfully
Syntax
document.addEventListener("la:dn:promotioncode:removed", function(event) {
const eventData = event.detail.data[0];
console.log('Promotion code removed', eventData);
})
Last updated
Was this helpful?