# Embedding Checkout

To use Jane's embedded checkout there are two steps:

* Adding the script to embed the checkout container on the page
* Send a message with the cart information payload to the container

### Adding the script

Add this script to your HTML page. This script will create an empty container for the Jane cart/checkout pages.

You must also ensure that the "jdid" identifier used in the dm-sdk is available in the HTML before the script is loaded.

*Note: The current version of the embedded checkout is v2. You can update to the new version by updating the script URL.*

```html
<script id="jane-frame-script" src="https://api.iheartjane.com/v2/headless/embed.js"></script>
```

### Making JDID available

If you are utilizing the Jane DM SDK to enable personalization and ads, you must pass the generated JDID through to the checkout script. Any one of the following options may be used to make the JDID available to the script:

1. Use a data attribute in the script tag\
   `<script id="jane-frame-script" data-jdid="user_jdid" src="`[`https://api.iheartjane.com/v2/headless/embed.js`](https://api.iheartjane.com/v2/headless/embed.js)`"></script>`<br>
2. Create any HTML element with id “jane-jdid” and data attribute:\
   `<div id="jane-jdid" data-jdid="user_jdid"></div>` <br>
3. Create a meta tag in the head:\
   `<head><meta name="jane-jdid" content="user_jdid"></meta></head>`

### Sending the cart information

When you are ready to move to the checkout stage, you need to use the `postMessage` API to send the following payload to the iframe. With this payload, Jane will create a server-side cart and handle all cart/checkout validations.

#### Product IDs from API&#x20;

In case you are using our [API](https://docs.iheartjane.com/docs/implementing-roots/other-api-operations#menu-products) to fetch products, there is a caveat about product ids. There is a distinction between "product id" and "menu product id":&#x20;

* "product id" is the same for that product across every store&#x20;
* "menu product id" is unique to the combination of product and store

If you retrieve products by calling  `/roots/store_operations_api/v1/menu_products` , you will want to use the `id` field that is present in the `product` attribute of the `menu_product` object.

\
Example API Response:

```json
"data": {
  "menu_product": [
    { // other attributes removed for clarity
      "id": 942824,    
      "product": {
        "id": 1822, <-- This is the id you send to the cart
        
        "description": "Testing things out",
        "full_name": "Jack Herer | Spliffin",
        "image_urls": [...],
        "kind": "vape",
        "name": "Jack Herer",
        "photos": [...],
      },
      "store": {...},
      "store_notes": "Testing things out",
      "thumbnail": null,
      "type": "vape",
      "unavailable_prices": []
    },
    {...},
    {...}
  ]
}
```

If you use Algolia, you want to use the `product_id` field in the payload.

Cart payload:

```javascript
data = {
  messageType: 'buildCart',
  payload: {
    products: [
      {
        productId: 2089,
        priceId: 'eighth_ounce',
        count: 2,
      },
      {
        productId: 1,
        priceId: 'eighth_ounce',
        count: 1,
      },
    ],
    user: {
      firstName: 'John',
      lastName: 'Smith',
      birthDate: '1988-04-20',
      phone: '5551112222',
      email: 'johnsmith@gmail.com',
      externalId: '12345',
    },
    cognitoToken: undefined,
    storeId: 68,
    headlessPartnerName: 'Partner Name',
    headlessCheckoutPartnerId: '1234-asdf-5678-ghjk', // Only needed if you want cart status webhooks
    options: {
     theme: {
        themeColor: "#004f89",
        navigationColor: "#ffc03c",
        ctaTextColor: "#ffffff",
        backgroundColor: '#f3e9db',
        font: {
          fontFamily: 'Gilroy',
          url: '//db.onlinewebfonts.com/t/1dc8ecd8056a5ea7aa7de1db42b5b639.woff2',
          color: '#111C4E'
        },
        calloutBackground: '#FFC03C',
        calloutTextColor: '#111C4E',
        buttonBorderRadius: '24px',
      },
      redirectUrl: 'https://iheartjane.com/',
      disableWeightSelection: false,// setting this to true will disable changing weight selections
      disableLoadingSpinner: false,
      disableAuthFeatures: true, //setting this to false will allow users to sign in but only in the checkout iFrame
      disablePrepayment: false,
      kiosk: false // set to true to enable kiosk mode
    },
  },
}
```

#### Cart Parameters

The following table contains some of the parameters that can be passed into the payload:

| Name                      | Values                 | Description                                                                                                                                        |
| ------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| user                      | JSON                   | The user's information.                                                                                                                            |
| storeId                   | number                 | The store id                                                                                                                                       |
| payload                   | JSON                   | The list of products that should be in the cart                                                                                                    |
| cognitoToken              | String                 | This is the `jwtToken` from the `accessToken` returned when the user signs in with Cognito                                                         |
| headlessCheckoutPartnerId | UUID                   | An id that we use to identify transactions from this cart for the purpose of sending callbacks as cart status changes. We will provide this to you |
| reservationMode           | `delivery` or `pickup` | The default order type that will be selected in the embedded checkout                                                                              |
| headlessPartnerName       | String                 | The partner name                                                                                                                                   |
| options                   | JSON                   | Various cart options. See below for more information                                                                                               |
| deliveryAddress           | Address (see below)    | The delivery address (for delivery orders). If not specified, the user will need to enter it                                                       |

The following table contains some of the parameters that can be passed into the `options` object:

| Name                   | Values     | Description                                                                                                                                                                 |
| ---------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| kiosk                  | true/false | Determines whether kiosk mode is enabled                                                                                                                                    |
| disableAuthFeatures    | true/false | Setting this to false will allow users to sign in using Jane's built-in accounts                                                                                            |
| disableWeightSelection | true/false | Setting this to true will disable changing weight selections                                                                                                                |
| theme                  | JSON       | Formatting options for the embedded checkout. See above for examples                                                                                                        |
| disableGuestCheckout   | true/false | Disables guest checkout. Requires the user to be logged in (via cognitoToken)                                                                                               |
| loginUrl               | string     | The URL that a user will need to visit to login. Used in conjunction with `disableGuestCheckout` to show a login link when the user goes to the cart in a logged out state. |
| closeButtonOnCheckout  | true/false | Setting this to true will add a "X" in the corner of the checkout page, which will trigger a `"drawerClosed"`  event when clicked.                                          |

Here is the format for the `deliveryAddress` object:

```javascript
export const deliveryAddress = {
    street: '112 Pine Pl',
    street2: 'Apt 5',
    city: 'Santa Cruz',
    state_code: 'CA',
    zipcode: '95060',
    lat: '36.9743982',
    long: '-122.0316472'
}
```

### Ensure the iframe is ready

To make sure no race conditions are created between the iframe initially loading and your code sending the cart data to the iframe, we have a callback to ensure the iframe is ready:

```json
// The iFrame is ready to accept cart data (use this event to 
// ensure the iFrame has loaded before you postMessage to it):
{
  data: {
    messageType: "loadingEvent",
    payload: {
      name: "headlessAppLoaded"
    }
  }
}
```

Setting an event listener for this would look like:

```javascript
<script>
     window.addEventListener("message", receiveMessage, false);

      function receiveMessage(event) {
        var payload = event.data && event.data.payload;

        if (!payload || event.data.messageType !== 'loadingEvent') return;

        if (
          payload.name === "headlessAppLoaded"
        ) {
        // Process and Send the payload to the iframe here
        }
      }
</script>
```

To send the message:

```javascript
// ensure the iframe is properly loaded then
frame = document.getElementById('jane-menu')
frame.contentWindow.postMessage(data, '*')
```

For more information on using `postMessage`, look [here](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).

#### Checkout with a pre-existing cart

It is possible to checkout with a pre-existing [Creating a Cart](/jane-docs/implementing-roots/building-your-menu/creating-a-cart.md#managed-carts), by using `postMessage` with `messageType: "fetchCart"`. The payload to `postMessage`, assuming an existing cart with UUID `4d3ce036-bd64-415f-8574-e0a101ee2f7d`, should look like the following example:

```json
{
    "messageType": "fetchCart",
    "payload": {
        "cartUuid": "4d3ce036-bd64-415f-8574-e0a101ee2f7d",
        "cognitoToken": "some token",
        "storeId": 123,
        "headlessPartnerName": "Your Company Name",
        "options": <options object>
    }
}
```

The JSON object follows the same parameters used in [#cart-parameters](#cart-parameters "mention"). It is currently not possible to change the `reservationMode` via the fetchCart call, the cart will retain the mode used at creation time. Also the `products` key must be omitted, since the products are fetched from the cart itself.&#x20;

#### Disabling guest checkout

To disable checkouts by users who are not logged in, set `disableGuestCheckout` to `true`. You will also need to set `loginUrl`, which is the URL where users can login.&#x20;

When a user goes to the checkout page without logging in, the "checkout" button will be changed to one that redirects them to the login page.

![Screen Shot 2022-07-06 at 3 58 09 PM](https://user-images.githubusercontent.com/88342481/177650531-7a938a23-bcea-4657-b0c9-52ae8eeccd09.png)

*Note: this option will only work if you are using Cognito authentication.*

### Theming the cart

If you want to customize the cart's appearance, you can pass the following theme options within the options object:

```javascript
theme: {
    font: {
        fontFamily: 'Comic Neue Angular',
        url: 'https://fonts.cdnfonts.com/s/12408/ComicNeue-Angular-Regular.woff',
    },
    themeColor: 'pink',
    navigationColor: 'red',
    ctaTextColor: 'purple',
    backgroundColor: 'orange',
    calloutBackground: 'blue',
    calloutTextColor: 'yellow',
    buttonBorderRadius: '0px',
}
```

And the following screens indicate what will be affected by these options:

<figure><img src="/files/TJ5xm1i5faZYndAuRJrC" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/GCd1mJ7wWsVUsB6VfZmw" alt=""><figcaption></figcaption></figure>

### Client-Side event callbacks

When users interact with the cart, Jane sends `postMessage` callbacks to the parent site, which will be your web page. For example, when users add or remove items from their carts in the Jane UI, Jane sends `cartItemAdd` and `cartItemRemove` events to the parent page. You can respond to these events to keep your local cart state in sync with Jane's cart.

Here are the events Jane posts back to the parent page:

```javascript

// The Cart is created as pending and this is the way to get the uuid for the cart
{
  data: {
    messageType: "analyticsEvent",
    payload: {
      name: "cartPageLoad"
      properties: {
      cartProducts: Array { product_id, name, brand, category, kind, count },
      cartUuid: uuid,
      storeId: number
      }
    }
  }
}

// Jane sends four cart-level events: 
// cartItemAdd, cartItemChangeCount, cartItemRemoval, and checkout:
{ 
  messageType: 'analyticsEvent',  
    payload: { name : 'cartItemAdd',  
               properties: { 
                 productId: string,
                 product: { product_id, name, brand, category, kind }
               }  
             }
}

{ 
  messageType: 'analyticsEvent',  
    payload: { name : 'cartItemChangeCount',  
               properties: { 
                 productId: string,
                 count: number,
                 priceId: string,
               }  
             }
}

{ 
  messageType: 'analyticsEvent',  
    payload: { name : 'cartItemRemoval',  
               properties: { productId: string }  
             }
}

{ 
  messageType: 'analyticsEvent',  
    payload: { name : 'cartEmptied' }
}

{ 
  messageType: 'analyticsEvent',  
    payload: { name : 'checkout',  
               properties: {
                  estimatedTotal: number
                  cartId: number 
                  products: Array { product_id, name, brand, category, kind, count }
               }  
             }
}
```

### Handling HTTP errors:

If any HTTP request fails within the embedded cart, Jane will report the error through an event you can subscribe to. The error report event looks like this:&#x20;

```javascript
{
  messageType: 'HTTPRequestError',  
  payload: {
    name: 'HTTPRequestError',
    properties: {
      error: string,
      source: string
    }
  }
}
```

You can set up a listener for these errors just like you would set up a listener for the cart events:

```javascript
<script>
     window.addEventListener("message", receiveMessage, false);

      function receiveMessage(event) {
        var payload = event.data && event.data.payload;

        if (!payload || event.data.messageType !== 'loadingEvent') return;

        if (
          payload.name === "HTTPRequestError"
        ) {
        // Handle or report the error
        }
      }
</script>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.iheartjane.com/jane-docs/implementing-roots/embedding-checkout.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
