# Functions

{% hint style="info" %}
The documentation below describes the API as of version 9.x of the script.&#x20;

Public properties or functions that are not in the `discountNinja.api` namespace should be considered obsolete and will be removed in the next major version release.

Using undocumented functions or objects will result in issues as custom code that relies on those functions or objects may break in the future when Discount Ninja's script is automatically updated.
{% endhint %}

## Cache

### Clear

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.cache.clear()</code></td></tr><tr><td></td><td>Clears all session and local storage data used by the script. Also clears the content of the indexedDb used by the script.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in troubleshooting sessions.</td></tr></tbody></table>

#### Syntax

```javascript
//Clear cache
if (discountNinja) await discountNinja.api.cache.clear();
```

## Cart

### Add

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.cart.add(variant: number, quantity: number, properties?: Record&#x3C;string, string>, sellingPlanId?: number)</code></td></tr><tr><td></td><td>Adds a variant to the cart. Note: this is an asynchronous function; the result must be awaited.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Parameters</strong></td><td><code>variant (number)</code>: the variant id</td></tr><tr><td></td><td><code>quantity (number)</code>: the number of items to add</td></tr><tr><td></td><td><code>properties? (Record&#x3C;string, string>)</code>: an optional object with key/value pairs of line item properties </td></tr><tr><td></td><td><code>sellingPlanId? (number)</code>: an optional selling plan (to allow for recurring purchases based on a subscription)</td></tr></tbody></table>

#### Syntax

```javascript
async function addVariantToCart() { 
    if (!discountNinja) return;
    
    const variant = 123456; //Ensure the variant id exists on the shop
    const quantity = 1;
    const properties = { "my_property": "my value", "my_property_2": "another value" };
    const sellingPlanId = 123456; //Ensure this is a valid selling plan for the variant
    
    //Add the variant
    await discountNinja.api.cart.add(variant, quantity);
    //Add the variant with a line item property
    await discountNinja.api.cart.add(variant, quantity, properties);
    //Add the variant with a selling plan
    await discountNinja.api.cart.add(variant, quantity, undefined, sellingPlanId);
}

//Run the above test
await addVariantToCart();
```

### Content

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Property</strong></td><td><code>discountNinja.api.cart.content</code></td></tr><tr><td></td><td>Can be used to get access to an object that represents the content of the cart, including any discounts applied by Shopify's backend.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Return value</strong></td><td><code>object | null</code> Returns the <a href="https://shopify.dev/docs/api/liquid/objects/cart">Shopify cart object</a>. Returns null if no cart is available.</td></tr></tbody></table>

#### Syntax

```javascript
function logShopifyCart() {
    const cart = discountNinja discountNinja.api.cart.content ? null;
    const itemCount = cart ? cart.item_count : 0;
    console.log(`There are currently ${itemCount} items in the cart`, cart);
}

logShopifyCart()
```

### Prefill

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Property</strong></td><td><code>await discountNinja.api.cart.prefill(variants?: string[], redirectUrl?: string)</code></td></tr><tr><td></td><td>Can be used to prefill a cart with specific variants.<br>Typically used to create a link to a prefilled, discounted cart. <br>Cf. <a href="https://support.discountninja.io/en/articles/5194395-how-to-build-a-prefilled-discounted-cart">https://support.discountninja.io/en/articles/5194395-how-to-build-a-prefilled-discounted-cart</a></td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td>Parameters</td><td><code>variants?: string[]</code>: a comma-separated list of the variant id of the product variants you want to add to the cart; for each variant you'll need to specify the quantity. </td></tr><tr><td></td><td>This parameter is optional. If it is omitted, the app will look for a query parameter named <code>variants</code> instead. If neither is available the prefill method will not execute.</td></tr><tr><td></td><td><code>redirectUrl?: string</code>: define which page should be loaded once the cart is prefilled</td></tr><tr><td></td><td>This parameter is optional. If it is omitted, the app will look for a query paramer named <code>redirectUrl</code> instead. If neither is available the default value is "<code>/cart</code>".</td></tr></tbody></table>

#### Syntax: example 1

This script can be used on a cart template to automatically prefill the cart based on the query parameters as explained here: [ttps://support.discountninja.io/en/articles/5194395-how-to-build-a-prefilled-discounted-cart](https://support.discountninja.io/en/articles/5194395-how-to-build-a-prefilled-discounted-cart)

```javascript
<script type="text/javascript">
    document.addEventListener("la:dn:promotions:loaded", async function() { 
	if (discountNinja) await discountNinja.api.cart.prefill();
    });
</script>
```

#### Syntax: example 2

Alternatively, create a variants array manually and then&#x20;

```javascript
async function prefillCartWithSpecificVariants() {	
    // Replace 123456 and 2345678 with valid variant ids
    // Add a quantity of 1 of the variant with id 1234567x1
    // and a quantity of 2 of the variant with id 2345678x2
    // then, redirect to the home page
    const variants = [];
    variants.push('1234567x1');
    variants.push('2345678x2');
    if (discountNinja) await discountNinja.api.cart.prefill(variants, '/');
}

await prefillCartWithSpecificVariants();
```

## Checkout

### Is discounted

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.checkout.isDiscounted()</code></td></tr><tr><td></td><td>Can be used to check if any of the promotions apply to the cart and result in a product, order or shipping discount. </td></tr><tr><td>Type</td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Return value</strong></td><td><p><code>Promise&#x3C;boolean></code> Returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a> which resolves to a <code>boolean</code>. </p><p></p><p>The return value indicates if the app will instruct Shopify to apply discounts at checkout. Additionally, when this function returns <code>true</code>, the script will attempt to take over the checkout process when the cart form is submitted using a checkout button.</p></td></tr></tbody></table>

#### Syntax

```javascript
document.addEventListener("la:dn:cart:updated", async function(event) {
    const discountedCart = event.detail.data[0]; 
    const isDiscounted = await discountNinja.api.checkout.isDiscounted();
    if (isDiscounted) {                
        console.log('The cart is discounted', discountedCart);
        // Add logic when the cart is discounted by Discount Ninja offers
    }
    else {
        console.log('The cart is not discounted', discountedCart);
        // Add logic when the cart is not discounted by Discount Ninja offers
    }
});
```

### Add pipeline rule

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.checkout.addPipelineRule()</code></td></tr><tr><td></td><td>Can be used to add custom business logic that is executed when the customer click the checkout button. </td></tr><tr><td></td><td>Discount Ninja needs to take over the checkout process when a user clicks the checkout button to ensure the checkout is correctly discounted. </td></tr><tr><td></td><td>As a result, the app overrides any logic you may have associated with clicking the checkout button. To execute this logic you can add it to the pipeline of rules that is executed by the app.</td></tr><tr><td></td><td>Each pipeline rule is a parameterless function that returns a boolean indicating if execution should continue (<code>true</code>) or not (<code>false</code>).</td></tr><tr><td>Type</td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Return value</strong></td><td><code>boolean</code> The return value indicates if the rule was added properly.</td></tr></tbody></table>

#### Syntax

```javascript
function checkoutPipelineRule1() {
    //Add your logic here
    //Return true to indicate that the customer can continue to the checkout
    //Return false to halt the pipeline
    console.log('Executing checkout pipeline rule 1');
    return true; 
}

function checkoutPipelineRule2() {
    //Add your logic here
    //Return true to indicate that the customer can continue to the checkout
    //Return false to halt the pipeline
    console.log('Executing checkout pipeline rule 2');
    return true; 
}

function registerCheckoutPipelineRules() {
    const successfullyAddedRule1 = 
        discountNinja.api.checkout.addPipelineRule(checkoutPipelineRule1);
    const successfullyAddedRule2 = 
        discountNinja.api.checkout.addPipelineRule(checkoutPipelineRule2);
    if (successfullyAddedRule1 && successfullyAddedRule2) {
        console.log('Pipeline rules successfully registered');
    }
    else {
        console.error('Pipeline rules could not be registered');
    }
}

//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) { 
        registerCheckoutPipelineRules();
    });
}
else {
    //The API was already available, no need to wait
    registerCheckoutPipelineRules();
}
```

### With

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Property</strong></td><td><code>await discountNinja.api.checkout.with(variants: string[], discountCodes?: string[])</code></td></tr><tr><td></td><td>Can be used to checkout using specific variants and one or more discount codes.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td>Parameters</td><td><code>variants?: string[]</code>: a comma-separated list of the variant id of the product variants you want to add to the cart; for each variant you'll need to specify the quantity. The variant and the quantity are separated by an x. E.g. 123456x2</td></tr><tr><td></td><td><code>discountCodes?: string[]</code>: a list of discount codes to apply to the cart</td></tr></tbody></table>

#### Example

This example shows you can use this api method to build a discounted checkout link, that can be used on any page that includes the Discount Ninja App embed.

```javascript
<a href="#" onclick='discountNinja.api.checkout.with(["19812741972097x2","19812742037633x3"],["ABCD"]); return false;'>
  Checkout with selected items
</a>
```

## Discount code

### Add

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.discountCode.add(discountCode: string)</code></td></tr><tr><td></td><td>Adds a discount code or promotion code to the Discount Ninja promotion code field programmatically.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Parameters</strong></td><td><code>discountCode (string)</code>: the discount code to add</td></tr></tbody></table>

#### Syntax

```javascript
async function addDiscountCode(discountCode) {
    if (discountNinja) await discountNinja.api.discountCode.add(discountCode);
    console.log(`Added the promotion with promotion code '${discountCode}' to the cart`);
}

await addDiscountCode('WELCOME10');
```

### Remove

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.discountCode.remove(discountCode: string)</code></td></tr><tr><td></td><td>Removes a discount code or promotion code from the Discount Ninja promotion code field programmatically.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Parameters</strong></td><td><code>discountCode (string)</code>: the discount code to remove</td></tr></tbody></table>

#### Syntax

```javascript
async function removeDiscountCode(discountCode ) {
    if (discountNinja) await discountNinja.api.discountCode.remove(discountCode);
    console.log(`Removed the promotion with promotion code '${discountCode}' from the cart`);
}

await removeDiscountCode('WELCOME10');
```

## Discounted cart

### Content

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Property</strong></td><td><code>discountNinja.api.discountedCart.content</code></td></tr><tr><td></td><td>Can be used to get access to an object that represents the content of the cart, including any discounts applied by Shopify's backend.</td></tr><tr><td>Type</td><td>Internal</td></tr><tr><td></td><td>This is an internal function or property.<br>Use it only for debugging purposes.<br>Do <em>not</em> rely on this function or property in your integration code.</td></tr><tr><td><strong>Return value</strong></td><td><code>object | null</code> Returns an object representing the current cart, with the applicable Discount Ninja offers applied. Note that amounts returned are in cents, not in dollars.</td></tr></tbody></table>

#### Syntax

```javascript
function logDiscountedCart() {
    const discountedCart = discountNinja ? discountNinja.api.discountedCart.content : null;
    console.log(`The discounted cart`, discountedCart);
}

logDiscountedCart()
```

## Entitlements

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Property</strong></td><td><code>discountNinja.api.entitlements</code></td></tr><tr><td></td><td>Lists the entitlements that apply based on the available offers. The array contains one item for each available offer. It details the prerequisites that were found in the cart, the discount amount, the target products and the entitled line items that were found in the cart.</td></tr><tr><td>Type</td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties..</td></tr><tr><td><strong>Return value</strong></td><td><code>object[] | null</code> Returns an array of <a href="../objects#entitlement-info">Entitement info</a> objects.</td></tr></tbody></table>

#### Syntax

```javascript
function logEntitlements() {
    if (discountNinja) console.log(`Entitlements`, discountNinja.api.entitlements);
}

logEntitlements()
```

## Events

### Subscribe

{% hint style="warning" %}
This function is not used to subscribe to events. Instead it is simply a helper function that prints sample code to the log console to explain how to subscribe to an event.
{% endhint %}

<table data-header-hidden><thead><tr><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.events.subscribe(eventName: string)</code></td></tr><tr><td></td><td>Provides instructions on how to subscribe to an event with a given name. <strong>Note</strong>: this function does not, itself, subscribe to the event.</td></tr><tr><td></td><td>See the list of available <a href="#events">events</a>.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

<pre class="language-javascript"><code class="lang-javascript">function printInstructionsToSubscribeToEvent(event) {
    if (discountNinja) discountNinja.api.events.subscribe(event);
}

printInstructionsToSubscribeToEvent('cart:updated')
// Prints the following message on the console:
<strong>// To subscribe to this event use the following code: 
</strong><strong>// document.addEventListener("la:dn:cart:updated", function(event) { const eventData = event.detail.data[0]; console.log('Event la:dn:cart:updated was published.', eventData); });
</strong></code></pre>

### Publish

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.events.publish(eventName: string)</code></td></tr><tr><td></td><td>Publishes an event to the PriceRuleEngine. </td></tr><tr><td></td><td>See the list of available <a href="#events">events</a>.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
function test() {
    if (discountNinja) discountNinja.api.events.publish('cart:updated');
}
```

## Help

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.help()</code></td></tr><tr><td></td><td>Prints a link to this page on the console.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
discountNinja.api.help()
```

## Line item

### Get updated key

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.lineItem.getUpdatedKey(key: string)</code></td></tr><tr><td></td><td>Returns the updated key associated with a cart line item. A key can be updated by Shopify's back-end when properties are added, a selling plan changes or a discount is added. Cf. <a href="https://support.discountninja.io/en/articles/9109023-fix-network-requests-to-cart-js">https://support.discountninja.io/en/articles/9109023-fix-network-requests-to-cart-js</a></td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Parameters</strong></td><td><code>key (string)</code>: the original key of the cart line item</td></tr><tr><td><strong>Return value</strong></td><td><code>string</code> The updated key.</td></tr></tbody></table>

#### Syntax

```javascript
function test() {
    for (let i = 0; i < cart.items.length; i++) {
        const item = cart.items[i];
        let key = item.key;
        if (discountNinja) {
            key = discountNinja.api.lineItem.getUpdatedKey(key);
        }
        
        // ... use the updated key, for example, to send requests to cart.js
    }
});
```

## Offers

### All&#x20;

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.offers.all</code></td></tr><tr><td></td><td>Lists all the active offers loaded by the app. </td></tr><tr><td><strong>Type</strong></td><td>Internal</td></tr><tr><td></td><td>This function returns an internal object.<br>Do <em>not</em> rely on the properties of this object in your integration code as they may be removed or renamed in future versions.</td></tr><tr><td><strong>Return value</strong></td><td><code>object[]</code> An array of <code>offer</code> objects, representing the offers that are applicable in the current context.</td></tr></tbody></table>

#### Syntax

```javascript
document.addEventListener("la:dn:promotions:loaded", function(event) { 
    const offers = discountNinja ? discountNinja.api.offers.all : null;
    console.log('Offers loaded', offers);
});
```

### Get

{% hint style="info" %}
This function is used to look up an offer that is available in the browser's cache. To load a promotion that is not available to the browser, use the Promotion [Trigger](#trigger) function or the Discount Code [Add](#add-1) function instead.
{% endhint %}

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.offers.get(token: string)</code></td></tr><tr><td></td><td>Finds a specific offer in the list of all the active offers loaded by the app. </td></tr><tr><td><strong>Type</strong></td><td>Internal</td></tr><tr><td></td><td>This function returns an internal object.<br>Do <em>not</em> rely on the properties of this object in your integration code as they may be removed or renamed in future versions.</td></tr><tr><td><strong>Parameters</strong></td><td><code>token (string)</code>: the token of the offer to find</td></tr><tr><td><strong>Return value</strong></td><td><code>object | null</code> An<code>offer</code> object if the offer is found, otherwise <code>null</code>.</td></tr></tbody></table>

#### Syntax

```javascript
document.addEventListener("la:dn:promotions:loaded", function(event) { 
    const offerToken = 'ABCD';
    const bfcmOffer =  discountNinja ? discountNinja.api.offers.get(offerToken) : null;
    if (bfcmOffer === null) {
        console.log(`Offer with token ${offerToken} not found`);
    }
    else {
        console.log(`Offer with token ${offerToken} found`, bfcmOffer);
    }
});
```

## Promotions

### All&#x20;

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Function</strong></td><td><code>discountNinja.api.promotions.all</code></td></tr><tr><td></td><td>Lists all the active promotions loaded by the app. </td></tr><tr><td><strong>Type</strong></td><td>Internal</td></tr><tr><td></td><td>This function returns an internal object.<br>Do <em>not</em> rely on the properties of this object in your integration code as they may be removed or renamed in future versions.</td></tr><tr><td><strong>Return value</strong></td><td><code>object[]</code> An array of <code>promotion</code> objects, representing the promotions that are applicable in the current context. The promotion object provides information about the trigger used and the list of offers associated with the promotion.</td></tr></tbody></table>

#### Syntax

```javascript
document.addEventListener("la:dn:promotions:loaded", function(event) { 
    const promotions = discountNinja ? discountNinja.api.promotions.all : null;
    console.log('Offers loaded', promotions);
});
```

### Get

{% hint style="info" %}
This function is used to look up a promotion that is available in the browser's cache. To load a promotion that is not available to the browser, use the Promotion [Trigger](#trigger) function or the Discount Code [Add](#add-1) function instead.
{% endhint %}

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Function</strong></td><td><code>discountNinja.api.promotions.get(token: string)</code></td></tr><tr><td></td><td>Finds a specific promotion in the list of all the active promotions loaded by the app. </td></tr><tr><td><strong>Type</strong></td><td>Internal</td></tr><tr><td></td><td>This function returns an internal object.<br>Do <em>not</em> rely on the properties of this object in your integration code as they may be removed or renamed in future versions.</td></tr><tr><td><strong>Parameters</strong></td><td><code>token (string)</code>: the token of the promotion to find</td></tr><tr><td><strong>Return value</strong></td><td><code>object | null</code> A <code>promotion</code> object if the promotion is found, otherwise <code>null</code>.</td></tr></tbody></table>

#### Syntax

```javascript
document.addEventListener("la:dn:promotions:loaded", function(event) { 
    const promotionToken = 'ABCD';
    const bfcmPromotion = discountNinja ? discountNinja.api.promotions.get(promotionToken) : null;
    if (bfcmPromotion === null) {
        console.log(`Promotion with token ${promotionToken} not found`);
    }
    else {
        console.log(`Promotion with token ${promotionToken} found`, bfcmPromotion);
    }
});
```

### Trigger

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.promotions.trigger(tokens: string)</code></td></tr><tr><td></td><td>Triggers a private promotion programmatically.</td></tr><tr><td></td><td>Use this as a programmatic alternative to using a discount link. To trigger a promotion based on a promotion code, use the Discount Code <a href="#add-1">Add</a> function instead.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr><tr><td><strong>Parameters</strong></td><td><code>tokens (string | string[])</code>: the token(s) of the promotion(s) to trigger</td></tr></tbody></table>

#### Syntax

```javascript
function triggerCustomPromotion() {
    const bcfmPromotionToken = 'ABCD';
    if (discountNinja) discountNinja.api.promotions.trigger(bcfmPromotionToken);
}
```

```html
<a href='javascript:triggerCustomPromotion()'>Unlock the BFCM promo!</a>
<button onclick='triggerCustomPromotion()'>Unlock the Cyber Monday offer!</button>
```

## Strikethrough Pricing

### Apply

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.strikethroughPricing.apply()</code></td></tr><tr><td></td><td>Triggers a refresh of all strikethrough pricing programmatically. This is typically not required since the app automatically detects situations where the strikethrough pricing must be updated.</td></tr><tr><td></td><td>For an event based approach, use <a href="../events#drawer-cart-opened">this event</a> instead.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
async function myPriceUpdateLogic() {
    //Trigger Discount Ninja's strikethrough pricing rendering
    if (discountNinja) await discountNinja.api.strikethroughPricing.apply();
};
```

### Before render

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><code>discountNinja.api.strikethroughPricing.setBeforeRender(async (input: Object) => string)</code></td></tr><tr><td></td><td>Discount Ninja ships with its own internal rendering function wired up as the “before render” callback. This function allows the user to override this callback with a custom callback.</td></tr><tr><td><strong>Parameters</strong></td><td><p><code>async (input: Object) => string)</code> A function that receives an input object and returns a string.<br></p><p><code>priceData: Object</code> An input object that can be used to decide if the rendered text should be updated.<br></p><p><code>string</code> The HTML that should be rendered. To render the HTML proposed by the internal rendering function, simply return input.defaultHtml</p><p></p><p>This is the shape of the <code>input</code>object:</p><pre class="language-typescript"><code class="lang-typescript">{
    offerToken: string;
    defaultHtml: string; // This is the default HTML, computed by the script
<strong>    productInfo: {
</strong>        productHandle: string;
        variantId: number;
        sellingPlanId: number | null;
        available: boolean;
        price: {
          original: number;
          compareAt: number;
          discounted: number;
        };
    };
<strong>};
</strong></code></pre></td></tr><tr><td><strong>Return value</strong></td><td></td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
function registerBeforeRenderLogic() {
    async function beforeRenderLogic(input) {          
      ... custom logic ...
      return input.defaultHtml;        
    }
    discountNinja.api.strikethroughPricing.setBeforeRender(beforeRenderLogic); 
}

//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) { 
        registerBeforeRenderLogic();
    });
}
else {
    //The API was already available, no need to wait
    registerBeforeRenderLogic();
}
```

## Widgets

### Render

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.widgets.render()</code></td></tr><tr><td></td><td>Triggers a refresh of all widgets (including strikethrough pricing) programmatically. This is typically not required since the app automatically detects situations where the widgets must be updated.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
async function myWidgetUpdateLogic() {
    //Trigger Discount Ninja's widget rendering update
    if (discountNinja) await discountNinja.api.widgets.render();
};
```

## Widgets > Promotion Code Field

### Toggle

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>Yes</td></tr><tr><td><strong>Function</strong></td><td><code>await discountNinja.api.widgets.promotionCodeField.toggle()</code></td></tr><tr><td></td><td>Expands or collapses the promotion code field widget.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
async function myFunction() {
    if (discountNinja) discountNinja.api.widgets.promotionCodeField.toggle();
};
```

### Footer Instructions

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td><strong>Async</strong></td><td>No</td></tr><tr><td><strong>Function</strong></td><td><p><code>discountNinja.api.widgets.promotionCodeField.showFooterInstructions()</code></p><p><code>discountNinja.api.widgets.promotionCodeField.hideFooterInstructions()</code></p><p><code>discountNinja.api.widgets.promotionCodeField.toggleFooterInstructions()</code></p></td></tr><tr><td></td><td>Expands or collapses the instructions section in the footer of the promotion code field.</td></tr><tr><td><strong>Type</strong></td><td>Public</td></tr><tr><td></td><td>This function is intended for use in integration code by third parties.</td></tr></tbody></table>

#### Syntax

```javascript
async function myFunction() {
    if (discountNinja) discountNinja.api.widgets.promotionCodeField.toggleFooterInstructions();
};
```
