Codevoorbeelden campagnes

Stuur conversies betrouwbaar vanuit je backend.

Gebruik deze voorbeelden wanneer een conversie pas definitief is nadat je server een betaling, registratie, download of lead heeft verwerkt. Je backend stuurt dan een POST-request naar Statora met je geheime API-sleutel.

Bewaar de API-sleutel altijd als server-side geheim en plaats hem nooit in HTML, WordPress frontend JavaScript of browsercode.

Campagnes openen

API

Endpoint en payload

Maak eerst bij Campagnes een API-sleutel voor de website. Stuur daarna na een succesvolle conversie een request naar:

POST https://statora.nl/api/campaign-conversions
X-Statora-Key: statora_jouw_geheime_sleutel
Content-Type: application/json
siteKey
De Site ID van de website in Statora.
campaignCode
De achtcijferige code uit campaign_id. Bewaar deze bij de bezoeker, lead, order of registratie.
conversionType
Gebruik sale, download, lead, signup of conversion.
externalReference
Een unieke referentie uit je eigen systeem, bijvoorbeeld ordernummer, user-id of lead-id.
value
Optioneel bedrag voor omzetrapportage, bijvoorbeeld 49.95.
Dubbele conversies

Gebruik per campagne een unieke externalReference. Als dezelfde referentie opnieuw binnenkomt, accepteert Statora het request maar telt de conversie niet dubbel.

.NET

C# voorbeeld

Dit voorbeeld gebruikt HttpClient en slaat foutmeldingen alleen op in je eigen logs, zodat een tijdelijke API-fout je signup-flow niet blokkeert.

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 voorbeeld

Plaats dit in een kleine plugin of in server-side theme code. Het voorbeeld leest campaign_id uit de URL, bewaart hem tijdelijk in een cookie en stuurt later een conversie met 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 voorbeeld

Gebruik dit patroon in Laravel, Symfony of plain PHP. Haal de API-sleutel uit environment variables of je 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 voorbeeld

Dit voorbeeld gebruikt requests. Roep de functie aan nadat je applicatie de order, lead of signup succesvol heeft opgeslagen.

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 voorbeeld

Dit voorbeeld gebruikt de standaard java.net.http.HttpClient. In Spring kun je dezelfde payload ook via RestClient of WebClient versturen.

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 voorbeeld

Node 18 en nieuwer hebben fetch standaard beschikbaar. Gebruik dit alleen server-side, bijvoorbeeld in Express, Next.js API routes of een 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}`
});

Afronden

Controlelijst voor productie

  1. Bewaar campaign_id bij binnenkomst.Gebruik bijvoorbeeld een HttpOnly cookie, sessie, cart, leadrecord of signup-flow.
  2. Stuur pas na succes.Registreer de conversie nadat je betaling, registratie of lead echt is opgeslagen.
  3. Gebruik secrets.Zet STATORA_API_KEY en STATORA_SITE_KEY in serverconfiguratie, niet in frontend code.
  4. Log fouten zonder je flow te blokkeren.Een tijdelijke netwerkfout mag een bestelling of registratie niet laten mislukken.
  5. Controleer 401 en 404 apart.401 betekent meestal een ontbrekende of verkeerde API-sleutel. 404 betekent vaak dat de campagnecode niet bij de opgegeven website hoort.