> For the complete documentation index, see [llms.txt](https://docs.globo.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.globo.io/pre-order/app-api/javascript-api-online-store/app-functions.md).

# App functions

## <mark style="color:$danger;">\* Calling functions correctly</mark>

To ensure the custom code always works, even if you uninstall the application, the added code will not affect the theme. <mark style="color:$danger;">This is very important!</mark>

```javascript
// Always check if the application is installed before calling the app function.
if(typeof Globo != 'undefined' && typeof Globo.Preorder != 'undefined'){
// code here
}
```

* Or you can also use try-catch blocks to wrap custom code to avoid exception errors.

```javascript
try{
// code here
} catch (error) {}
```

## 1. Re-render in product page

In some cases, the app theme does not re-render after a variant change.

<pre class="language-javascript"><code class="lang-javascript"><strong>// after variant changed 
</strong>if(typeof Globo != 'undefined' &#x26;&#x26; typeof Globo.Preorder != 'undefined'){
 Globo.Preorder.initPreorder();
}
</code></pre>

## 2. Re-render in collection page

In some cases, the app theme does not re-render after collection filtering, sort, paginate

<pre class="language-javascript"><code class="lang-javascript"><strong>// after filtering, paginate, sort 
</strong>if(typeof Globo != 'undefined' &#x26;&#x26; typeof Globo.Preorder != 'undefined'){
 Globo.Preorder.initCollection();
}
</code></pre>

* Suggest products in the footer, using this code similarly.

## 3. Helper functions

#### **1. Search product**

* `Globo.Preorder.searchProductByJson(chunkProducts = [])`&#x20;
* Example

```javascript
const chunkProducts = [
  'id:"gid://shopify/Product/123"',
  // ...,
  'handle:"puma-runner"',
]
const products = await Globo.Preorder.searchProductByJson(chunkProducts)
if(products.length > 0){
// Push data to list product & re-render on collection page
  const currentProductIds = new Set(
    Globo.Preorder.settings.products.map(product => product.id)
  );
  const newProducts = products.filter(
    product => product && !currentProductIds.has(product.id)
  );
  Globo.Preorder.settings.products.push(...newProducts);
  Globo.Preorder.initCollection();
} 
```

#### 2. Get profile product

* Required `productJson` `variantId`
* `Globo.Preorder.getResolvedProfile(productJson, variantId)`
* Example get product profile and check status product

```javascript
const profile = Globo.Preorder.getResolvedProfile(productJson, variantId);
if(!profile){
// The current product is not included any profile, or the profile status is draft.
} else if(profile && (typeof profile.isPreorder == 'undefined' || (!profile.isPreorder && (profile?.isComingSoon ?? false)))){
    // profile is coming soon add to cart
} else {
    // profile is pre-order and 
    if(!profile.isPreorder && profile.endedByCondition == 'date'){
        // Product is ended preorder by date
    } else if (!profile.isPreorder && profile.endedByCondition == 'quantity') {
        // Product is ended preorder by quantity condition
    } else if (!profile.isPreorder && profile.startCondition == 'date' ) {
        // Product is preorder and coming soon preorder
    } else if (!profile.isPreorder && (profile.startCondition == 'quantity' || profile.startCondition == 'stock')){
        // Product is preorder and coming soon preorder
    } else if (profile.isPreorder) {
        // Product is preorder
    }
} 
```

#### 3. Get payment options & discount product preorder

```javascript
const profile = Globo.Preorder.getProductProfile(productJson, variantId);
let discountPayment = profile.discountPayment;
// data format discountPayment
// {
//     "display": {
//         hidePaymentOptions: false, // [true, false]
//         showComparePrice: true // [true, false]
//     },
//     "fullPayment": {
//         "enable": true, // [true, false]
//         "discountValue": "0", // number
//         "discountType": "percentage" // ["percentage", "fixed"]
//     },
//     "partialPayment": {
//         "enable": false, // [true, false]
//         "value": "10", // number
//         "valueType": "percentage", // ["percentage", "fixed"]
//         "discountValue": "0", // number
//         "discountType": "percentage",  // ["percentage", "fixed"]
//         "remainingBalanceChargeTrigger": "EXACT_TIME", // ["MANUAL", "EXACT_TIME", "TIME_AFTER_CHECKOUT"]
//         "remainingBalanceChargeExactTime": "2026-08-30", // specific date string - set when remainingBalanceChargeTrigger == "EXACT_TIME"
//         "remainingBalanceChargeTimeAfterCheckoutType": "week", // ["day", "week", "month"] - set when remainingBalanceChargeTrigger == "TIME_AFTER_CHECKOUT"
//     },
//     "display": {
//         "hidePaymentOptions": false,
//         "showComparePrice": true
//     }
// }
```

#### 4. Get messages

* Get messages by default translate, use `Globo.Preorder.settings.translation`
* Get messages by profile, this is last text after translated by current locale

```javascript
const profile = Globo.Preorder.getResolvedProfile(productJson, variantId);
const message = profile.message;
// data message example
// {
//     "preorderText": "Pre Order",
//     "messageAboveText": "Don't miss out - Grab yours now before we sell out again!",
//     "messageBellowText": "We will fulfill the item as soon as it becomes available",
//     "naMessageText": "Not available for Pre order",
//     "comingSoonText": "Coming soon",
//     "comingSoonAddToCartText": "Coming soon",
//     "soldoutText": "Sold out",
//     "preorderLimitMessage": "Only :stock items left in stock",
//     "outOfStockMessage": "Inventory level is :stock.It is less than you are trying to purchase. Some of the items will be pre-ordered. Continue?",
//     "labelCountdownStart": "Coming soon",
//     "labelCountdownEnd": "Pre-Order ending in",
//     "labelCountdownDays": "Days",
//     "labelCountdownHours": "Hours",
//     "labelCountdownMinutes": "Minutes",
//     "labelCountdownSeconds": "Second",
//     "preorderBadge": "Pre Order",
//     "preorderLabel": "Pre-order",
//     "preorderedItemlabel": "Pre-order item",
//     "preorderContactLink": "Reach out for more information →",
//     "cartWarningTitle": "Warning: you have pre-order and in-stock in the same cart",
//     "cartWarningContent": "Shipment of your in-stock items may be delayed until your pre-order item is ready for shipping.",
//     "cartWarningCheckboxLabel": "Don't show this again",
//     "partialPaymentLabel": "Payment option",
//     "partialPaymentOptionFull": "Full Payment",
//     "partialPaymentOptionPart": "Partial Payment",
//     "preorderPrice": "PreOrder Price",
//     "partialPaymentTitle": "Prepaid amount for {{product.title}} ({{variant.title}})",
//     "cartWarningLimitMessage": "There are still :stock pre-order items that can be added to the cart",
//     "cartWarningEndLimitMessage": "The number of products that can be pre-ordered has reached the limit",
//     "cartWarningAlertMessage": "There are still :stock pre-order items that can be added to the cart. You can purchase up to :max products",
//     "bisTextButton": "Email me when available",
//     "bisTitleForm": "Email me when available",
//     "bisHeaderContent": "Register your email address below to receive an email as soon as this becomes available again",
//     "bisPlaceHolderEmail": "Enter your email",
//     "bisSubscribeTextButton": "SUBSCRIBE",
//     "bisFooterContent": "We will send you an email once the product becomes available. Your email address will not be shared with anyone else",
//     "bisSubscribeSuccess": "Your notification has been registered",
//     "bisSubscribeFail": "The email address you entered is invalid",
//     "bisSubscribeRegistered": "Your email address is registered on this product",
//     "bisSubscribeRequired": "The email address is required",
//     "bisPhoneRegistered": "Your phone is registered on this product",
//     "bisEmailAlertTitle": "Email",
//     "bisSmsAlertTitle": "SMS",
//     "partialPaymentSaveLavel": "Save",
//     "emailPlaceholderBisForm": "Enter your email",
//     "partialPaymentReleased": "You will be charged the remaining balance when the product is released on {{ released }}",
//     "unsubscribeTitle": "<b>{{ email }}</b><br>will be unsubscribe from the <b>{{ shop_name }}</b> shop listings",
//     "unsubscribeButton": "Unsubscribe",
//     "unsubscribeSuccess": "You have successfully unsubscribed. Please re-register the product to receive notification",
//     "unsubscribeProductUnsubscribed": "You have unsubscribed from this product"
// }
```

#### 5&#x20;
