Browser Session Purchases
Octocom can record purchases made by users during their browser session. This lets you tie checkout events to the same visitor who may have chatted with your AI — useful for analytics, attribution, and support. Recording purchases is done via a public API that requires no authentication, only rate limiting.
What is a browser session?
When the Octocom chat widget loads on your page, it automatically creates a browser session — even before the visitor opens the chat. The session is identified by a UUID and is stored in the visitor's localStorage, so it persists across page navigations within the same browser.
A browser session is how Octocom links activity across a visitor's journey: it connects chat conversations, page visits, and (with this integration) purchases to a single anonymous visitor profile.
Prerequisites
Before you record purchases via the API, make sure you have:
- ✅ The Octocom chat widget installed on your site
Getting the browser session ID
The browser session ID is stored in localStorage under the key:
octocom-browser-session-id:{configId}where {configId} is your web chat configuration ID (visible in the Octocom dashboard under Settings → Channels → Web Chat).
If you don't know your configId, you can find the session ID by scanning localStorage for any key with the octocom-browser-session-id: prefix:
function getOctocomBrowserSessionId() {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key?.startsWith("octocom-browser-session-id:")) {
return localStorage.getItem(key);
}
}
return null;
}
const browserSessionId = getOctocomBrowserSessionId();If the widget has not yet loaded, this will return null. Make sure the widget script has had a chance to run before calling this function. In private/incognito windows the session still exists for the duration of the tab — it just won't carry over once the tab is closed.
Without a valid browser session ID, the API returns 404 Browser session not found. The purchase is not stored.
Recording a purchase via the API
Endpoint
POST https://api.octocom.ai/rest/v1/browser-sessions/:browserSessionId/purchases- No authentication is required; the endpoint is protected by rate limiting only.
- Rate limit: Maximum 100 requests per minute per IP address. Exceeding this returns 429 with an error message.
Example
const browserSessionId = getOctocomBrowserSessionId(); // see above
if (browserSessionId) {
try {
const response = await fetch(
`https://api.octocom.ai/rest/v1/browser-sessions/${browserSessionId}/purchases`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
lineItems: [
{
id: "product-123",
quantity: 2,
},
{
id: "product-456",
quantity: 1,
variant: { variantId: "variant-789" },
},
],
totalPrice: 99.99,
currencyCode: "USD",
provider: "shopify",
}),
},
);
if (!response.ok) {
console.error(
"Failed to record purchase",
response.status,
await response.text(),
);
}
} catch (err) {
console.error("Failed to record purchase", err);
}
}Full checkout integration example
Here is a complete example of how you might call this at the end of a checkout flow:
async function recordOctocomPurchase({
lineItems,
totalPrice,
currencyCode,
provider,
}) {
function getOctocomBrowserSessionId() {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key?.startsWith("octocom-browser-session-id:")) {
return localStorage.getItem(key);
}
}
return null;
}
const browserSessionId = getOctocomBrowserSessionId();
if (!browserSessionId) {
// Widget hasn't initialised yet or Octocom isn't installed — skip silently.
return;
}
try {
const response = await fetch(
`https://api.octocom.ai/rest/v1/browser-sessions/${browserSessionId}/purchases`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ lineItems, totalPrice, currencyCode, provider }),
},
);
if (!response.ok) {
console.error(
"Octocom: failed to record purchase",
response.status,
await response.text(),
);
}
} catch (err) {
console.error("Octocom: failed to record purchase", err);
}
}
// Call this after a successful checkout:
recordOctocomPurchase({
lineItems: [
{ id: "product-123", quantity: 2 },
{ id: "product-456", quantity: 1, variant: { variantId: "variant-789" } },
],
totalPrice: 99.99,
currencyCode: "USD",
provider: "shopify",
});Request schema
The request body must be valid JSON with the following shape:
{
lineItems: Array<{
id: string, // Required. The purchased item's (product) ID.
quantity: number, // Required. Quantity purchased.
variant?: { // Optional. Include only when the item is a variant.
variantId: string, // The variant's ID.
},
// You may include other fields; they are stored as JSON.
}>,
totalPrice: number, // Required. Total price of the purchase. Must be positive.
currencyCode: string, // Required. e.g. "USD", "EUR".
provider?: string, // Optional. e.g. "shopify", "api". Default: "api".
}Line items:
lineItemsmust be an array. Each element represents one purchased item.- Each item must include:
id— the purchased product/item ID.quantity— how many of this item were purchased.
- If the item is a variant (e.g. size/color), add a
variantobject with avariantIdfield.
Example for a simple product and a variant product:
lineItems: [
{ id: "prod_abc", quantity: 2 },
{ id: "prod_xyz", quantity: 1, variant: { variantId: "var_123" } },
];Response
| Status | Meaning |
|---|---|
| 201 | Purchase recorded. Response body includes success: true, message, and id (UUID of the created purchase record). |
| 400 | Invalid request body (e.g. validation failed). |
| 404 | Browser session not found. Check that browserSessionId is a valid, existing session UUID. |
| 429 | Rate limit exceeded. Maximum 100 requests per minute per IP. |
| 500 | Server error (e.g. failed to store the purchase). |
Security considerations
- No API keys: This endpoint is intended to be called from the browser (e.g. after checkout). Because the URL and payload can be seen in client-side code, the endpoint does not use API keys. Protection is via rate limiting (100 requests/minute per IP).
- Abuse: If you see abuse or spam purchases, report it to Octocom. We can help with additional mitigations (e.g. stricter limits or custom rules).
- CORS: The API is configured to allow requests from your origins as needed for browser-based calls.
Summary
| What you need | Description |
|---|---|
| Browser session ID | Read from localStorage using the key octocom-browser-session-id:{configId}, or scan for any key with the octocom-browser-session-id: prefix. |
| Line items | Array of objects with id, quantity, and optional variant: { variantId } for variants. |
| totalPrice / currencyCode | Total amount and currency of the order. |
| provider | Optional identifier (e.g. "shopify", "api") for where the purchase originated. |
Call POST …/browser-sessions/:browserSessionId/purchases with the above body to record a purchase for that session.