> For the complete documentation index, see [llms.txt](https://bogos-api-integration.gitbook.io/bogos-api-integration/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bogos-api-integration.gitbook.io/bogos-api-integration/bogos-js-sdk.md).

# Integration with BOGOS JS/SDK

<details>

<summary>🔔 New Update</summary>

* [Booster](#step-7-booster)
* [Product Add-on](#step-5-upsell-offer)
* [Bundle on product page](#step-3-bundle-offer)
* [Offer Page](#step-8-offer-page)

</details>

## Integration flow

```mermaid
flowchart TD
    A[Add the bogos-core script to your page] --> B["updateCore(option)<br/>with cart / customer / locale"]
    B --> C{Which offer do you want?}
    C --> D["Gift: dispatch 'bogos:gifts' on cart change"]
    C --> E["Bundle / Mix-match / Bundle on product page:<br/>add view div + dispatch 'bogos:bundle-init'"]
    C --> F["Upsell (FBT) / Product Add-on:<br/>add view div + dispatch 'bogos:upsell-init'"]
    C --> G["Discount: add view div<br/>+ dispatch 'bogos:discount-init'"]
    C --> H["Booster: add view div<br/>+ dispatch 'bogos:progress-rerender' / 'bogos:to-widget-render'"]
    C --> J["Offer Page: add view div<br/>+ dispatch 'bogos:offer-page-init'"]
    D --> I[BOGOS renders the offer UI for you]
    E --> I
    F --> I
    G --> I
    H --> I
    J --> I
```

## 1. Requirements <a href="#requirements" id="requirements"></a>

* Install BOGOS app: [https://apps.shopify.com/freegifts](https://apps.shopify.com/freegifts?utm_source=gitbook\&utm_medium=headlessapi)
* Your store must be built using the [Storefront API](https://shopify.dev/docs/api/storefront).
* Always create a cart after applying BOGOS to ensure the [cart ID](https://shopify.dev/docs/api/storefront/latest/queries/cart#returns-Cart.fields.id) is received correctly. [*Example*](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/root.tsx#L79)
* For advanced customization in your Headless store, refer to the [BOGOS API](/bogos-api-integration/integration-steps.md) documentation.
* Please refer to BOGOS' Demo store for all features demo: [Demo store](https://demo-store-by-bogos.myshopify.com/?utm_source=Headless_docs)

{% hint style="info" %}
If you need integration in a development environment, contact BOGOS via live chat or email at ***<help@bogos.io>***
{% endhint %}

## 2. Installation <a href="#installation" id="installation"></a>

### Version source <a href="#version-source" id="version-source"></a>

```
  BOGOS_JS_SDK=https://cdn.bogos.io/bogos-app-ext/20260722-1784688973/core.min.js
```

### Step 1: Getting started <a href="#step-1-getting-started" id="step-1-getting-started"></a>

1. **Add the following script to your project:**

   ```html
   <script id="bogos-core" src={{BOGOS_JS_SDK}} defer
     data-storefront-api-token={{PUBLIC_STOREFRONT_API_TOKEN}}
     data-api-version={{PUBLIC_STOREFRONT_API_VERSION}}
     data-myshopify-domain={{MYSHOPIFY_DOMAIN}}
     data-bogos-key={{BOGOS_KEY}}
   />
   ```

   | **Property**                             | **Description**                                                                                                                            | **Example**                                        |
   | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
   | `VERSION_SOURCE: String!`                | The script URL for the current version                                                                                                     | <https://cdn.bogos.io/\\{{version\\}}/core.min.js> |
   | `PUBLIC_STOREFRONT_API_TOKEN: String!`   | [Public Storefront API token](https://shopify.dev/docs/api/storefront/latest#token-based-authentication)                                   | abcd...                                            |
   | `PUBLIC_STOREFRONT_API_VERSION: String!` | [Storefront API version](https://shopify.dev/docs/api/storefront/latest#versioning)                                                        | 2025-04                                            |
   | `MYSHOPIFY_DOMAIN: String!`              | [Myshopify domain](https://shopify.dev/docs/api/storefront/latest#endpoints-and-queries) (found in **Shopify Admin > Settings**)           | bogos.myshopify.com                                |
   | `BOGOS_KEY: String!`                     | [Key generated by the BOGOS app](https://bogos-api-integration.gitbook.io/bogos-api-integration/integration-requirements#id-4.-middleware) | bogoskey...                                        |

   > 💡 **Example Available**\
   > 👉 [root.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/root.tsx#L164)
2. **Update your project with the required BOGOS data:**

   ```javascript
   typeof window !== 'undefined' && typeof window.BOGOS_CORE !== 'undefined' &&
     window.BOGOS_CORE?.helper?.updateCore(option: BOGOSOptions)
   ```

   ```typescript
   export type BOGOSOptions = {
     cart?: Cart;
     customer?: string | Customer;
     locale?: string; https://shopify.dev/docs/api/storefront/latest#@inContext-(Language)
     country?: string; https://shopify.dev/docs/api/storefront/latest#@inContext-(Country-Code)
     currency?: {
       active: string;
       rate: number;
     };
     market?: {
       id: number;
       handle: string;
     }
   };
   ```

   Note:

   * You must provide at least one of the above properties.

   * If you provide the full Cart object, BOGOS will not fetch the cart again.

   * If only the Cart ID is provided, BOGOS will fetch the cart again.

   * The customer parameter can be either a [customer access token](https://shopify.dev/docs/api/storefront/latest/queries/customer) or [customer object](https://shopify.dev/docs/api/storefront/latest/objects/Customer)

   > 💡 **Example Available**\
   > 👉 [root.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/root.tsx#L131)\
   > 👉 [Layout.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/components/Layout.tsx#L86)\
   > 👉 [Cart.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/components/Cart.tsx#L27)

### Step 2: Gift Offer <a href="#step-2-gift-offer" id="step-2-gift-offer"></a>

1. **Trigger the gift logic whenever the cart is updated:**

   ```javascript
     typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent('bogos:gifts', { detail: cart }));
   ```

   Note:

   * cart: [Cart](https://shopify.dev/docs/api/storefront/latest/objects/Cart)

   * If you provide the full Cart, it won’t fetch again.

   * If only the Cart ID is provided, it will fetch again.

   > 💡 **Example Available**\
   > 👉 [Cart.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/components/Cart.tsx#L24)
2. **Add prepareCheckout to your checkout process to validate gift items before proceeding to checkout:**

   ```javascript
   async function {your_function_checkout} (args) {
       ...
       typeof window !== 'undefined' && typeof window.BOGOS_CORE !== 'undefined' &&
         await BOGOS_CORE?.helper?.gift?.prepareCheckout();
       ...
   }
   ```

   > 💡 **Example Available**\
   > 👉 [Cart.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/components/Cart.tsx#L135)
3. **Customize**

   **3.1. Gift Icon & Gift thumbnail**

   * On the product page Add class "fg-secomapp-product-title" where you want to display gift icon Add class "bogos-gift-thumbnail-view" where you want to display gift thumbnail

   ```javascript
   typeof window !== 'undefined' && window.BOGOS_CORE?.helper?.gift?.renderCustomizeForProduct([{ id: product_id }], { product: true });
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: { product: true, selectedVariants?: [{ product_id: product_id, id: selected_variant_id }] }
     }
   }));
   ```

   > 💡 **Example Available**\
   > 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L164)

   * For collection page Add class "fg-secomapp-collection-img" to where you want to display gift icon on product card

   ```javascript
   typeof window !== 'undefined' && window.BOGOS_CORE?.helper?.gift?.renderCustomizeForProduct([{ id: product.id }], { collection: true });
   ```

   > 💡 **Example Available**\
   > 👉 [collections.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/collections.%24handle.tsx#L97)

   **3.2. Cart message**

   Add the class "bogos-cart-message-view" to the element where you want the message displayed

   ```html
   <div class="bogos-cart-message-view"></div>
   ```

   **3.3. Gift slider**

   To embed the gift slider instead of displaying as a popup, include the following code:

   ```html
   <div id="freegifts-main-page-container"></div>
   ```

### Step 3: Bundle Offer <a href="#step-3-bundle-offer" id="step-3-bundle-offer"></a>

1. **Classic bundle**

   Add the following element to where you want to display the bundle offer.

   ```html
     <div id="bogos-bundle-view" data-product-handle={{product_handle}} data-product-id={{product_id}} data-offer-id={{offer_id}}></div>

     /* 
       product_id: number; legacy product id
       offer_id: number; BOGOS offer id
     */
   ```

   Dispatch this element to render the bundle offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:bundle-init"));
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: { 
         product?: true, 
         selectedVariants?: [{ product_id: product_id, id: selected_variant_id }] 
       }
     }
   }));
   ```

   > 💡 **Example Available**\
   > 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L164)
2. **Mix-match**

   Add the following element to where you want to display the bundle offer.

   ```html
     <div id="bogos-mix-match-view" data-product-handle={{product_handle}} data-product-id={{product_id}} data-offer-id={{offer_id}}></div>

     /* 
       product_id: number; legacy product id
       offer_id: number; BOGOS offer id
     */
   ```

   Dispatch this element to show bundle offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:bundle-init"));
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: { 
         product?: true, 
         selectedVariants?: [{ product_id: product_id, id: selected_variant_id }] 
       }
     }
   }));
   ```

   > 💡 **Example Available**\
   > 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L164)
3. **Bundle on product page**

   Displays bundle offers directly on the product detail page. This is different from the standalone [Bundle Page](#step-4-bundle-page) below.

   Add the following element to where you want to display the bundle offer on the product page.

   ```html
     <div id="bogos-bundle-product-page-view" data-offer-id={{offer_id}}></div>

     /*
       offer_id: number; BOGOS offer id — OPTIONAL.
       If omitted, BOGOS auto-matches bundles configured for the current product.
     */
   ```

   Optionally, add the child widget element to display the bundle's child widget.

   ```html
     <div id="bogos-bpp-child-widget-view" data-offer-id={{offer_id}}></div>
   ```

   Dispatch this element to render the bundle offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:bundle-init"));
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: {
         product?: true,
         selectedVariants?: [{ product_id: product_id, id: selected_variant_id }]
       }
     }
   }));
   ```

### Step 4: Bundle Page <a href="#step-4-bundle-page" id="step-4-bundle-page"></a>

Add the following element to where you want to display the bundle offer.

```html
  <div id="bogos-bundle-page-view" data-offer-id={{offer_id}}></div>

  /* offer_id: number; BOGOS offer id */
```

Dispatch this element to render the bundle offer.

```javascript
  typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:bundle-page-init"));
```

> 💡 **Example Available**\
> 👉 [bundle-page.$id.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/bundle-page.%24id.tsx#L24)

### Step 5: Upsell Offer <a href="#step-5-upsell-offer" id="step-5-upsell-offer"></a>

1. **Frequently Bought Together (FBT)**

   Add the following element to where you want to display the upsell offer

   ```html
     <div id="bogos-fbt-upsell-view" data-product-handle={{product_handle}} data-product-id={{product_id}} data-offer-id={{offer_id}}></div>

     /* 
       product_id: number; legacy product id
       offer_id: number; BOGOS offer id
     */
   ```

   Dispatch this element to render the upsell offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:upsell-init"));
   ```

   > 💡 **Example Available**\
   > 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L164)
2. **Product Add-on (PA)**

   Add the following element to where you want to display the product add-on offer

   ```html
     <div id="bogos-pa-upsell-view" data-product-handle={{product_handle}} data-product-id={{product_id}} data-offer-id={{offer_id}}></div>

     /*
       product_id: number; legacy product id
       offer_id: number; BOGOS offer id
     */
   ```

   Dispatch this element to render the product add-on offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:upsell-init"));
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: {
         product?: true,
         selectedVariants?: [{ product_id: product_id, id: selected_variant_id }]
       }
     }
   }));
   ```

   **Required:** whenever the main product is added to cart, you must dispatch `bogos-headless:product-atc` so BOGOS adds the selected add-on products alongside it. Without this event, the add-on logic will not run.

   ```javascript
   async function {your_add_to_cart_function} (args) {
       ...
       // after adding the main product to cart
       typeof document !== "undefined" &&
         document.dispatchEvent(new CustomEvent("bogos-headless:product-atc"));
       ...
   }
   ```

   Note:

   * The add-on renders in the same pass as FBT — the `bogos:fbt-render` event (see [section 3.3](#step-7-other-integration)) fires for add-on views too.

### Step 6: Discount Offer <a href="#step-6-discount-offer" id="step-6-discount-offer"></a>

1. **Volume Discount**

   Add the following element to where you want to display the discount offer

   ```html
     <div id="bogos-volume-discount-view" data-product-handle={{product_handle}} data-product-id={{product_id}} data-offer-id={{offer_id}}></div>

     /* 
       product_id: number; legacy product id
       offer_id: number; BOGOS offer id
     */
   ```

   Dispatch this element to render the discount offer

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:discount-init"));
   ```

   or

   ```javascript
   // An event is triggered for all customizations on the product page
   typeof document !== 'undefined' && document.dispatchEvent(new CustomEvent("bogos:product-change", {
     detail: {
       products: [{ id: product_id }],
       options: { 
         product?: true, 
         selectedVariants?: [{ product_id: product_id, id: selected_variant_id }] 
       }
     }
   }));
   ```

   > 💡 **Example Available**\
   > 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L164)
2. **Product Discount — override the native price**

   When a Product Discount offer is active, BOGOS hides the store's native product price and renders its own overridden price in its place.

   To make this work on your headless store, add the class **`bogos-native-price`** to the element that displays your product price. BOGOS hides any element matching that class and inserts the overridden price right before it.

   ```html
     <span class="your-price-class bogos-native-price">{{ product_price }}</span>
   ```

   Note:

   * The override is triggered by the same product-render flow — dispatch `bogos:discount-init` (or `bogos:product-change`, see above) after the product renders so BOGOS recalculates the price.
   * BOGOS injects the overridden price as a `<div class="bogos-pd-native-override">` element; style it as needed to match your theme.

### Step 7: Booster <a href="#step-7-booster" id="step-7-booster"></a>

1. **Progressing bar**

   Add the following element to where you want to display the progressing bar

   ```html
     <div class="bogos-progressing-bar-view" data-offer-id={{offer_id}}></div>

     /* 
       offer_id: number; BOGOS booster id
     */
   ```

   Dispatch this element to render the progressing bar

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:progress-rerender"));
   ```

   > 💡 **Example Available**\
   > 👉 [Cart.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/be9dcfb7ffb92e7c9108c9c223488152a98e0034/app/components/Cart.tsx#L38)
2. **Today offer**

   Add the following element to where you want to display the today offer block

   ```html
     <div class="bogos-to-block-view" data-offer-id={{offer_id}}></div>

     /* 
       offer_id: number; BOGOS booster id
     */
   ```

   Dispatch this element to render the today offer block and today offer widget

   ```javascript
     typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:to-widget-render"));
   ```

   > 💡 **Example Available**\
   > 👉 [\_index.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/be9dcfb7ffb92e7c9108c9c223488152a98e0034/app/routes/_index.tsx#L35)\
   > 👉 [Cart.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/be9dcfb7ffb92e7c9108c9c223488152a98e0034/app/components/Cart.tsx#L26)

### Step 8: Offer Page <a href="#step-8-offer-page" id="step-8-offer-page"></a>

A dedicated landing page that renders a configured booster offer.

Add the following element to where you want to display the offer page.

```html
  <div id="bogos-offer-page-view" data-offer-id={{offer_id}}></div>

  /*
    offer_id: number; BOGOS booster id — REQUIRED
  */
```

Dispatch this element to render the offer page.

```javascript
  typeof document !== "undefined" && document.dispatchEvent(new CustomEvent("bogos:offer-page-init"));
```

Note:

* `data-offer-id` is **required** — it must match a booster of type `offer_page`.
* After the page renders, BOGOS dispatches `bogos:offer-page-render` with `detail: { booster }`, which you can listen to for re-rendering your layout:

```typescript
document.addEventListener("bogos:offer-page-render", (e) => {
    console.log((e as CustomEvent).detail); // { booster }
});
```

## 3. Other integrations <a href="#step-7-other-integration" id="step-7-other-integration"></a>

### 3. 1. Hide gift product (cloned product)

* If you use [products](https://shopify.dev/docs/api/storefront/lastes/queries/products) query, you should add : `query: "tag_not:bogos-gift"`

```graphql
products (
    ...,
    query: "tag_not:bogos-gift"
) {
...
}
```

* For collection and product page, you can import **`checkItemIsGift`** and use returned value to skip gift products or replace to other pages

```typescript
export type ProductObject = {
    handle: string;
    tags: string[];
    variant_id: number;
};

/* item can be product handle */
checkItemIsGift: (item: string | ProductObject) => boolean;
```

> 💡 **Example Available**\
> 👉 [collections.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/collections.%24handle.tsx#L107)\
> 👉 [products.$handle.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/routes/products.%24handle.tsx#L193)

### 3.2. Customize gift popup/slider

* Hide all default gift slider elements, and override with your custom implementation.

```css
  #freegifts-main-popup-container, #freegifts-main-page-container {
    display: none !important;
  }
```

```typescript
type GiftItem = {
    id: number;
    discount_type: 'percentage' | 'fixed_amount';
    discount_value: number;
    original_price: number;  // Original price - price before discount
    price: number;           // Discount price - price after discount
    title: string;
    thumbnail?: string;
};

type GiftProduct = {
    id: number;
    title: string;
    handle: string;
    thumbnail?: string;
    belongs_to_offer: string;
    variants: GiftItem[];
};

document.addEventListener("fg-gifts:show-slider", (e) => {
    console.log((e as CustomEvent).detail);
    /* render gift slider with detail {
        addGiftToCartFunc: (variant_id: number, quantity: number, offer_id: number) => {};
        gifts?: GiftProduct[]; // show all gifts
        giftsOffer?: { // show gifts by offer
          arrGiftShow: GiftProduct[];
        }
    } */
});

```

### 3.3. Details of additional event listeners

* `fg-gifts:updated`: Event gift is updated in cart

```typescript
document.addEventListener("fg-gifts:updated", (e) => {
    /* use this function to re-render cart */
    console.log((e as CustomEvent).detail);
});
```

> 💡 **Example Available**\
> 👉 [Layout.tsx](https://github.com/krycek-fengdx/bogos-headless-js/blob/f17a2faab77baa85413af3fa3ad36bf28019d97a/app/components/Layout.tsx#L61)

* `fg-cart:auto-updated`: Event gift auto add

```typescript
document.addEventListener("fg-cart:auto-updated", (e) => {
    console.log((e as CustomEvent).detail);
});
```

* `fg-gifts:added`: Fired when a gift is added from the slider. This event will not fire if you customize the gift popup/slider (see section 3.2 above).

```typescript
document.addEventListener("fg-gifts:added", (e) => {
    console.log((e as CustomEvent).detail);
});
```

* `fg-gifts:gift-icon`: Show gift icons
* `bogos:message`: Show cart message

## 4. Note <a href="#notice" id="notice"></a>

{% hint style="info" %}
For deeper customization, please contact our support team via live chat or email - <help@bogos.io>
{% endhint %}

### 4.1. Publish Gift/Cloned Products <a href="#publish-giftcloned-products" id="publish-giftcloned-products"></a>

* After creating or editing an offer, ensure that the gift/cloned product is published to your Headless channel (or any channel where you want BOGOS to run).

### 4.2. Some features are not yet available in this version

* Draft-Order API
* Market
* Bundle page button block
* Some Shopify object-based params (if only id provided, BOGOS will fetch the rest).
