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.
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,signuporconversion. 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.
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
- Store
campaign_idon arrival.Use an HttpOnly cookie, session, cart, lead record or signup flow, for example. - Only send after success.Register the conversion after your payment, registration or lead is truly saved.
- Use secrets.Set
STATORA_API_KEYandSTATORA_SITE_KEYin server configuration, not in frontend code. - Log errors without blocking your flow.A temporary network error must not make an order or registration fail.
- 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.