Browse Product guides

Affiliates with any checkout or platform

Use this path when Plandalf does not read the platform directly. The browser captures a referral token, your checkout stores it with the order, and your server reports paid sales and refunds.

Capture and store the referral

Copy your organization’s script URL from Affiliates → Setup; acme.plandalf.dev below is a placeholder. Install the SDK once. The following form is an example of your own checkout endpoint, not a Plandalf endpoint. Add your application’s normal authentication and CSRF protection.

This example loads the SDK before calling it and waits for referral capture before enabling checkout:

<form id="checkout" action="/billing/checkout" method="post">
  <input type="hidden" name="referral_token" value="" />
  <button type="submit" disabled>Continue to checkout</button>
</form>
<script src="https://acme.plandalf.dev/js/plandalf-sdk.js"></script>
<script>
  plandalf("ready", async (sdk) => {
    const form = document.querySelector("#checkout");
    const referral = await sdk.referral();
    form.querySelector('[name="referral_token"]').value = referral?.token ?? "";
    form.querySelector('button[type="submit"]').disabled = false;
  });
</script>

Save the token with the order on your server. You can also read the pf_rt cookie on the same host. A missing token is a direct visit; do not invent a partner code.

The SDK attempts a cookie on the hostname’s last two labels, then falls back to a host-only cookie if the browser rejects that domain. Do not assume cookies are shared across subdomains, particularly under suffixes such as .co.uk. Custom cookie-domain overrides are not supported by the current SDK.

Crossing domains

For ordinary links to another checkout host, configure decoration on your existing script tag:

<script
  src="https://acme.plandalf.dev/js/plandalf-sdk.js"
  data-config-referral-decorate="checkout.example-shop.com"
  async
></script>

The SDK adds pf_rt when a visitor clicks a matching anchor. The destination must read and save that token, or load the same organization’s SDK to validate and restore it. Decoration alone does not integrate a third-party checkout that discards unknown query parameters. Programmatic redirects and form posts need your own explicit token handoff.

If tracking requires consent, add data-config-referral-consent="required" to the script tag and call plandalf("consent", true) from your consent manager after permission is granted. Referral capture waits while consent is required. Do not make an essential checkout depend on that promise resolving before the visitor has decided; offer your own untracked checkout path when consent is declined.

Report payment

When payment succeeds, call the sales API from your server. Never call it from browser code.

curl --fail-with-body -X POST "https://acme.plandalf.dev/api/v1/affiliate/sales" \
  -H "Authorization: Bearer $PLANDALF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "my-shop",
    "external_id": "order_10492",
    "currency": "USD",
    "amount_cents": 30000,
    "tax_cents": 0,
    "test": true,
    "referral_token": "rt_01J9Z4K7...",
    "customer": { "email": "sam@example.com", "external_id": "cus_881" }
  }'

The example is a test sale. Use a regular active partner and a different buyer email when testing commissions. amount_cents is the amount after discounts, including any tax; commission basis is amount_cents - tax_cents. discount_cents, if supplied, is informational and is not subtracted again. Keep source, external_id, and test unchanged on retries: the API returns the existing sale rather than updating it. Change test to false only for confirmed live payments.

If the buyer used a partner code and no token is available, send code. Code-only sales are credited by the live API; they are not automatically held for review unless a separate review rule is added later.

Subscriptions

Follow the subscription setup guide for first-payment and renewal payloads. Send the same stable customer ID on each invoice and a different sale ID for each paid invoice.

Send each paid subscription invoice as one sale. For Stripe subscriptions you run yourself, prefer the native Stripe source or report invoice.paid events only; report the paid invoice once, not the subscription Checkout Session as an additional sale.

Refunds

Report each successful refund from your server, using the original sale’s source, sale_external_id, and test/live mode. Give each refund its own stable external_id, and reuse it on retries:

curl --fail-with-body -X POST "https://acme.plandalf.dev/api/v1/affiliate/refunds" \
  -H "Authorization: Bearer $PLANDALF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "my-shop",
    "sale_external_id": "order_10492",
    "external_id": "refund_10492_1",
    "amount_cents": 10000,
    "test": true
  }'

Before launch, verify an attributed paid test sale, replay the same sale without duplication, and report a partial refund. For subscriptions, also verify a paid renewal without another click.

Planned platform shortcuts

Shopify and WordPress affiliate-source apps are planned. Until they ship, use the sales API or the native Stripe source.

Feature detail