HomeDevelopers

Developer Docs

Feed, transactional APIs & widget embed

Connect ChatAxon to any e-commerce platform — product catalog sync, add-to-cart, discount codes, order tracking, and the chat widget embed.

Overview

Start here

ChatAxon supports full feature parity across all e-commerce platforms — not just WooCommerce. The integration is split into two layers:

Product Catalog

Feed URL or webhook — point ChatAxon at your product catalog. Supports Google Merchant XML, Shopify JSON, or a custom endpoint.

Transactional

Add to cart, apply discounts, and track orders — via JavaScript hooks (client-side) and a server endpoint you expose.

FeatureWooCommerceOther platforms
Product search & AI chat✅ Auto✅ Feed sync
Add to cart✅ Native✅ JS Hook
Apply discount code✅ Native✅ JS Hook
Order tracking (WIMO)✅ Native✅ Server endpoint
Real-time stock updates✅ Webhook✅ Webhook
WooCommerce users don't need this guide — install the WordPress plugin for a fully automatic native integration.

Feed URL Setup

Dashboard

In the ChatAxon dashboard, open Store Settings → Product Feed Integration and paste your feed URL. Select a format or leave it on Auto-detect.

1

Paste your feed URL

Accepts any publicly accessible URL. The feed must return XML or JSON. No authentication on the feed URL is supported yet.

2

Click "Test Feed"

We fetch the first 5 products and show them in a preview table. Confirm the format is correct.

3

Click "Sync Now"

A background job fetches all products, generates AI embeddings, and indexes them. Large catalogs may take a few minutes.

4

Embed the widget

Copy your chataxon_ API key and follow the instructions below.

Google Merchant Center XML

Recommended

The most widely supported format. If you already run Google Shopping ads, you already have this feed. Both RSS 2.0 (<rss><channel><item>) and Atom (<feed><entry>) are supported.

Platforms with built-in export

  • PrestaShop — built-in Google Shopping module
  • Magento / Adobe Commerce — native data feed
  • Wix eCommerce — Marketing → Google Shopping
  • BigCommerce — Channel Manager → Google Shopping
  • WooCommerce — plugins: Product Feed PRO, WOOSEA

Minimal example

xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <title>My Store</title>
    <item>
      <g:id>SKU-001</g:id>
      <g:title>Nike Air Max 90</g:title>
      <g:description>Classic everyday sneaker.</g:description>
      <g:price>129.99 USD</g:price>
      <g:image_link>https://mystore.com/img/nike.jpg</g:image_link>
      <g:link>https://mystore.com/products/nike-air-max-90</g:link>
      <g:product_type>Sneakers</g:product_type>
      <g:availability>in stock</g:availability>
    </item>
  </channel>
</rss>

Recognized fields

FieldRequiredDescription
g:idrequiredUnique product identifier
g:titlerequiredProduct name shown in chat
g:descriptionoptionalLong text used for AI search
g:priceoptionalNumeric price with currency code (e.g. 29.99 USD)
g:image_linkoptionalPrimary product image URL
g:linkoptionalProduct page URL
g:product_typeoptionalCategory label
g:availabilityoptional"in stock" or "out of stock"

ChatAxon JSON

For custom platforms

The simplest option if your developer is building a custom endpoint. Serve a JSON response at any URL — we handle the rest.

The endpoint must be publicly accessible (no auth). Serve it over HTTPS. Recommended Content-Type: application/json.

Format

json
{
  "products": [
    {
      "id": "123",
      "name": "Nike Air Max 90",
      "description": "Classic everyday sneaker, available in 5 colors.",
      "price": 129.99,
      "image": "https://mystore.com/img/nike.jpg",
      "url": "https://mystore.com/products/nike-air-max-90",
      "category": "Sneakers",
      "in_stock": true,
      "variant_id": "123-42"
    }
  ]
}
FieldRequiredDescription
idrequiredUnique product identifier (string or number)
namerequiredProduct name
descriptionoptionalProduct description (HTML stripped automatically)
priceoptionalNumeric price (no currency symbol)
imageoptionalPrimary image URL
urloptionalProduct page URL
categoryoptionalCategory string
in_stockoptionalBoolean or "in stock" / "out of stock"
variant_idoptionalVariant identifier passed to addToCart hook (size, color, etc.)
javascript
// GET /chataxon-feed.json
app.get('/chataxon-feed.json', async (req, res) => {
  const products = await db.query(
    'SELECT id, name, description, price, image_url, slug FROM products WHERE active = 1'
  );
  res.json({
    products: products.map(p => ({
      id:          String(p.id),
      name:        p.name,
      description: p.description,
      price:       parseFloat(p.price),
      image:       p.image_url,
      url:         `https://mystore.com/products/${p.slug}`,
      in_stock:    true,
    }))
  });
});

Shopify — Product Feed

Zero config

Every Shopify store exposes a public /products.json endpoint. No plugin or app install required.

1

Enter your store URL

Paste https://your-store.myshopify.com — or your custom domain — into the Feed URL field. Select Auto-detect or Shopify.

2

That's it

ChatAxon automatically calls /products.json?limit=250&page=N, paginates through all pages (up to 5 000 products), and indexes everything including variant IDs.

Shopify's /products.json is public by default. If you have a password-protected store (development mode), the endpoint will return 401 and the sync will fail.

For add-to-cart, discounts, and order tracking on Shopify, see

Cart Integration

JS Hooks

The ChatAxon widget can add products directly to the cart on any platform by calling a JavaScript function you register on the page. If the hook is not registered, the widget falls back to showing a View Product button.

Register window.ChatAxonHooks before the ChatAxon widget script executes, or pass hooks inline via window.ChatAxonConfig.hooks.

Hook interface

typescript
window.ChatAxonHooks = {
  /**
   * Add a product to the cart.
   * productId  — your product ID from the feed
   * variantId  — variant ID if applicable (size, color…); undefined for simple products
   * quantity   — always ≥ 1
   * name       — product name (for optimistic UI feedback)
   */
  addToCart: async ({ productId, variantId, quantity, name }) => {
    // Your implementation here
    return {
      success:   true,        // required
      cartCount: 3,           // optional — total items in cart after add
      cartTotal: 259.97,      // optional — new cart total
      message:   'Added!',   // optional — shown briefly in the widget
    };
    // On failure:
    // return { success: false, message: 'Item is out of stock' };
  },

  // Optional: remove a line item by its cart ID.
  // NOTE: the AI does NOT trigger removeFromCart — this hook is only called
  // if your own widget UI exposes a remove button inside the chat window.
  removeFromCart: async ({ lineItemId }) => ({ success: true }),

  // Optional: return current cart so the widget shows an item count badge
  getCart: async () => ({
    count: 2,
    total: 129.98,
    items: [{ id: '123', name: 'Nike Air Max', quantity: 1, price: 129.99 }],
  }),
};

Implementation examples

javascript
// Use when your store has a custom /api/cart/add endpoint
window.ChatAxonHooks = {
  addToCart: async ({ productId, variantId, quantity }) => {
    const res = await fetch('/api/cart/add', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ product_id: productId, variant_id: variantId, qty: quantity }),
    });
    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      return { success: false, message: err.message || 'Could not add to cart' };
    }
    const data = await res.json();
    return { success: true, cartCount: data.cart_count, cartTotal: data.cart_total };
  },
};

Inline via ChatAxonConfig

html
<script>
  window.ChatAxonConfig = {
    apiKey: 'chataxon_YOUR_API_KEY',
    apiUrl: 'https://api.chataxon.com',
    hooks: {
      addToCart: async ({ productId, quantity }) => {
        // your implementation
        return { success: true };
      },
    },
  };
</script>
The variantId passed to addToCart comes directly from your product feed. Include variant_id in your feed records if your store sells products with variants (size, color, etc.). For simple products variantId will be undefined.

Discount Codes

JS Hooks
WooCommerce only — currently. The automatic [COUPON:CODE] discount mechanism requires WooCommerce API keys to be configured. The AI fetches active coupons live from your WooCommerce admin (/wp-json/wc/v3/coupons) and only offers codes it finds there. For custom e-shops using the feed + JS API, the applyDiscount hook interface is available but the AI will not proactively offer codes — there is no mechanism to configure coupon lists for non-WooCommerce stores yet.

When the AI decides to offer a discount (WooCommerce stores only), it embeds a special tag in its response: [COUPON:CODE] (e.g. [COUPON:SUMMER20]). The ChatAxon widget intercepts this tag, hides it from the chat UI, and calls ChatAxonHooks.applyDiscount({ code: 'SUMMER20' }). You decide how the code is applied — pass it to your cart API, validate it server-side, or use a platform-native redirect.

WooCommerce: Coupons are read directly from your WooCommerce admin (WooCommerce → Marketing → Coupons). Enable coupon offering in ChatAxon → Settings → Offer coupons on exit intent. The AI only offers codes that exist in WooCommerce — it does not invent codes.

Hook interface

typescript
window.ChatAxonHooks = {
  applyDiscount: async ({ code }) => {
    return {
      success:         true,              // required
      message:         '10% off applied!', // required — shown in chat
      discountAmount:  12.99,             // optional — absolute value
      discountPercent: 10,                // optional — percentage
    };
    // On failure:
    // return { success: false, message: 'Code expired or invalid' };
  },
};
javascript
// Frontend: call your own validation endpoint
window.ChatAxonHooks = {
  applyDiscount: async ({ code }) => {
    const res = await fetch('/api/coupon/apply', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ code }),
    });
    return res.json(); // Must match the interface above
  },
};

Order Tracking API

Server-side endpoint

When a customer asks “Where is my order?” or “What's the status of order #1234?”, the ChatAxon AI calls an order lookup endpoint on your server. You implement this endpoint — ChatAxon sends the request, formats the result into natural language, and delivers it in chat.

1

Add your Order Lookup URL in the dashboard

Go to Dashboard → Store Settings → Order Tracking and paste your endpoint URL, e.g. https://mystore.com/chataxon/orders.

2

Implement the endpoint on your server

Accept a GET request with email and/or order_id query params. Verify the X-ChatAxon-Secret header. Return the order as JSON.

3

Test it

Use the “Test” button in the dashboard to send a sample request and verify your response.

Request — what ChatAxon sends to your server

http
GET https://your-store.com/chataxon/orders?email=customer@email.com&order_id=12345

Headers:
  X-ChatAxon-Secret: <your_webhook_secret>   # same value as GET /api/store/feed/webhook-secret
  Accept:            application/json
FieldRequiredDescription
emailoptionalCustomer email (present when known from the conversation)
order_idoptionalOrder ID or reference number (present when provided by the customer)
At least one of email or order_id will always be present. Handle all three cases: lookup by email only (return latest order), by order_id only, and by both together.

Response — order found

json
{
  "found": true,
  "order": {
    "id":                 "12345",
    "status":             "shipped",
    "status_label":       "Shipped",
    "date":               "2026-06-08T14:30:00Z",
    "total":              129.99,
    "currency":           "USD",
    "items": [
      { "name": "Nike Air Max 90", "quantity": 1, "price": 129.99 }
    ],
    "tracking_number":    "1Z999AA10123456784",
    "tracking_url":       "https://www.ups.com/track?tracknum=1Z999AA10123456784",
    "estimated_delivery": "2026-06-15",
    "shipping_address": {
      "city":    "New York",
      "country": "US"
    },
    "notes": "Left at front door"
  }
}

Response — order not found

json
{ "found": false, "message": "No order found for this email / ID combination." }
FieldRequiredDescription
foundrequiredBoolean — whether an order was found
order.idrequiredOrder identifier shown to the customer
order.statusrequiredMachine-readable: pending | processing | shipped | delivered | cancelled | refunded
order.status_labeloptionalHuman-readable label in the store's language
order.dateoptionalISO 8601 order date
order.totaloptionalOrder total (numeric)
order.currencyoptionalISO 4217 currency code (USD, EUR, GBP…)
order.itemsoptionalArray of line items — name, quantity, price
order.tracking_numberoptionalCarrier tracking number
order.tracking_urloptionalCarrier tracking page URL
order.estimated_deliveryoptionalISO 8601 estimated delivery date
order.shipping_addressoptionalPartial address — city + country is enough
order.notesoptionalAny extra note to surface to the customer

Always verify the secret

ChatAxon sends an X-ChatAxon-Secret header with every order lookup request. It contains the same webhook secret value returned by GET /api/store/feed/webhook-secret (also visible in Dashboard → Store Settings → Product Feed Integration). Store it as CHATAXON_WEBHOOK_SECRETin your environment and reject any request where the header doesn't match.

Implementation examples

javascript
// GET /chataxon/orders
app.get('/chataxon/orders', async (req, res) => {
  // 1. Verify secret
  if (req.headers['x-chataxon-secret'] !== process.env.CHATAXON_WEBHOOK_SECRET) {
    return res.status(401).json({ found: false, message: 'Unauthorized' });
  }

  const { email, order_id } = req.query;

  // 2. Query your DB
  const order = await db.orders.findOne({
    where: {
      ...(order_id && { id: order_id }),
      ...(email    && { customer_email: email }),
    },
    include: ['items', 'shipment'],
    order:   [['created_at', 'DESC']],
  });

  if (!order) return res.json({ found: false, message: 'No order found.' });

  const shipment = order.shipment;

  res.json({
    found: true,
    order: {
      id:                 String(order.id),
      status:             order.status,
      status_label:       order.status_label,
      date:               order.created_at.toISOString(),
      total:              parseFloat(order.total),
      currency:           order.currency,
      items:              order.items.map(i => ({
        name:     i.product_name,
        quantity: i.qty,
        price:    parseFloat(i.unit_price),
      })),
      tracking_number:    shipment?.tracking_number ?? null,
      tracking_url:       shipment?.tracking_url ?? null,
      estimated_delivery: shipment?.estimated_delivery ?? null,
      shipping_address:   { city: order.shipping_city, country: order.shipping_country },
    },
  });
});

Shopify: Cart & Orders

Native API

Since the ChatAxon widget loads on the same domain as your Shopify store, it can call Shopify's first-party Ajax Cart API directly — no app install or admin token needed for cart operations.

Add to cart — Shopify Ajax Cart API

Paste this snippet in your Shopify theme (theme.liquid) before the ChatAxon widget script.

javascript
window.ChatAxonHooks = {
  addToCart: async ({ variantId, quantity }) => {
    // variantId = Shopify numeric variant ID (auto-extracted from /products.json feed)
    const res = await fetch('/cart/add.js', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ id: Number(variantId), quantity }),
    });

    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      return { success: false, message: err.description || 'Could not add to cart' };
    }

    // Fetch updated cart totals
    const cart = await fetch('/cart.js').then(r => r.json());
    return {
      success:   true,
      cartCount: cart.item_count,
      cartTotal: cart.total_price / 100, // Shopify stores prices in cents
    };
  },

  getCart: async () => {
    const cart = await fetch('/cart.js').then(r => r.json());
    return {
      count: cart.item_count,
      total: cart.total_price / 100,
      items: cart.items.map(i => ({
        id:       String(i.variant_id),
        name:     i.title,
        quantity: i.quantity,
        price:    i.final_price / 100,
      })),
    };
  },
};

Discount codes — two approaches

Shopify does not expose a same-domain AJAX endpoint to apply discount codes to a cart. The standard workaround is a redirect to /discount/{code} which sets the code via a cookie for checkout.

javascript
// Simple and reliable. Shopify stores the discount code in a cookie.
// It will automatically apply at checkout.
window.ChatAxonHooks = {
  // ...addToCart above...
  applyDiscount: async ({ code }) => {
    window.location.href =
      `/discount/${encodeURIComponent(code)}?redirect=${encodeURIComponent(window.location.pathname)}`;
    // Return success optimistically — the redirect confirms the code
    return { success: true, message: `Applying code ${code}…` };
  },
};

Order tracking on Shopify

A — Order status page link

No server-side code. The AI links customers to Shopify's native order status page. Customer must be logged in or have the order confirmation URL.

Zero setup

B — Admin API proxy endpoint

A server function queries the Shopify Admin API and exposes a /chataxon/orders endpoint for ChatAxon to call. Full order data in chat, no customer login required.

Recommended

Option B — Shopify Admin API proxy (Node.js / Vercel Function)

javascript
// /api/chataxon-orders.js  (Vercel, Netlify, or any Node server)
// Register this URL in Dashboard → Store Settings → Order Tracking

export default async function handler(req, res) {
  // 1. Verify ChatAxon secret
  if (req.headers['x-chataxon-secret'] !== process.env.CHATAXON_WEBHOOK_SECRET) {
    return res.status(401).json({ found: false });
  }

  const { email, order_id } = req.query;

  // 2. Query Shopify Admin API (REST)
  const query = order_id
    ? `name=%23${order_id}`             // search by order name e.g. #1234
    : `email=${encodeURIComponent(email)}&status=any&limit=1`;

  const sfRes = await fetch(
    `https://${process.env.SHOPIFY_SHOP_DOMAIN}/admin/api/2024-01/orders.json?${query}`,
    {
      headers: {
        'X-Shopify-Access-Token': process.env.SHOPIFY_ADMIN_TOKEN,
        'Content-Type': 'application/json',
      },
    }
  );

  const { orders } = await sfRes.json();
  const order = orders?.[0];

  if (!order) return res.json({ found: false, message: 'No order found.' });

  const fulfillment = order.fulfillments?.[0];

  return res.json({
    found: true,
    order: {
      id:                 String(order.order_number),
      status:             order.fulfillment_status ?? order.financial_status ?? 'pending',
      status_label:       (order.fulfillment_status ?? order.financial_status ?? 'pending')
                            .replace(/_/g, ' '),
      date:               order.created_at,
      total:              parseFloat(order.total_price),
      currency:           order.currency,
      items:              order.line_items.map(i => ({
        name:     i.name,
        quantity: i.quantity,
        price:    parseFloat(i.price),
      })),
      tracking_number:    fulfillment?.tracking_number ?? null,
      tracking_url:       fulfillment?.tracking_url ?? null,
      estimated_delivery: null,
      shipping_address: {
        city:    order.shipping_address?.city,
        country: order.shipping_address?.country_code,
      },
    },
  });
}
The SHOPIFY_ADMIN_TOKEN is a private Admin API access token — never expose it in client-side code. This endpoint runs server-side only. Your CHATAXON_WEBHOOK_SECRET ensures only ChatAxon can call it.

Real-time Webhook

Instant sync

When products change on your platform, fire a POST to our webhook endpoint. ChatAxon immediately re-fetches your feed and re-indexes it — your AI assistant stays up to date within seconds.

Endpoint

http
POST https://api.chataxon.com/api/store/feed/webhook

Headers:
  x-api-key: chataxon_YOUR_API_KEY
  Content-Type: application/json
  X-ChatAxon-Signature: <your_webhook_secret>   # optional but strongly recommended

Body (all fields optional):
{
  "event": "product.updated"  // product.created | product.deleted | catalog.updated
}
About the webhook signature: The X-ChatAxon-Signature header is optional — if omitted, the request is still accepted when the API key is valid. If included, it must be the pre-computed HMAC-SHA256 hex value tied to your store. Retrieve it once from GET https://api.chataxon.com/api/store/feed/webhook-secret (authenticated with your API key) and store it as an environment variable on your server. Do not compute it per-request — just send the static value you retrieved.

Get your webhook secret (one-time setup)

bash
# Run once. Store the returned webhook_secret in your server's environment variables.
curl -s https://api.chataxon.com/api/store/feed/webhook-secret \
  -H "x-api-key: chataxon_YOUR_API_KEY"

# Response:
# { "webhook_secret": "a3f1c8...64 hex chars..." }
202

Accepted

Sync job queued successfully

401

Unauthorized

Invalid API key or signature

422

Unprocessable

No feed URL configured for this store

Rate limit

Max 20 calls per hour per API key. For catalogs that change frequently, batching is fine — the queue deduplicates rapid calls. If you exceed the limit, you receive a 429 Too Many Requests response.

Code examples

Replace chataxon_YOUR_API_KEY with your actual API key and CHATAXON_WEBHOOK_SECRET with the value returned by the /webhook-secret endpoint above.

bash
# Set these in your environment first:
# CHATAXON_API_KEY=chataxon_YOUR_API_KEY
# CHATAXON_WEBHOOK_SECRET=<value from /api/store/feed/webhook-secret>

curl -X POST https://api.chataxon.com/api/store/feed/webhook \
  -H "x-api-key: $CHATAXON_API_KEY" \
  -H "X-ChatAxon-Signature: $CHATAXON_WEBHOOK_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"event": "catalog.updated"}'

CSAT Rating

Optional

Show a satisfaction prompt at the end of a conversation (👍 / 👎) and send the result to ChatAxon. The rating appears in your analytics dashboard under CSAT Score.

Fire the event from your widget UI (after the user clicks 👍 or 👎) using the POST /api/store/track endpoint:

Endpoint

http
POST https://api.chataxon.com/api/store/track
x-api-key: chataxon_YOUR_API_KEY
x-session-id: <current chat session UUID>
Content-Type: application/json

{
  "event_type": "csat",
  "metadata": {
    "rating": "positive"   // "positive" | "negative"
  }
}

JavaScript widget example

javascript
// Call this after showing the thumbs-up / thumbs-down prompt
async function sendCSAT(rating) {
  await fetch('https://api.chataxon.com/api/store/track', {
    method: 'POST',
    headers: {
      'Content-Type':  'application/json',
      'x-api-key':     window.ChatAxonConfig.apiKey,
      'x-session-id':  window.ChatAxon.getSessionId(), // exposed by the widget
    },
    body: JSON.stringify({
      event_type: 'csat',
      metadata:   { rating }, // 'positive' | 'negative'
    }),
  });
}

// Wire up your buttons
document.getElementById('thumbs-up').addEventListener('click',   () => sendCSAT('positive'));
document.getElementById('thumbs-down').addEventListener('click', () => sendCSAT('negative'));
FieldRequiredDescription
event_typerequiredMust be exactly "csat"
metadata.ratingrequired"positive" or "negative"
Only one CSAT event per session is counted. Sending a second rating for the same x-session-id will be recorded but may skew averages — gate the prompt so it appears only once.

Widget Embed

Non-WordPress

Add the ChatAxon chat widget to any website — no CMS required. Include the script tag before </body>.

Minimal embed

html
<!-- ChatAxon Widget -->
<div id="chataxon-root"></div>
<script>
  window.ChatAxonConfig = {
    apiKey:  'chataxon_YOUR_API_KEY',
    apiUrl:  'https://api.chataxon.com',
  };
</script>
<script
  src="https://cdn.chataxon.com/widget.js"
  data-cfasync="false"
  data-no-defer="1"
  defer
></script>

Full configuration

html
<script>
  window.ChatAxonConfig = {
    // Required
    apiKey:  'chataxon_YOUR_API_KEY',
    apiUrl:  'https://api.chataxon.com',

    // Appearance
    themeColor:     '#1E364B',      // hex color for buttons and accents
    widgetPosition: 'bottom-right', // 'bottom-right' | 'bottom-left'
    offsetBottom:   24,             // pixels from bottom edge
    offsetSide:     24,             // pixels from side edge

    // Mobile overrides (null = inherit from desktop)
    mobileWidgetPosition: null,
    mobileOffsetBottom:   null,
    mobileOffsetSide:     null,

    // Behaviour
    defaultOpen:    false,          // open chat on page load
    bubbleText:     'Need help?',   // speech bubble above widget
    welcomeMessage: 'Hi! How can I help you today?',

    // Internationalisation
    currency: '€',                  // symbol passed to price display

    // Transactional hooks (optional — enables add-to-cart, discounts)
    hooks: {
      addToCart:     async ({ productId, variantId, quantity }) => { /* ... */ return { success: true }; },
      applyDiscount: async ({ code })                          => { /* ... */ return { success: true, message: 'Applied!' }; },
      getCart:       async ()                                  => ({ count: 0, total: 0, items: [] }),
    },
  };
</script>
FieldRequiredDescription
apiKeyrequiredYour chataxon_ store key (from the dashboard)
apiUrlrequiredAlways https://api.chataxon.com
themeColoroptionalHex color for the widget accent (#1E364B default)
widgetPositionoptional"bottom-right" (default) or "bottom-left"
offsetBottomoptionalPixels from bottom edge (default 24)
offsetSideoptionalPixels from side edge (default 24)
mobileWidgetPositionoptionalOverride position on mobile. null = use desktop setting
defaultOpenoptionalOpen chat automatically on page load (default false)
bubbleTextoptionalShort text in the speech bubble shown above the button
welcomeMessageoptionalFirst message shown in the chat window
currencyoptionalCurrency symbol used by the widget for price display only (default $). Not stored server-side — prices in the feed are used as-is.
hooks.addToCartoptionalJS Hook — called when AI adds product to cart
hooks.applyDiscountoptionalJS Hook — called when AI applies a discount code
hooks.getCartoptionalJS Hook — widget calls this to show cart count badge
The apiKey is safe to include in client-side code. It is scoped to your store and only permits reading product data and sending chat messages — no write access.