Reference

Build on the Lucra API.

Drag a sticker to move it, or use the arrow keys while focused.

Attribution

Pixels, server events, conversions and creator codes.

Track what creators drive on a brand's own site. A pixel records visitors' events, a conversion decides which events count, and a link from a creator's video credits them. The tracking guide covers installing the pixel in the browser.

Start with POST /v1/pixels, then add a conversion for the event you care about, like a purchase.

Pixels

POST /v1/pixels creates one for the domains it may send from:

JSON
{
  "name": "Shop",
  "domains": ["https://shop.example.com"],
  "excludedCountries": ["DE"]
}
JSON
{
  "id": "pxl_0Q2m8VxR4sTnYb7KcLd3Ew",
  "name": "Shop",
  "domains": ["https://shop.example.com"],
  "excludedCountries": ["DE"],
  "status": "verified",
  "lastSeenAt": "2026-10-07T15:04:05.000Z",
  "snippet": "<script>window.lucra=window.lucra||[];lucra.push([\"init\",{siteId:\"pxl_0Q2m8VxR4sTnYb7KcLd3Ew\"}]);</script><script async src=\"https://a.onlucra.com/p.js\"></script>",
  "firstParty": {
    "path": "/lucra",
    "target": "https://a.onlucra.com",
    "snippet": "<script>…</script><script async src=\"/lucra/p.js\"></script>"
  },
  "quality": {
    "events": 1840,
    "consented": 1622,
    "fromServer": 212,
    "withUserData": 240,
    "withClickIds": 610,
    "credited": 388,
    "located": 1835
  },
  "version": 2,
  "createdAt": "2026-10-01T15:04:05.000Z",
  "updatedAt": "2026-10-02T09:12:44.000Z"
}
  • domains are origins with no path, like https://shop.example.com.
  • excludedCountries are two-letter codes; visitors there aren't recorded.
  • status is waiting until the first event arrives, then verified; archived pixels accept no events.
  • firstParty is the recommended install: proxy path on your site to target and use its snippet.
  • quality counts the last 7 days' events.

PATCH /v1/pixels/:id renames it, changes domains or excludedCountries, or archives it with status: "archived". The pixel.verified webhook fires on its first event.

A connected Shopify store can install the pixel without code from Settings → Lucra Pixel in the app.

Server events

POST /v1/pixels/:id/events (lucra.pixels.events.create in the SDK) records an event from the brand's server, so ad blockers and closed tabs can't lose it. It returns 202:

JSON
{
  "name": "purchase",
  "eventId": "order-1042",
  "orderId": "1042",
  "value": 4999,
  "currency": "USD",
  "pageUrl": "https://shop.example.com/thanks",
  "lucraId": "sub_14XA4WGiSOmaVI3B4QLm4Fs",
  "landedAt": "2026-10-05T18:20:00.000Z",
  "user": { "email": "jo@example.com", "phone": "+1 555 010 4477" },
  "clickIds": { "fbc": "fb.1.1759685000000.IwAR2x", "fbp": "fb.1.1759600000000.1234567890" },
  "ipAddress": "203.0.113.7",
  "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 26_0 like Mac OS X) …"
}
JSON
{ "eventId": "order-1042", "duplicate": false }
FieldWhat
nameA standard event (page_view, view_content, search, add_to_cart, begin_checkout, purchase, lead, sign_up, start_trial, subscribe, contact) or your own, in snake_case.
eventIdSend the browser event's ID to count it once. A repeat returns duplicate: true and confirms the browser event.
occurredAtDefaults to now; within the last 7 days.
value, currencyIn cents, with an ISO 4217 code. Send both or neither.
orderIdYour order's ID.
pageUrlA page on the pixel's domains. Defaults to its first domain.
consentgranted (default), denied or unknown. Without granted, leave out lucraId, landedAt, user, clickIds, ipAddress and userAgent.
lucraIdlucra_id from the landing URL: the video the visitor came from.
discountCodeThe order's discount code, recorded with the event.
landedAtWhen the visitor arrived from the video or code, for attribution windows.
useremail, phone, firstName, lastName, city, state, zip, country, externalId. Hashed (SHA-256) on arrival; hashes are kept as sent.
clickIdsfbc, fbp, gclid, gbraid, wbraid, ttclid, ttp, sccid, scid.
ipAddress, userAgentThe visitor's. The IP is kept 13 months.
locationcountry, region, city, postalCode, like the shipping address.
actionSourcewebsite (default), app, physical_store, phone_call, chat, email, system_generated or other.
propertiesproductId, variantId, quantity, contents ({ id, quantity, price }, up to 100) and custom (up to 25 fields).

A pixel takes up to 1,200 events a minute; past that you get 429.

Pixel events

GET /v1/pixel-events lists what the pixels received, newest first. Filter by pixel, conversion, or attributed=true for events from a creator's video. GET /v1/pixel-events/:id returns one, with what ad platforms' conversion APIs take:

JSON
{
  "id": "pxev_3Hd8kQm1ZrT6yWv2NbLx0Pa",
  "pixel": "pxl_0Q2m8VxR4sTnYb7KcLd3Ew",
  "name": "purchase",
  "occurredAt": "2026-10-07T15:04:05.000Z",
  "receivedAt": "2026-10-07T15:04:05.412Z",
  "sentFrom": "server",
  "actionSource": "website",
  "consent": "granted",
  "value": 4999,
  "currency": "usd",
  "orderId": "1042",
  "pageUrl": "https://shop.example.com/thanks",
  "referrerUrl": null,
  "submission": "sub_14XA4WGiSOmaVI3B4QLm4Fs",
  "landedAt": "2026-10-05T18:20:00.000Z",
  "clickIds": { "fbc": "fb.1.1759685000000.IwAR2x" },
  "user": { "email": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" },
  "ipAddress": "203.0.113.7",
  "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 26_0 like Mac OS X) …",
  "properties": {},
  "conversions": ["conv_1fK7pQ2wXy9LmN4bVc8RtZa"],
  "source": "paid_ad",
  "creator": "crtr_026UYfiw1Y6OvUpuKWiOpeL",
  "discountCode": null,
  "location": { "country": "US", "region": "California", "city": "Oakland", "postalCode": "94612", "timezone": "America/Los_Angeles", "latitude": 37.8, "longitude": -122.27 },
  "network": { "asn": 7922, "organization": "Comcast" },
  "device": { "type": "mobile", "os": "iOS", "browser": "Safari", "inApp": "tiktok", "language": "en-US" }
}
  • sentFrom is server for server events and browser events a server copy confirmed.
  • source is paid_ad (an ad's link) or direct; creator is who's credited.
  • user holds SHA-256 hashes, normalized for Meta, TikTok and Google.

Conversions

A conversion counts the events that matter, like purchases over $20:

JSON
{
  "name": "Purchase",
  "eventName": "purchase",
  "pageUrlContains": "/thanks",
  "minValue": { "amount": 2000, "currency": "USD" },
  "attributionWindowDays": 30,
  "payBrowserEvents": false
}
JSON
{
  "id": "conv_1fK7pQ2wXy9LmN4bVc8RtZa",
  "name": "Purchase",
  "eventName": "purchase",
  "pageUrlContains": "/thanks",
  "minValue": { "amount": 2000, "currency": "usd" },
  "attributionWindowDays": 30,
  "payBrowserEvents": false,
  "status": "active",
  "recorded": 412,
  "attributed": 96,
  "version": 1,
  "createdAt": "2026-10-01T15:04:05.000Z",
  "updatedAt": "2026-10-01T15:04:05.000Z"
}
  • eventName is a standard event or your own.
  • pageUrlContains and minValue narrow it; a minimum value matches only events in its currency.
  • attributionWindowDays (1–90, default 30) credits the creator when the visitor converts within that many days of landing from their video. Events without a landing time, like server events, are credited too.
  • payBrowserEvents lets browser-only events pay creators. Off by default, since anyone with the pixel ID can send browser events.
  • recorded counts matching events; attributed, those credited to a creator.

PATCH /v1/conversions/:id changes it or archives it; events already recorded keep counting as they did. Each matching event sends conversion.recorded with conversion, pixel_event and, when credited to a video, submission.

Pay per conversion

Add a conversion rule to a program's or a retainer's pay:

JSON
{
  "rules": [
    { "conversion": "conv_1fK7pQ2wXy9LmN4bVc8RtZa", "amount": 500 },
    { "conversion": "conv_7Rt2LmQ9xWb4NcV1kZp8YsD", "percent": 10 }
  ],
  "cap": 100000,
  "schedule": { "every": "week" }
}
  • amount pays a flat amount in cents per conversion; percent pays a share of its value, like an affiliate commission. A percent counts only events valued in USD for now.
  • Only conversions credited to the creator count: through their video's lucra_id link, within the conversion's window. One counts toward every program and retainer of that creator that pays on it.
  • Only server-confirmed events pay, unless the conversion has payBrowserEvents: true.
  • A retainer can pay only on conversions. A program pays them alongside its usual rule.

Report

GET /v1/conversions/:id/report?groupBy=creator,country breaks a conversion down by up to 3 of creator, country, region, city, inApp, deviceType, source and day. Narrow it with from, to, and credited=true for creators' only.

JSON
{
  "data": [
    { "creator": "crtr_026UYfiw1Y6OvUpuKWiOpeL", "country": "US", "conversions": 58, "value": 289942, "currency": "usd" },
    { "creator": null, "country": "CA", "conversions": 21, "value": 104979, "currency": "usd" }
  ]
}
POST/v1/pixels
write

Create a pixel

const { data } = await lucra.pixels.create({
  body: { name: "…", domains: ["…"] },
})

Body

  • namestring· required
  • domainsstring[]· required

    Origins the pixel may send from, like https://shop.example.com.

  • excludedCountriesstring[]

    Countries (ISO 3166-1 alpha-2) whose visitors the pixel doesn't record, decided by the visitor's IP country.

Response20112 fieldsShow
  • idpxl_…
  • namestring
  • domainsstring[]
  • excludedCountriesstring[]
  • statusenum

    verified once the first event arrives from an allowed domain; archived pixels accept no events.

    waitingverifiedarchived
  • lastSeenAtstringnullable
  • snippetstring

    Paste before </head> on every page of the allowed domains.

  • firstPartyobject

    Recommended: proxy path on your site to target (a rewrite in Next.js, Vercel, Cloudflare or nginx) and use this snippet instead. The pixel then keeps visitors' attribution in a first-party cookie, so Safari doesn't forget them after 7 days.

    Show 3 child fields
    • pathstring
    • targetstring
    • snippetstring
  • qualityobject

    Of the last 7 days' events: how many had consent, came from your server, carried user data or ad click IDs, were credited to a creator, and have a location.

    Show 7 child fields
    • eventsinteger
    • consentedinteger
    • fromServerinteger
    • withUserDatainteger
    • withClickIdsinteger
    • creditedinteger
    • locatedinteger
  • versioninteger

    Send it back on PATCH to reject edits based on a stale read.

  • createdAtstring
  • updatedAtstring
POST/v1/pixels/:id/events
write

Send a conversion from the brand's server; 202 once it's recorded for attribution

const { data } = await lucra.pixels.events.create({
  path: { id: "pxl_…" },
  body: { name: "…" },
})

Path parameters

  • idpxl_…· required

Body

  • namestring· required

    A standard event (page_view, view_content, search, add_to_cart, begin_checkout, purchase, lead, sign_up, start_trial, subscribe, contact) or your own, in snake_case.

  • occurredAtstring

    Defaults to now; must be within the last 7 days.

  • orderIdstring
  • valueinteger

    In cents, with its currency.

  • currencystring

    ISO 4217, in either case (usd or USD).

  • consentenum

    Recorded by default, like the browser pixel; send denied or unknown when the visitor declined, and leave out lucraId, campaign, attributionId and clickId.

    granteddeniedunknown
  • lucraIdstring

    lucra_id from the landing URL: the video (submission) the visitor came from.

  • campaignstring

    lucra_campaign from the landing URL: the paid campaign (camp_…) whose ad the visitor came from.

  • attributionIdstring

    lucra_attribution_id from older landing URLs; send lucraId for new ones.

  • clickIdstring
  • eventIdstring

    Send the browser event's ID to count a conversion once when both fire.

  • pageUrlstring

    The page the conversion happened on; defaults to the pixel's first domain.

  • propertiesobject
    Show 5 child fields
    • productIdstring
    • quantityinteger
    • variantIdstring
    • contentsobject[]
      Show 3 child fields
      • idstring· required
      • quantityinteger
      • priceinteger

        Per item, in cents, in the event's currency.

    • customobject
  • actionSourceenum

    Where the conversion happened.

    websiteappphysical_storephone_callchatemailsystem_generatedother
  • landedAtstring

    When the visitor arrived from the video (lucra_id), for conversion attribution windows.

  • userobject

    For matching on ad platforms: hashed (SHA-256) on arrival, never stored raw; already-hashed values are kept.

    Show 9 child fields
    • emailstring
    • phonestring
    • firstNamestring
    • lastNamestring
    • citystring
    • statestring
    • zipstring
    • countrystring
    • externalIdstring
  • clickIdsobject

    Ad click IDs and platform cookies from the visitor's browser.

    Show 9 child fields
    • fbcstring
    • fbpstring
    • gclidstring
    • gbraidstring
    • wbraidstring
    • ttclidstring
    • ttpstring
    • sccidstring
    • scidstring
  • ipAddressstring

    The visitor's IP address; kept 13 months.

  • userAgentstring

    The visitor's browser user agent, for their device and in-app browser.

  • creatorCodestring

    The creator's code from the landing URL (?lucra=CODE).

  • discountCodestring

    The order's discount code, recorded with the event.

  • locationobject

    Where the customer is, like the order's shipping address.

    Show 4 child fields
    • countrystring
    • regionstring
    • citystring
    • postalCodestring
GET/v1/pixels
read

List pixels

const { data } = await lucra.pixels.list()

Query parameters

Plus paging: limit, cursor, createdAfter and createdBefore.

Response200A page of items, 12 fields each, and nextCursorShow
  • idpxl_…
  • namestring
  • domainsstring[]
  • excludedCountriesstring[]
  • statusenum

    verified once the first event arrives from an allowed domain; archived pixels accept no events.

    waitingverifiedarchived
  • lastSeenAtstringnullable
  • snippetstring

    Paste before </head> on every page of the allowed domains.

  • firstPartyobject

    Recommended: proxy path on your site to target (a rewrite in Next.js, Vercel, Cloudflare or nginx) and use this snippet instead. The pixel then keeps visitors' attribution in a first-party cookie, so Safari doesn't forget them after 7 days.

    Show 3 child fields
    • pathstring
    • targetstring
    • snippetstring
  • qualityobject

    Of the last 7 days' events: how many had consent, came from your server, carried user data or ad click IDs, were credited to a creator, and have a location.

    Show 7 child fields
    • eventsinteger
    • consentedinteger
    • fromServerinteger
    • withUserDatainteger
    • withClickIdsinteger
    • creditedinteger
    • locatedinteger
  • versioninteger

    Send it back on PATCH to reject edits based on a stale read.

  • createdAtstring
  • updatedAtstring
GET/v1/pixels/:id
read

Get a pixel and whether it's verified

const { data } = await lucra.pixels.retrieve({
  path: { id: "pxl_…" },
})

Path parameters

  • idpxl_…· required
Response20012 fieldsShow
  • idpxl_…
  • namestring
  • domainsstring[]
  • excludedCountriesstring[]
  • statusenum

    verified once the first event arrives from an allowed domain; archived pixels accept no events.

    waitingverifiedarchived
  • lastSeenAtstringnullable
  • snippetstring

    Paste before </head> on every page of the allowed domains.

  • firstPartyobject

    Recommended: proxy path on your site to target (a rewrite in Next.js, Vercel, Cloudflare or nginx) and use this snippet instead. The pixel then keeps visitors' attribution in a first-party cookie, so Safari doesn't forget them after 7 days.

    Show 3 child fields
    • pathstring
    • targetstring
    • snippetstring
  • qualityobject

    Of the last 7 days' events: how many had consent, came from your server, carried user data or ad click IDs, were credited to a creator, and have a location.

    Show 7 child fields
    • eventsinteger
    • consentedinteger
    • fromServerinteger
    • withUserDatainteger
    • withClickIdsinteger
    • creditedinteger
    • locatedinteger
  • versioninteger

    Send it back on PATCH to reject edits based on a stale read.

  • createdAtstring
  • updatedAtstring
PATCH/v1/pixels/:id
write

Rename a pixel, change its domains or excluded countries, or archive it

const { data } = await lucra.pixels.update({
  path: { id: "pxl_…" },
  body: { name: "…" },
})

Path parameters

  • idpxl_…· required

Body

  • namestring
  • domainsstring[]

    Origins the pixel may send from, like https://shop.example.com.

  • excludedCountriesstring[]

    Countries (ISO 3166-1 alpha-2) whose visitors the pixel doesn't record, decided by the visitor's IP country.

  • statusstring

    Stops the pixel accepting events; its history stays.

    archived
  • versioninteger
Response20012 fieldsShow
  • idpxl_…
  • namestring
  • domainsstring[]
  • excludedCountriesstring[]
  • statusenum

    verified once the first event arrives from an allowed domain; archived pixels accept no events.

    waitingverifiedarchived
  • lastSeenAtstringnullable
  • snippetstring

    Paste before </head> on every page of the allowed domains.

  • firstPartyobject

    Recommended: proxy path on your site to target (a rewrite in Next.js, Vercel, Cloudflare or nginx) and use this snippet instead. The pixel then keeps visitors' attribution in a first-party cookie, so Safari doesn't forget them after 7 days.

    Show 3 child fields
    • pathstring
    • targetstring
    • snippetstring
  • qualityobject

    Of the last 7 days' events: how many had consent, came from your server, carried user data or ad click IDs, were credited to a creator, and have a location.

    Show 7 child fields
    • eventsinteger
    • consentedinteger
    • fromServerinteger
    • withUserDatainteger
    • withClickIdsinteger
    • creditedinteger
    • locatedinteger
  • versioninteger

    Send it back on PATCH to reject edits based on a stale read.

  • createdAtstring
  • updatedAtstring
POST/v1/conversions
write

Create a conversion: the events that count as a sign-up, a purchase or your own goal

const { data } = await lucra.conversions.create({
  body: { name: "…", eventName: "…" },
})

Body

  • namestring· required
  • eventNamestring· required

    The event that counts: a standard one (purchase, sign_up, lead…) or your own.

  • pageUrlContainsstringnullable

    Only events on pages whose URL contains this (case-insensitive).

  • minValueobject

    Only events in this currency with at least this value count.

    Show 2 child fields
    • amountinteger· required

      In cents.

    • currencystring· required

      ISO 4217, in either case.

  • attributionWindowDaysinteger

    Credits the video when the visitor converts within this many days of landing from it.

  • payBrowserEventsboolean

    Pay creators on events only the browser sent. Anyone with your pixel ID can forge those, so by default only events your server or Shopify confirmed pay.

GET/v1/conversions
read

List conversions, newest first

const { data } = await lucra.conversions.list()

Query parameters

Plus paging: limit, cursor, createdAfter and createdBefore.

GET/v1/conversions/:id
read

Get a conversion and how many events counted as it

const { data } = await lucra.conversions.retrieve({
  path: { id: "…" },
})

Path parameters

  • idstring· required
PATCH/v1/conversions/:id
write

Change a conversion or archive it; events already recorded keep counting as they did

const { data } = await lucra.conversions.update({
  path: { id: "…" },
  body: { name: "…" },
})

Path parameters

  • idstring· required

Body

  • namestring
  • eventNamestring

    The event that counts: a standard one (purchase, sign_up, lead…) or your own.

  • pageUrlContainsstringnullable

    Only events on pages whose URL contains this (case-insensitive).

  • minValueobjectnullable
    Show 2 child fields
    • amountinteger· required

      In cents.

    • currencystring· required

      ISO 4217, in either case.

  • attributionWindowDaysinteger

    Credits the video when the visitor converts within this many days of landing from it.

  • payBrowserEventsboolean

    Pay creators on events only the browser sent. Anyone with your pixel ID can forge those, so by default only events your server or Shopify confirmed pay.

  • statusenum
    activearchived
  • versioninteger
GET/v1/conversions/:id/report
read

Break a conversion down by creator, place, in-app browser, source or day, with counts and value

const { data } = await lucra.conversions.report.retrieve({
  path: { id: "…" },
  query: { groupBy: "…" },
})

Path parameters

  • idstring· required

Query parameters

  • groupBystring· required

    Up to 3, comma-separated: creator, country, region, city, inApp, deviceType, source, day.

  • fromstring

    Only conversions at or after this time.

  • tostring

    Only conversions before this time.

  • creditedenum

    true: only conversions credited to a creator.

    truefalse
Response2001 fieldsShow
  • dataany[]
GET/v1/pixel-events
read

List the events your pixels received, newest first

const { data } = await lucra.pixelEvents.list({
  query: { pixel: "pxl_…" },
})

Query parameters

  • pixelpxl_…
  • conversionconv_…
  • attributedenum

    true: only events credited to a creator (their video or their code).

    truefalse

Plus paging: limit, cursor, createdAfter and createdBefore.

GET/v1/pixel-events/:id
read

Get one pixel event, with what ad platforms' conversion APIs take

const { data } = await lucra.pixelEvents.retrieve({
  path: { id: "…" },
})

Path parameters

  • idstring· required