Analytics Configuration
Overview
Initialising Seekora analytics from a client (browser, server, or worker) needs two pieces of per-tenant configuration: the writeKey that authenticates ingest, and the ingestHost that determines which environment (stage vs production) you're pointing at. Both are surfaced through the Admin UI Welcome page and through a programmatic retrieval endpoint.
This page walks you through fetching those values, initialising the SDK, wiring it into the React provider, and verifying that events landed.
Get your writeKey
Through the Admin UI
- Sign in to the Seekora Admin UI.
- Open Stores → select your store → Welcome.
- Locate the Events Write Key and Events Host rows in the credentials section (alongside Application ID, Search API Key, and Write API Key).
- Copy both values —
Events Write Keyis the value you'll pass aswriteKeyon every analytics request;Events Hostis the ingest URL for your environment.
Tenants whose analytics provision is still pending will see "Provisioning…" instead of a UUID. Wait a minute and re-fetch — there's nothing the merchant needs to do.
Programmatically
For automation or first-party tooling, fetch both values via the account analytics endpoint:
GET /api/v3/account/analytics/writekey
Response:
{
"writeKey": "00000000-0000-0000-0000-000000000000",
"ingestHost": "https://analytics-ingest.seekora.ai",
"orgcode": "your-orgcode",
"xstoreid": "your-xstoreid"
}
The ingestHost field is the analytics ingest host for your tenant — use it verbatim, as it's already pinned to the right environment for the calling tenant, so you don't have to branch stage vs production yourself.
Ingest hosts by environment
If you need to know the canonical host without hitting the writekey endpoint:
| Environment | Host |
|---|---|
| Stage | https://analytics-ingest.seekora.ai |
| Production | https://analytics-ingest.seekora.ai |
Both expose the same POST /v1/b ingest path and the same { ok, okEvents, receivedEvents } response shape. See Events for the full ingest reference.
SDK initialisation
For JS/TS clients, initialise via @seekora-ai/search-sdk (lower-level trackXxx helpers) or @seekora-ai/ui-sdk-react (<SearchProvider> auto-fires lifecycle events). You don't need to construct a transport object — the SDK manages batching, retries, and routing internally.
@seekora-ai/search-sdk — direct trackXxx helpers
import { trackSearchSubmitted } from '@seekora-ai/search-sdk';
const ctx = {
writeKey: 'YOUR_WRITE_KEY',
ingestHost: 'https://analytics-ingest.seekora.ai',
userId: undefined, // set when the visitor is logged in
};
trackSearchSubmitted(ctx, {
search_id: 'search-abc-001',
query: 'wireless headphones',
num_found: 47,
surface: 'search-page',
});
@seekora-ai/ui-sdk-react — <SearchProvider>
For React storefronts using Seekora's UI components, pass trackContext on <SearchProvider>. The provider wires Search, Filter, Object, and Suggestion lifecycle events automatically.
import { SearchProvider, SearchBox, Hits } from '@seekora-ai/ui-sdk-react';
export function StorefrontSearch() {
return (
<SearchProvider
trackContext={{
writeKey: 'YOUR_WRITE_KEY',
ingestHost: 'https://analytics-ingest.seekora.ai',
}}
>
<SearchBox />
<Hits />
</SearchProvider>
);
}
You can still call the search-sdk track* helpers manually inside this tree for cart / checkout events (Product Added, Cart Viewed, Order Completed) — they share the same trackContext shape.
Direct REST initialisation
When you don't have a JS runtime (Liquid themes, server cron jobs, mobile native shells, custom integrations), POST directly to /v1/b. The writeKey goes in the body, not in a header — there is no Bearer token on this surface.
See the canonical curl example in Events for the exact payload shape, and Event fields for the per-event schema.
Verifying events landed
The ingest responds with HTTP 200 and { ok, okEvents, receivedEvents } on accept; downstream processing is asynchronous.
okEventsequals the count of events that passed envelope-level validation.receivedEventsmirrors the size of the batch you sent.- A 200 with
okEventsmatchingreceivedEventsmeans every event in the batch was accepted at ingest. Downstream processing then runs asynchronously.
If okEvents is lower than receivedEvents, some events in the batch failed envelope-level checks — see Troubleshooting below.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
HTTP 400 with body {"error":"error parsing message: ..."} | The request body is malformed JSON or fails envelope validation (missing writeKey, batch, or sentAt). | Check the envelope shape against Events → Request envelope. |
HTTP 200 with okEvents: 0 while receivedEvents is positive | The writeKey was accepted but every event in the batch failed envelope-level checks (missing type, event, anonymousId, messageId, or timestamp). | Verify each event entry has all required fields listed in Events → Event fields. |
HTTP 401 with body {"error":"Authorization header with Bearer token is required"} | You're hitting a non-public path. /v1/b does not require an Authorization header — the writeKey in the body is sufficient. | Switch to POST /v1/b with the writeKey in the body. |
| Welcome page shows "Provisioning…" instead of a writeKey | The writeKey row is still pending for this tenant. | Wait a minute, then re-fetch. If it persists, escalate — provisioning may have errored. |
| Browser network panel shows analytics requests blocked by CORS | You're calling a path other than /v1/b. Only /v1/b is browser-accessible. | Send all browser traffic to POST /v1/b. |