Jane Docs 1.0

Jane Roots

Jane Roots is Jane's headless eCommerce solution, allowing for fully custom frontends to be built on top of Jane's infrastructure.

What is Headless?

Headless is a fancy term. It simply means that Jane exposes data that allows you to build a custom user interface. Put another way – Jane handles the backend; you handle the frontend.
A few examples of what Jane handles on the backend:
  • Product content – Jane ensures that all product content (inventory levels, photos, descriptions, taxonomy, etc.) is accurate.
  • Recommendations – Jane's recommendation algorithm returns the most relevant complementary products for a given product.
  • Specials – Jane handles all specials logic, ensuring the optimal specials are applied to the right products.
  • Checkout requirements – Jane ensures that the user is not able to check out, e.g., when the store is closed.

Who can use Jane Roots?

Jane Roots is relevant to anyone who sells cannabis online – brands, single stores, single-state operators, multi-state operators, etc. If you can provide an eCommerce portal through which customers can make reservations for cannabis, you can build on Jane Roots.
However! There are a few prerequisites to building on Jane Roots:
  • Technical sophistication – Jane Roots is for developers. If you're not sure whether Jane Roots is appropriate for you, here are a few litmus test questions you should be able to answer without thinking too much:
    • What is the most performant way to support search and filtering?
    • What kind of infrastructure is needed to deploy a web app?
    • What are your KPIs and how will you measure them?
  • Relationship with Jane – Jane Roots is limited to Jane partners. If you're already a Jane partner (e.g. you're a dispensary using Jane's eComm solutions; you're a brand using Jane's brand embed solution), feel free to contact your partner success rep, and we'll get the conversation going. If you're not already a Jane partner, reach out!


The architecture of a frontend built on Jane Roots will contain at least the following elements:
Search + Sorting
Product Cards
Specials (e.g. BOGOs)
Product Detail Pages
Product Reviews


To build out an eCommerce experience, you'll need to get the right data. Jane exposes this data through indices, which are optimized for highly performant searching, filtering, sorting, and loading. All of the functionality you'll find on a standard Jane menu is replicable via our indices by allowing for filtering by the following attributes:
If you'd like access to a sandbox environment, please reach out to [email protected]
Depending on whether you're a brand or a dispensary (or a chain of dispensaries), you will be retrieving different sets of data.


Dispensaries have access to the following data:
  • Carts – retrieve all carts for a given user.
  • Menu Products – retrieve all product data for a given store. 
  • Recommendations – leverage Jane's recommendation algorithm to retrieve all complementary products for a given product.
  • Reviews – retrieve all verified reviews for a given product.
  • Deals and Discounts – retrieve all available discounts (e.g. cart-level, user-group, product-level, BOGOs, etc.).
  • Store Information – retrieve all data necessary to display store details (e.g. schedules, reservation slots, etc.)
  • Curbside checkout – allow users to notify stores when they've arrived at the designated curbside pickup spot.


Brands have access to the following data:
  • Carts – retrieve all carts that originated from your frontend.
  • Products – retrieve all of your brand's products within a specified radius of a given zipcode.
  • Menu Products – retrieve all product data for a given store. 
  • Recommendations – leverage Jane's recommendation algorithm to retrieve all complementary products for a given product.
  • Reviews – retrieve all verified reviews for a given product.
  • Deals and Discounts – retrieve all available discounts (e.g. cart-level, user-group, product-level, BOGOs, etc.).
  • Stores – retrieve all stores that carry a given product.
  • Curbside checkout – allow users to notify stores when they've arrived at the designated curbside pickup spot.

Plug-and-play Checkout

Jane's Cart and Checkout pages are battle-tested – they have been optimized to support a range of operational requirements, support the highest checkout conversion rate in the cannabis industry, and have facilitated over $3 billion in checkouts.
Building out your own cart and checkout pages is a lot of work. It requires ingesting, coordinating, and executing on various concerns to ensure the user checks out in accordance with the store's operational requirements. For example, you will have to account for at least the following:
  1. 1.
    Enforcing cart limits
  2. 2.
    Validating the user's delivery address
  3. 3.
    Optimizing the distribution of specials across the user's cart
  4. 4.
    CRM integrations
  5. 5.
    User group discounts
  6. 6.
    Tax calculations
  7. 7.
    Store schedules, including max orders per window
We highly recommend letting Jane handle all of this (and more) for you.


To use Jane's headless checkout, follow these steps:
Add this script to your HTML page. This script will create an empty container for the Jane cart/checkout pages.
<script id="jane-frame-script" src="https://api.iheartjane.com/v1/headless/embed.js"></script>
When you're ready to materialize the cart/checkout pages, use the browser's postMessage API to send the following payload (with the values that correspond to your store and products) to the container. With this payload, Jane will create a server-side cart and handle all cart/checkout validations.
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',
externalId: '12345',
cognitoToken: undefined,
storeId: 68,
headlessPartnerName: 'Partner Name',
headlessCheckoutPartnerId: '1234-asdf-5678-ghjk', // provided by Jane
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,
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
frame = document.getElementById('jane-menu')
frame.contentWindow.postMessage(data, '*')
To see a live example of this in action, visit https://www.leafly.com/dispensary-info/rise-silver-spring. You should see something like the following:

Client-Side Event Callbacks

When users interact with the cart, Jane sends callbacks to the parent site. For example, when users add or remove items from their carts in the Jane UI, Jane sends cartItemdAdd 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:
// 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"
// Jane sends three cart-level events:
// cartItemAdd, cartItemRemoval, and checkout:
messageType: 'analyticsEvent',
payload: { name : 'cartItemAdd',
properties: {
productId: string,
product: { product_id, name, brand, category, kind }
messageType: 'analyticsEvent',
payload: { name : 'cartItemRemoval',
properties: { productId: string }
messageType: 'analyticsEvent',
payload: { name : 'checkout',
properties: {
estimatedTotal: number
cartId: number
products: Array { product_id, name, brand, category, kind, count }
Additional information on these events can be found here: https://docs.iheartjane.com/docs/custom-analytics-scripts.


After an order is placed via Jane's Headless Checkout, you'll want to be updated when the status of the order changes (e.g. when an order is marked as "ready for pickup"). This updating is accomplished by webhooks.
Setting up webhooks requires the following steps (coordination with Jane is necessary to set up webhooks):
  1. 1.
    Stand up an endpoint to which Jane will send POST requests.
  2. 2.
    Pass in your headlessCheckoutPartnerId to the postMessage payload.
  3. 3.
    After the user checks out, the endpoint will receive POST requests with the following payload:
cart: {
amount: 41.8,
assigned_employee_id: null,
assigned_employee_name: null,
assigned_manager_id: null,
assigned_manager_name: null,
checked_out_time: '2021-06-21 21:41:28',
checkout_message: '',
customer_phone_number: '+1112223333',
customer_email_address: '[email protected]',
customer_name: 'John Smith',
created_at: '2021-06-21 21:41:20',
id: 7469,
pos_order_id: null,
promo_code: null,
queue_number: 'G19',
rating: 0,
reservation_mode: 'pickup',
reservation_start_window: '2021-06-21 22:45:00',
status: 'verification',
store_id: 68,
store_name: "Jane's Shop",
tags: {},
user_id: null,
external_user_id: '12345',
external_user_source: 'foo',
uuid: 'fed89a88-2928-4a1f-9134-45c2fd27b2ca',
products: [Array]
webhook_event: 'cart_status_updated'
The status of the reservation will be part of the webhook payload.

Sandbox Project

If you'd like to play around with this, you can do so by using the following starter project:

Ready to build on Jane Roots?

If you're ready to start building on Jane Roots, please reach out to your partner success representative, or send a message to [email protected], and we'll dig in.