Figlix is in private pilot. Every example on this site is real output from a real campaign.Ask for early access
figlix

Help · For developers

Send Figlix your conversions.

Figlix writes and posts a brand's marketing. This is how the brand's own site tells it what happened after the click — a signup, an order, a booking — so Insights can say which channel, campaign and post brought each one. One endpoint, one POST, no SDK.

The one idea

Every link Figlix puts on a post already carries UTM tags it built itself: the channel in utm_source, the campaign in utm_campaign, the exact post in utm_content. Keep those tags when a visitor lands, and send them back with the event when that visitor converts. Figlix matches them to the post that carried the link. An event with no tags still counts — as direct.

The endpoint

On Insights → Conversions in Figlix, someone with the workspace's permission makes a source — one per site or app — and gets a key. The key goes in the path, and it is the whole authentication:

POST https://api.figlix.com/public/conversions/<key>

The key names the brand, so keep it on the server where you can. Any origin may call it, so a browser snippet works too. If it leaks, revoke it on the same screen and make another — the events it already sent stay.

The body

POST https://api.figlix.com/public/conversions/<key>
content-type: application/json

{
  "events": [
    {
      "id": "signup-1042",
      "type": "SIGNUP_COMPLETED",
      "occurredAt": "2026-09-22T04:12:09Z",
      "anonymousId": "v_8f2a…",
      "url": "https://your-site.example/start?utm_source=facebook&utm_campaign=spring-launch&utm_content=<post id>"
    }
  ]
}

Up to 50 events in one call, 32 KB in all. A bigger backlog is more calls.

Every field

id · yes
Your own id for the event, 1–128 characters. The same id on a retry counts once, so retrying is free.
type · yes
What happened. One of the types below, or your own in the same shape.
occurredAt · yes
When it happened, ISO 8601. Inside the last 30 days; a few minutes into the future is allowed for a clock that drifts.
url · one of the two
The landing page's full address, with the utm_ parameters the visitor arrived with. Figlix reads the tags off it.
utm · one of the two
The tags themselves: source, medium, campaign, content, term. Send these when you kept the tags rather than the whole address.
value, currency · together or not at all
The amount in the currency's units (149.5, not 14950) and its ISO 4217 code, such as AUD.
anonymousId, sessionId · no
Opaque ids you choose, up to 128 characters, never an email address. Send an anonymousId per visitor: it is what lets a funnel count people rather than events.
metadata · no
Up to 20 keys of short strings (at most 200 characters each). Never personal data — an email address anywhere in it refuses the event.

The event types

Figlix knows these, and shows them in words on Insights:

  • LANDING_PAGE_VIEW
  • SIGNUP_STARTED
  • SIGNUP_COMPLETED
  • WEDDING_CREATED
  • VENDOR_SEARCHED
  • VENDOR_SHORTLISTED
  • VENDOR_PROFILE_CLAIM_STARTED
  • VENDOR_PROFILE_CLAIM_COMPLETED
  • SUBSCRIPTION_STARTED
  • REVENUE

Your own type is allowed in the same shape: UPPER_CASE, 3–60 characters, such as BOOKING_CONFIRMED.

From the browser

// On every page: keep the tags the visitor landed with, and who they are to you.
const q = new URLSearchParams(location.search);
if (q.has("utm_source")) sessionStorage.setItem("figlix_landing", location.href);
let anonymousId = localStorage.getItem("figlix_visitor");
if (!anonymousId) localStorage.setItem("figlix_visitor", (anonymousId = crypto.randomUUID()));

// When the thing happens: send it once, with an id of your own.
fetch("https://api.figlix.com/public/conversions/<key>", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ events: [{
    id: "signup-" + SIGNUP_ID,
    type: "SIGNUP_COMPLETED",
    occurredAt: new Date().toISOString(),
    anonymousId,
    url: sessionStorage.getItem("figlix_landing") ?? location.href,
  }] }),
});

Sending from your server is better where you can: it survives ad blockers, and the key stays out of the page.

What it answers

200
The batch was read. The body says how many were accepted, how many were duplicates of ids already sent, and which were refused and why.
404
source_not_found — the key names no active source. It was revoked, or copied wrongly.
413
body_too_large — over 32 KB. Send fewer events per call.
422
validation_failed — the body is not { "events": [ … ] }, or it is empty, or over 50.
429
rate_limited — too many calls at once. The retry-after header says when to come back.
5xx
Figlix's side. Retry with the same ids; nothing is ever counted twice.

Retries are free: the id you send is yours and unique per brand, so the same event twice counts once and says so.

What never to send

  • An email address, a name or a phone number — anywhere, including inside metadata. Figlix refuses the event rather than storing it.
  • Anything you would not want in a marketing report. Metadata is for a plan name or a product line, not for a person.
  • A key in a public repository. Keep it on the server where you can; revoke and remake it on Insights → Conversions if it leaks.

What Figlix does with it

  • Attributes each event as it arrives — last touch — to the channel, campaign and post its tags name. A tag that names nothing Figlix knows is kept as it arrived, and that dimension counts as unattributed.
  • Shows the last 30 days on Insights → Conversions: by type, by channel, by campaign, by post, with the recent events.
  • Counts them against a funnel you define — landed, signed up, paid — on Insights → Funnels, which says where people stop and which channel's people get furthest. Send an anonymousId and it counts people rather than events.
  • Holds no personal data about your customers. That is a rule at the door, not a promise: an email address in the metadata refuses the event.
  • Reads no ad spend yet, so it shows counts and values rather than a cost per conversion. That arrives when spend does.