Campaign code examples

Send conversions reliably from your backend.

Use these examples when a conversion is only final after your server has processed a payment, registration, download or lead. Your backend then sends a POST request to Statora with your secret API key.

Always keep the API key as a server-side secret and never place it in HTML, WordPress frontend JavaScript or browser code.

Open campaigns

API

Endpoint and payload

First create an API key for the website under Campaigns. Then send a request after a successful conversion to:

POST https://statora.nl/api/campaign-conversions
X-Statora-Key: statora_jouw_geheime_sleutel
Content-Type: application/json
siteKey
The website Site ID in Statora.
campaignCode
The eight-digit code from campaign_id. Store it with the visitor, lead, order or registration.
conversionType
Use sale, download, lead, signup or conversion.
externalReference
A unique reference from your own system, for example order number, user ID or lead ID.
value
Optional amount for revenue reporting, for example 49.95.
Duplicate conversions

Use a unique externalReference. If the same reference comes in again, Statora accepts the request but does not count the conversion twice.

.NET

C# example

This example uses HttpClient and only stores errors in your own logs, so a temporary API error does not block your signup flow.

using System.Net.Http.Json;

public sealed class StatoraConversionService
{
  private readonly HttpClient _httpClient;
  private readonly ILogger<StatoraConversionService> _logger;
  private readonly IConfiguration _configuration;

  public StatoraConversionService(
    HttpClient httpClient,
    ILogger<StatoraConversionService> logger,
    IConfiguration configuration)
  {
    _httpClient = httpClient;
    _logger = logger;
    _configuration = configuration;
  }

  public async Task TrackSignupAsync(
    string? campaignCode,
    string externalReference,
    CancellationToken cancellationToken = default)
  {
    campaignCode = NormalizeCampaignCode(campaignCode);
    if (campaignCode is null)
      return;

    var apiKey = _configuration["Statora:ApiKey"];
    var siteKey = _configuration["Statora:SiteKey"];
    var endpoint = _configuration["Statora:Endpoint"] ?? "https://statora.nl";

    if (string.IsNullOrWhiteSpace(apiKey) || string.IsNullOrWhiteSpace(siteKey))
    {
      _logger.LogWarning("Statora conversion skipped because configuration is incomplete.");
      return;
    }

    using var request = new HttpRequestMessage(
      HttpMethod.Post,
      $"{endpoint.TrimEnd('/')}/api/campaign-conversions")
    {
      Content = JsonContent.Create(new
      {
        siteKey,
        campaignCode,
        conversionType = "signup",
        externalReference
      })
    };
    request.Headers.Add("X-Statora-Key", apiKey);

    try
    {
      using var response = await _httpClient.SendAsync(request, cancellationToken);
      if (!response.IsSuccessStatusCode)
      {
        _logger.LogWarning(
          "Statora conversion failed with status {StatusCode} for campaign {CampaignCode}.",
          (int)response.StatusCode,
          campaignCode);
      }
    }
    catch (Exception ex)
    {
      _logger.LogWarning(ex, "Statora conversion failed for campaign {CampaignCode}.", campaignCode);
    }
  }

  private static string? NormalizeCampaignCode(string? value)
  {
    var code = value?.Trim();
    return code is { Length: 8 } && code.All(char.IsDigit) ? code : null;
  }
}

CMS

WordPress example

Place this in a small plugin or in server-side theme code. The example reads campaign_id from the URL, stores it temporarily in a cookie and later sends a conversion with wp_remote_post.

<?php
/**
 * Plugin Name: Statora Backend Conversions
 */

add_action('init', function () {
  if (!empty($_GET['campaign_id']) && preg_match('/^\d{8}$/', $_GET['campaign_id'])) {
    setcookie(
      'statora_campaign_id',
      sanitize_text_field($_GET['campaign_id']),
      time() + DAY_IN_SECONDS * 30,
      COOKIEPATH ?: '/',
      COOKIE_DOMAIN,
      is_ssl(),
      true
    );
  }
});

function statora_track_conversion($conversion_type, $external_reference, $value = null) {
  $campaign_code = $_COOKIE['statora_campaign_id'] ?? null;
  if (!$campaign_code || !preg_match('/^\d{8}$/', $campaign_code)) {
    return;
  }

  $body = [
    'siteKey' => getenv('STATORA_SITE_KEY'),
    'campaignCode' => $campaign_code,
    'conversionType' => $conversion_type,
    'externalReference' => $external_reference,
  ];

  if ($value !== null) {
    $body['value'] = (float) $value;
  }

  $response = wp_remote_post('https://statora.nl/api/campaign-conversions', [
    'timeout' => 5,
    'headers' => [
      'Content-Type' => 'application/json',
      'X-Statora-Key' => getenv('STATORA_API_KEY'),
    ],
    'body' => wp_json_encode($body),
  ]);

  if (is_wp_error($response)) {
    error_log('Statora conversion failed: ' . $response->get_error_message());
  }
}

// Voorbeeld na een succesvolle registratie:
// statora_track_conversion('signup', 'WP-USER-' . $user_id);

Backend

PHP example

Use this pattern in Laravel, Symfony or plain PHP. Get the API key from environment variables or your secret manager.

<?php
function track_statora_conversion(
  ?string $campaignCode,
  string $conversionType,
  string $externalReference,
  ?float $value = null
): void {
  $campaignCode = trim((string) $campaignCode);
  if (!preg_match('/^\d{8}$/', $campaignCode)) {
    return;
  }

  $payload = [
    'siteKey' => getenv('STATORA_SITE_KEY'),
    'campaignCode' => $campaignCode,
    'conversionType' => $conversionType,
    'externalReference' => $externalReference,
  ];

  if ($value !== null) {
    $payload['value'] = $value;
  }

  $ch = curl_init('https://statora.nl/api/campaign-conversions');
  curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 5,
    CURLOPT_HTTPHEADER => [
      'Content-Type: application/json',
      'X-Statora-Key: ' . getenv('STATORA_API_KEY'),
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
  ]);

  $body = curl_exec($ch);
  $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

  if ($body === false || $status < 200 || $status >= 300) {
    error_log('Statora conversion failed with status ' . $status);
  }

  curl_close($ch);
}

track_statora_conversion($_COOKIE['statora_campaign_id'] ?? null, 'sale', 'ORD-123', 49.95);

Backend

Python example

This example uses requests. Call the function after your application has successfully saved the order, lead or signup.

import logging
import os
import re

import requests

logger = logging.getLogger(__name__)


def track_statora_conversion(campaign_code, conversion_type, external_reference, value=None):
    campaign_code = (campaign_code or "").strip()
    if not re.fullmatch(r"\d{8}", campaign_code):
        return

    payload = {
        "siteKey": os.environ["STATORA_SITE_KEY"],
        "campaignCode": campaign_code,
        "conversionType": conversion_type,
        "externalReference": external_reference,
    }
    if value is not None:
        payload["value"] = value

    try:
        response = requests.post(
            "https://statora.nl/api/campaign-conversions",
            json=payload,
            headers={"X-Statora-Key": os.environ["STATORA_API_KEY"]},
            timeout=5,
        )
        if not response.ok:
            logger.warning(
                "Statora conversion failed with status %s for campaign %s",
                response.status_code,
                campaign_code,
            )
    except requests.RequestException:
        logger.exception("Statora conversion failed for campaign %s", campaign_code)


track_statora_conversion(campaign_code, "lead", "LEAD-123")

Backend

Java example

This example uses the standard java.net.http.HttpClient. In Spring you can send the same payload via RestClient or WebClient send.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public final class StatoraConversionService {
  private final HttpClient httpClient = HttpClient.newHttpClient();
  private final String siteKey = System.getenv("STATORA_SITE_KEY");
  private final String apiKey = System.getenv("STATORA_API_KEY");

  public void trackSale(String campaignCode, String orderId, double value) {
    if (campaignCode == null || !campaignCode.trim().matches("\\d{8}")) {
      return;
    }

    String json = String.format(
      "{\"siteKey\":\"%s\",\"campaignCode\":\"%s\",\"conversionType\":\"sale\",\"externalReference\":\"%s\",\"value\":%.2f}",
      siteKey,
      campaignCode.trim(),
      orderId,
      value);

    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://statora.nl/api/campaign-conversions"))
      .header("Content-Type", "application/json")
      .header("X-Statora-Key", apiKey)
      .POST(HttpRequest.BodyPublishers.ofString(json))
      .build();

    httpClient.sendAsync(request, HttpResponse.BodyHandlers.discarding())
      .thenAccept(response -> {
        if (response.statusCode() < 200 || response.statusCode() >= 300) {
          System.err.println("Statora conversion failed with status " + response.statusCode());
        }
      })
      .exceptionally(error -> {
        System.err.println("Statora conversion failed: " + error.getMessage());
        return null;
      });
  }
}

Backend

Node.js example

Node 18 and newer have fetch available by default. Use this only server-side, for example in Express, Next.js API routes or a worker.

export async function trackStatoraConversion({
  campaignCode,
  conversionType,
  externalReference,
  value
}) {
  campaignCode = String(campaignCode || '').trim();
  if (!/^\d{8}$/.test(campaignCode)) {
    return;
  }

  const payload = {
    siteKey: process.env.STATORA_SITE_KEY,
    campaignCode,
    conversionType,
    externalReference
  };

  if (value !== undefined && value !== null) {
    payload.value = value;
  }

  try {
    const response = await fetch('https://statora.nl/api/campaign-conversions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Statora-Key': process.env.STATORA_API_KEY
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      console.warn(
        `Statora conversion failed with status ${response.status} for campaign ${campaignCode}`
      );
    }
  } catch (error) {
    console.warn(`Statora conversion failed for campaign ${campaignCode}`, error);
  }
}

await trackStatoraConversion({
  campaignCode: req.cookies.statora_campaign_id,
  conversionType: 'signup',
  externalReference: `USER-${user.id}`
});

Finish

Production checklist

  1. Store campaign_id on arrival.Use an HttpOnly cookie, session, cart, lead record or signup flow, for example.
  2. Only send after success.Register the conversion after your payment, registration or lead is truly saved.
  3. Use secrets.Set STATORA_API_KEY and STATORA_SITE_KEY in server configuration, not in frontend code.
  4. Log errors without blocking your flow.A temporary network error must not make an order or registration fail.
  5. Check 401 and 404 separately.401 usually means a missing or incorrect API key. 404 often means the campaign code does not belong to the specified website.