curl -X POST "https://api.genlook.app/storefront/v1/events" \
-H "Authorization: Bearer pk_your_key_here" \
-H "X-Genlook-Anonymous-Id: anon_550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"event": "widget:button_click",
"properties": { "product_id": "gid://shopify/Product/456" },
"timestamp": "2024-01-15T10:30:00Z",
"$insert_id": "event_123"
}
],
"context": {
"anonymous_id": "anon_550e8400-e29b-41d4-a716-446655440000",
"session_id": "sess_abc123",
"$pageview_id": "pv_1",
"widget_version": "wv_custom-1.0.0",
"widget_enabled": true,
"product_id": "gid://shopify/Product/456",
"variant_id": null,
"$screen_width": 390,
"$screen_height": 844,
"$timezone": "Europe/Paris",
"$current_url": null,
"$raw_user_agent": null,
"integration": "sdk"
}
}'
await fetch("https://api.genlook.app/storefront/v1/events", {
method: "POST",
headers: {
"Authorization": `Bearer ${PUBLISHABLE_KEY}`,
"X-Genlook-Anonymous-Id": anonymousId,
"Content-Type": "application/json",
},
body: JSON.stringify({
events: [
{
event: "widget:button_click",
properties: { product_id: "gid://shopify/Product/456" },
timestamp: new Date().toISOString(),
$insert_id: `evt_${Date.now()}_${Math.random()}`,
},
],
context: {
anonymous_id: anonymousId, // "anon_...", same id as the header
session_id: sessionId, // "sess_...", mint once per session
$pageview_id: pageviewId,
widget_version: "wv_custom-1.0.0", // must start with "wv_"
widget_enabled: true,
product_id: currentProductId, // or null
variant_id: null,
$screen_width: screen?.width ?? 0,
$screen_height: screen?.height ?? 0,
$timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
// Browser-only fields: send real values in a browser, null elsewhere.
$current_url: typeof location !== "undefined" ? location.href : null,
$raw_user_agent: typeof navigator !== "undefined" ? navigator.userAgent : null,
integration: "sdk",
},
}),
});
{
"success": true
}
Widget API Reference
Events
Send analytics events for widget usage and conversion tracking
POST
/
storefront
/
v1
/
events
curl -X POST "https://api.genlook.app/storefront/v1/events" \
-H "Authorization: Bearer pk_your_key_here" \
-H "X-Genlook-Anonymous-Id: anon_550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"event": "widget:button_click",
"properties": { "product_id": "gid://shopify/Product/456" },
"timestamp": "2024-01-15T10:30:00Z",
"$insert_id": "event_123"
}
],
"context": {
"anonymous_id": "anon_550e8400-e29b-41d4-a716-446655440000",
"session_id": "sess_abc123",
"$pageview_id": "pv_1",
"widget_version": "wv_custom-1.0.0",
"widget_enabled": true,
"product_id": "gid://shopify/Product/456",
"variant_id": null,
"$screen_width": 390,
"$screen_height": 844,
"$timezone": "Europe/Paris",
"$current_url": null,
"$raw_user_agent": null,
"integration": "sdk"
}
}'
await fetch("https://api.genlook.app/storefront/v1/events", {
method: "POST",
headers: {
"Authorization": `Bearer ${PUBLISHABLE_KEY}`,
"X-Genlook-Anonymous-Id": anonymousId,
"Content-Type": "application/json",
},
body: JSON.stringify({
events: [
{
event: "widget:button_click",
properties: { product_id: "gid://shopify/Product/456" },
timestamp: new Date().toISOString(),
$insert_id: `evt_${Date.now()}_${Math.random()}`,
},
],
context: {
anonymous_id: anonymousId, // "anon_...", same id as the header
session_id: sessionId, // "sess_...", mint once per session
$pageview_id: pageviewId,
widget_version: "wv_custom-1.0.0", // must start with "wv_"
widget_enabled: true,
product_id: currentProductId, // or null
variant_id: null,
$screen_width: screen?.width ?? 0,
$screen_height: screen?.height ?? 0,
$timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
// Browser-only fields: send real values in a browser, null elsewhere.
$current_url: typeof location !== "undefined" ? location.href : null,
$raw_user_agent: typeof navigator !== "undefined" ? navigator.userAgent : null,
integration: "sdk",
},
}),
});
{
"success": true
}
Send batched analytics events to track widget usage and conversion funnels. Max 50 events per batch. Tracking failures never block user flow.
With the SDK, funnel events are assembled, batched, and sent automatically; switch them off with
Event names follow
On JavaScript, the
@genlook/storefront SDK is the recommended integration: it calls this endpoint for you, along with the rest of the try-on flow.tracking: "denied" when creating the client.
Request
array
required
Array of event objects. Each contains:
event(string, required): Event name (e.g.widget:button_click)properties(object, optional): Custom propertiestimestamp(string, required): ISO 8601 timestamp$insert_id(string, required): Unique ID for deduplication
object
required
Shared context for all events in the batch. Required fields:
anonymous_id (anon_*), session_id (sess_*), $pageview_id, widget_version (wv_*), widget_enabled, product_id and variant_id (both nullable), $screen_width, $screen_height (send 0 when there is no display), and $timezone.The page fields ($current_url, $pathname, $host, $viewport_width, $viewport_height, $raw_user_agent, $browser_language) are optional and nullable: a browser fills them all, a native app or a server has none of them, and an honest null is expected there. Never invent values for them.An integration field (optional string) labels where the batch came from, e.g. "sdk". Set it when you build batches yourself so your traffic can be told apart in analytics.The Genlook SDK assembles and sends all of this for you, batching included. Build batches by hand only when you are not on JavaScript.
curl -X POST "https://api.genlook.app/storefront/v1/events" \
-H "Authorization: Bearer pk_your_key_here" \
-H "X-Genlook-Anonymous-Id: anon_550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"event": "widget:button_click",
"properties": { "product_id": "gid://shopify/Product/456" },
"timestamp": "2024-01-15T10:30:00Z",
"$insert_id": "event_123"
}
],
"context": {
"anonymous_id": "anon_550e8400-e29b-41d4-a716-446655440000",
"session_id": "sess_abc123",
"$pageview_id": "pv_1",
"widget_version": "wv_custom-1.0.0",
"widget_enabled": true,
"product_id": "gid://shopify/Product/456",
"variant_id": null,
"$screen_width": 390,
"$screen_height": 844,
"$timezone": "Europe/Paris",
"$current_url": null,
"$raw_user_agent": null,
"integration": "sdk"
}
}'
await fetch("https://api.genlook.app/storefront/v1/events", {
method: "POST",
headers: {
"Authorization": `Bearer ${PUBLISHABLE_KEY}`,
"X-Genlook-Anonymous-Id": anonymousId,
"Content-Type": "application/json",
},
body: JSON.stringify({
events: [
{
event: "widget:button_click",
properties: { product_id: "gid://shopify/Product/456" },
timestamp: new Date().toISOString(),
$insert_id: `evt_${Date.now()}_${Math.random()}`,
},
],
context: {
anonymous_id: anonymousId, // "anon_...", same id as the header
session_id: sessionId, // "sess_...", mint once per session
$pageview_id: pageviewId,
widget_version: "wv_custom-1.0.0", // must start with "wv_"
widget_enabled: true,
product_id: currentProductId, // or null
variant_id: null,
$screen_width: screen?.width ?? 0,
$screen_height: screen?.height ?? 0,
$timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
// Browser-only fields: send real values in a browser, null elsewhere.
$current_url: typeof location !== "undefined" ? location.href : null,
$raw_user_agent: typeof navigator !== "undefined" ? navigator.userAgent : null,
integration: "sdk",
},
}),
});
Event Types
| Event | Description |
|---|---|
widget:button_click | Widget button clicked |
widget:image_upload | User uploaded an image |
widget:generation_start | Try-on started |
widget:result_view | Result displayed |
widget:share_clicked | Share button clicked |
widget:download_clicked | Download button clicked |
widget:add_to_cart_clicked | Add to cart from widget |
widget:add_to_cart | Add to cart succeeded |
widget:email_collected | Email collected |
product_page:page_view | Product page viewed |
product_page:cart_add | Cart add from product page |
category:action format with snake_case. The names are part of the analytics contract, so send them exactly as listed.
Identifying a signed-in shopper
Two optional headers attach the batch to a known shopper:X-Genlook-Customer-Id: platform customer idX-Genlook-Customer-Email: customer email
Authenticating
One endpoint serves every platform, and in most cases you send no credential at all: whatever sits between your code and Genlook adds one for you.| Where your code runs | What you send |
|---|---|
| Your own app, headless storefront or server | Authorization: Bearer pk_..., as shown above |
| Inside a Shopify or SHOPLINE storefront | Nothing. The app proxy signs the request. |
| On a WooCommerce or PrestaShop site | Nothing. Call your own site’s Genlook proxy path and the plugin authenticates server-side. |
Your store API key is a server credential. It never belongs in an app binary, a page bundle, or any request a browser makes. The only key meant to be embedded is the publishable one, and it always starts with
pk_.Response
boolean
required
Whether the batch was processed.
{
"success": true
}
Was this page helpful?

