Conversion tracking

Capture post-click outcomes with the Conversion API: leads, sales, refunds, and more.

What conversion tracking does

Conversion tracking lets you measure what happens after someone clicks one of your short links. Instead of only knowing that a click occurred, you can record the business outcomes that followed-a lead form submission, a completed purchase, a subscription signup, a refund.

This gives you a complete picture: not just "how many people clicked?" but "how many people clicked and then became customers?"


How it works (end to end)

Visitor clicks your short link
        ↓
Nimriz appends nim_ct to the destination URL
        ↓
Your landing page captures and stores nim_ct
        ↓
Visitor completes an action (fills form, purchases, signs up)
        ↓
Your backend sends a signed conversion event to Nimriz
        ↓
Nimriz joins the conversion to the original click

The nim_ct parameter is the deterministic bridge between the click and the conversion. It is an opaque token-it does not encode any personal information.


Prerequisites

  • A workspace plan that includes conversion tracking.
  • Conversion tracking explicitly enabled on the links you want to measure.
  • A workspace Conversion API signing secret generated from Dashboard → Settings → Integrations.
  • A secure server-side environment to receive and store the click ID, and to send signed conversion events.
  • Control over your landing page to capture the nim_ct query parameter.

Step 1-Enable conversion tracking on a link

Conversion tracking is opt-in per link. It is not enabled by default.

  1. Create a new link or open an existing link's detail page.
  2. Find the Conversion tracking toggle in the link settings.
  3. Enable it.

When conversion tracking is enabled on a link, Nimriz will append nim_ct=<token> to the destination URL on every redirect where the destination is safe to modify.


Step 2-Generate your signing secret

Your Conversion API signing secret is used to sign requests from your backend to the Nimriz Conversion API. This is a separate credential from your workspace API key.

  1. Go to Dashboard → Settings → Integrations.
  2. Find the Conversion tracking section.
  3. Click Generate signing secret.
  4. Copy and store the secret securely in your server-side environment variables. It is shown only once.

Never expose this secret in browser-side code or commit it to version control.


Step 3-Capture nim_ct on your landing page

When a visitor clicks your enabled short link, Nimriz appends nim_ct=<token> to the destination URL before redirecting. Your landing page needs to read and store this token.

// Server-side example (Next.js App Router, Express, etc.)
export async function GET(request: Request) {
  const url = new URL(request.url);
  const clickId = url.searchParams.get('nim_ct');

  if (clickId) {
    // Store on the session, lead record, cart, order, or checkout metadata
    await storeClickIdForSession(sessionId, clickId);
  }

  // Render your landing page normally
}

Where to store nim_ct depends on your funnel:

Funnel stageWhere to store nim_ct
Lead/signup formOn the pending lead or CRM contact record.
E-commerce checkoutOn the cart or order metadata before payment completes.
SaaS trialOn the pending trial or account record.
Long consideration cycleCarry it through your CRM pipeline to the closed event.

Step 4-Send conversion events from your backend

After a business event occurs (a lead is created, an order is paid, a subscription activates), your backend sends a signed POST request to the Nimriz Conversion API.

Endpoint

POST https://api.nimriz.com/api/conversions/callback/:workspace_id

Replace :workspace_id with your workspace's UUID (visible in Settings → Account).

Required headers

Content-Type: application/json
X-Nim-Timestamp: <current unix timestamp in seconds>
X-Nim-Signature: v1=<hex hmac sha256>
Idempotency-Key: <stable key for this conversion event>

Generating the signature

import crypto from 'node:crypto';

function signConversionRequest({ secret, timestamp, rawBody }) {
  return `v1=${crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')}`;
}

// Usage
const timestamp = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify(payload);
const signature = signConversionRequest({
  secret: process.env.NIM_CONVERSION_SECRET,
  timestamp,
  rawBody: body,
});

Conversion event types

Nimriz supports five immutable conversion outcome types. Each event type is stored permanently-negative follow-on events (refund, cancellation, reversal) do not overwrite the original positive event.

lead

A non-monetary attributable outcome: form submission, trial signup, demo booking, newsletter subscription.

{
  "event_name": "lead",
  "event_time": "2026-04-01T14:30:00.000Z",
  "event_id": "crm-lead-abc123",
  "user_data": {
    "click_id": "nimct_xxxxxxxxxxxxxxxxxxxxxxxx",
    "external_id": "contact_12345"
  },
  "custom_data": {
    "properties": {
      "source_system": "hubspot",
      "form_type": "demo-request"
    }
  }
}

sale

A confirmed purchase, paid invoice, or subscription activation.

{
  "event_name": "sale",
  "event_time": "2026-04-01T15:05:00.000Z",
  "event_id": "order-xyz789",
  "user_data": {
    "click_id": "nimct_xxxxxxxxxxxxxxxxxxxxxxxx",
    "external_id": "customer_67890"
  },
  "custom_data": {
    "order_id": "order-xyz789",
    "value": 149.00,
    "currency": "USD",
    "quantity": 1,
    "properties": {
      "plan": "pro-annual"
    }
  }
}

refund

A confirmed refund on a prior sale. Must reference the original sale.

{
  "event_name": "refund",
  "event_time": "2026-04-10T09:00:00.000Z",
  "event_id": "refund-xyz789-1",
  "custom_data": {
    "order_id": "refund-xyz789",
    "related_order_id": "order-xyz789",
    "value": 149.00,
    "currency": "USD",
    "properties": {
      "reason": "customer_request"
    }
  }
}

cancellation

A cancellation or void of a prior commitment when it is distinct from a refund in your billing system.

{
  "event_name": "cancellation",
  "event_time": "2026-04-12T11:00:00.000Z",
  "event_id": "cancel-sub-67890",
  "custom_data": {
    "related_order_id": "order-xyz789",
    "properties": {
      "reason": "end_of_contract"
    }
  }
}

reversal

A chargeback or negative financial adjustment when it does not fit the refund or cancellation semantics.

{
  "event_name": "reversal",
  "event_time": "2026-04-15T13:00:00.000Z",
  "event_id": "chargeback-xyz789",
  "custom_data": {
    "related_order_id": "order-xyz789",
    "value": 149.00,
    "currency": "USD",
    "properties": {
      "reason": "fraudulent"
    }
  }
}

Complete field reference

FieldRequiredTypeDescription
event_nameYesStringOne of: lead, sale, refund, cancellation, reversal.
event_timeNoISO 8601 stringWhen the event occurred. Defaults to the time Nimriz receives the request.
event_idRecommendedStringYour stable business identifier for this event. Used for business-level deduplication.
user_data.click_idNoStringThe nim_ct value captured from the landing page URL. Enables deterministic click attribution.
user_data.external_idNoStringYour stable customer or lead identifier. Enables future same-customer attribution.
custom_data.order_idRecommended for salesStringYour order, invoice, or transaction identifier.
custom_data.related_order_idRequired for refund/cancellation/reversalStringReferences the original sale's order_id.
custom_data.related_event_idAlternative to related_order_idStringReferences the original event's event_id.
custom_data.valueNoNumberMonetary value. Requires currency when provided.
custom_data.currencyConditionalStringISO 4217 currency code (e.g., USD, EUR). Required when value is set.
custom_data.quantityNoIntegerMust be a positive integer.
custom_data.propertiesNoObjectArbitrary key/value metadata for your own reporting context.
Idempotency-Key headerYesStringTransport-level retry key. Must be unique per delivery attempt of the same event.

event_id vs Idempotency-Key

These two fields serve distinct purposes and should not be confused:

  • event_id is a business identifier-it identifies a specific business outcome (e.g., "this is the lead created for John Smith after clicking the spring campaign link"). Using the same event_id for duplicate requests tells Nimriz "this is the same business event, do not create a duplicate record."

  • Idempotency-Key is a transport identifier-it protects against duplicate deliveries caused by network failures and retries. Use a fresh Idempotency-Key for each retry of a failed request, but keep the event_id the same.

First attempt:   Idempotency-Key: attempt-1-uuid,  event_id: crm-lead-abc123
Retry attempt:   Idempotency-Key: attempt-2-uuid,  event_id: crm-lead-abc123

Query-sensitive destinations

Some destination URLs cannot safely have nim_ct appended because they rely on signed or integrity-protected query strings. Common examples:

  • Pre-signed S3 or GCS URLs (contain X-Amz-Signature, X-Goog-Signature, or policy parameters).
  • Destinations with HMAC-protected parameter sets.
  • Payment confirmation URLs with integrity tokens.

When Nimriz detects a query-sensitive destination, it suppresses nim_ct appending rather than risk breaking the redirect. The short link redirects normally to the destination-but without the nim_ct parameter.

What you can still do:

  • Use user_data.external_id in your conversion events to link conversions to customers identified by your own system.
  • If your system assigns order IDs before the redirect, carry the order ID through your funnel without relying on nim_ct.

Idempotency and retries

Conversion events are designed to be sent at-least-once safely. If your backend fails or times out when sending an event, you can retry with the same event_id. Nimriz returns the stored event rather than creating a duplicate.

Rules:

  • Same event_id + same payload on a retry → returns the stored result, no duplicate.
  • Same Idempotency-Key + different payload → rejected (the key is already associated with a different payload).
  • Generate a fresh Idempotency-Key on each retry to protect against transport-level duplicates while keeping event_id stable.

Viewing conversions in the dashboard

Conversion events appear in your analytics under Analytics → Conversions.

The Conversions view shows:

  • Total conversions by type (lead, sale, etc.) over your selected date range.
  • Attribution rate: percentage of conversions that were attributed to a specific Nimriz click via nim_ct.
  • Conversions by link: which links are driving the most conversions.
  • Conversions by variant: for A/B-routed links, how conversions split across variants.

Conversion data is also available in analytics exports (see Exports).


Troubleshooting

nim_ct is not appearing on my landing page URL

  1. Confirm conversion tracking is enabled on the link (toggle in link settings).
  2. Check whether the destination URL is classified as query-sensitive. If Nimriz detects a signed URL pattern, it suppresses nim_ct to avoid breaking the redirect.
  3. Confirm you are clicking the actual short link (not navigating directly to the destination).

Conversion API request is rejected with a 401 or signature error

  1. Confirm you are using the Conversion API signing secret, not the workspace API key.
  2. Verify the signature computation: HMAC-SHA256("${timestamp}.${rawBody}", secret).
  3. Confirm X-Nim-Timestamp is a Unix timestamp in seconds (not milliseconds).
  4. Confirm you are signing the raw request body bytes-do not parse and re-serialize the JSON before signing, as this can alter byte order or whitespace.

Refund/cancellation event is rejected

Negative follow-on events must reference an earlier sale. Include custom_data.related_order_id matching the original sale's order_id, or custom_data.related_event_id matching the original sale's event_id. If no matching sale exists in Nimriz yet, the event will be rejected.

Conversions appear but attribution shows 0%

Attribution requires a valid nim_ct click ID in user_data.click_id. If conversions arrive without a click ID, they are stored (for reporting totals) but cannot be attributed to a specific click. Ensure your funnel is capturing and forwarding nim_ct from the landing page URL to your conversion event.


Related guides