Skip to main content
GUIDE · REDDIT CAPI9 min read

Reddit Conversions API: the 2026 setup manual

A production-focused setup guide for sending Reddit conversion events from your server with stable event contracts, click identifier capture, Pixel deduplication, consent-aware routing, Events Manager validation, and diagnostics that keep attribution from quietly drifting.

Context

Why Reddit CAPI

Reddit is still underpriced for a specific class of advertisers: B2B tech teams selling into technical buyers, gaming publishers with community-led demand, crypto and fintech brands that need credible discussion instead of polished ad inventory, and DTC companies built around niche hobbies. The platform is not always the easiest place to scale broad prospecting, but it can surface buyers who are already reading threads, comparing tools, and asking blunt questions before they ever search for a brand.

That behavior makes measurement fragile. A Reddit click can land on a long technical article, send the user into docs, return through a direct visit, and convert after a sales form, checkout, or app install handoff. Browser-only tracking loses pieces of that path through ad blockers, Safari restrictions, consent banners, payment redirects, and cross-device research. Reddit Conversions API gives your server a direct way to send the final conversion with the first-party context you were allowed to keep.

Requirements

Prerequisites

01

Reddit Ads account with admin or measurement access to the ad account that owns the conversion source.

02

pixel_id from Reddit Events Manager for the production website pixel, not a staging or agency-only test pixel.

03

conversion_access_token generated from Reddit Ads Manager with permission to send conversion events for the target ad account.

04

Domain verified in Reddit Ads Manager for the landing pages, checkout domain, and any embedded storefront path used by paid traffic.

Build

Step-by-step setup

Build the integration in narrow layers: prove authorization, add browser context, normalize identifiers, send backend truth, then harden logging and retries. Each layer should be independently visible in your logs and Reddit diagnostics.

Step 1

Confirm account, pixel, and token ownership

Start with the objects that route the event. Reddit CAPI is scoped to an ad account endpoint, while the payload references a pixel_id and the request is authorized by the conversion_access_token. A token can be valid and still be useless if it belongs to a different business, account, or pixel. Make your first request intentionally small so token scope, account ownership, and endpoint formatting are the only variables.

POST https://ads-api.reddit.com/api/v2.0/conversions/events/{ad_account_id}
Authorization: Bearer conversion_access_token
Content-Type: application/json

{
  "pixel_id": "t2_abc123",
  "event_at": "2026-04-23T10:15:30.000Z",
  "event_type": {
    "tracking_type": "PageVisit"
  },
  "event_metadata": {
    "conversion_id": "pv_session_10492_1"
  },
  "user": {
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0..."
  }
}
Step 2

Capture browser context before checkout

The backend needs values that only the browser sees at landing time. Capture the Reddit click identifiers, client IP, user agent, screen dimensions, consent state, and product context before a payment redirect or embedded checkout changes domains. Store those values against the session, cart, or checkout so the purchase event can reuse the original context.

{
  "pixel_id": "t2_abc123",
  "event_at": "2026-04-23T10:18:22.000Z",
  "event_type": {
    "tracking_type": "AddToCart"
  },
  "event_metadata": {
    "value": 89.95,
    "currency": "USD",
    "item_count": 1,
    "conversion_id": "cart_10492_add_1"
  },
  "user": {
    "email": "sha256_lowercase_email",
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0...",
    "screen_dimensions": {
      "width": 1440,
      "height": 900
    }
  }
}
Step 3

Normalize user identifiers before hashing

Reddit can use deterministic first-party identifiers when consent and policy allow them. Normalize email by trimming and lowercasing before SHA-256 hashing. Normalize external_id to your stable customer or lead ID format, then hash it if your policy requires hashed transmission. Do not hash IP address, user agent, device advertising IDs, or screen dimensions because those fields are expected in their native formats.

import crypto from "node:crypto";

function sha256(value: string) {
  return crypto
    .createHash("sha256")
    .update(value.trim().toLowerCase())
    .digest("hex");
}

const user = {
  email: sha256("buyer@example.com"),
  external_id: sha256("cust_10492"),
  ip_address: "203.0.113.42",
  user_agent: "Mozilla/5.0..."
};
Step 4

Send purchase truth from the backend

For Purchase, Lead, SignUp, and other lower-funnel actions, use the system of record as the event source. The order service should decide final value, currency, item_count, conversion_id, timestamp, refund policy, and whether the event is eligible for Reddit. Avoid letting a browser confirmation page become the only source of revenue truth.

{
  "pixel_id": "t2_abc123",
  "event_at": "2026-04-23T10:24:16.000Z",
  "event_type": {
    "tracking_type": "Purchase"
  },
  "event_metadata": {
    "value": 129.95,
    "currency": "USD",
    "item_count": 2,
    "conversion_id": "ord_10492_purchase"
  },
  "user": {
    "email": "sha256_lowercase_email",
    "external_id": "sha256_customer_id",
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0...",
    "screen_dimensions": {
      "width": 1440,
      "height": 900
    }
  }
}
Step 5

Log responses and retry with the same conversion_id

Operate Reddit CAPI like revenue infrastructure. Store the request body, response status, response ID if present, conversion_id, token version, consent decision, identifiers present, and retry count. Retry transient network failures with backoff, but keep the same conversion_id. Replaying a purchase with a new ID makes diagnostics harder and can produce duplicate conversion candidates.

{
  "event": "reddit_capi_dispatch",
  "ad_account_id": "a2_abc123",
  "pixel_id": "t2_abc123",
  "tracking_type": "Purchase",
  "conversion_id": "ord_10492_purchase",
  "status": 200,
  "retry_count": 0,
  "identifiers_present": ["email", "ip_address", "user_agent", "rdt_uuid"]
}
Contract

Required fields

Reddit will not need every field on every event, but production payloads should be predictable. The table below is the practical contract for web and app events. Keep the same meanings across Reddit Pixel, CAPI, analytics, and backend logs so a rejected or duplicated conversion can be traced without guesswork.

FieldTypeRequiredPurposeExample
event_atISO stringYesTimestamp for when the conversion actually happened, not when a queue worker sent it.2026-04-23T10:24:16.000Z
event_type.tracking_typestringYesReddit event name used for optimization and reporting.Purchase
event_metadata.valuenumberFor purchasesRevenue value used in reporting and bidding signals.129.95
event_metadata.currencystringFor valueThree-letter ISO 4217 currency code.USD
event_metadata.item_countnumberRecommendedCount of items associated with the conversion.2
event_metadata.conversion_idstringRecommendedStable deduplication key shared by Reddit Pixel and CAPI.ord_10492_purchase
user.emailsha256 stringRecommendedHashed normalized email for deterministic matching.6b3a55e0261b...
user.external_idstringRecommendedStable customer, lead, or account identifier when available.sha256_customer_id
user.ip_addressstringRecommendedClient IP address from the browser request.203.0.113.42
user.user_agentstringRecommendedBrowser and device context used for validation and matching.Mozilla/5.0...
user.aaidstringApp trafficAndroid advertising ID for eligible app events.cdda802e-fb9c-47ad-9866-0794d394c912
user.idfastringApp trafficApple advertising ID when ATT and consent allow it.7D9B2B40-5E4D-4A25-A0F0-5A6C7E8D9012
user.screen_dimensionsobjectRecommendedClient viewport context with width and height.{ width: 1440, height: 900 }
Click identity

The rdt_uuid + _reddit_uuid2 cookies

Reddit's click and browser identifiers are the bridge between an ad interaction and a later server event. The Reddit Pixel can write first-party cookie values such as rdt_uuid and _reddit_uuid2 on your domain. When present, those values help Reddit connect CAPI events to the browser session that saw or clicked an ad. They are especially useful when the conversion happens after checkout moves to another domain or when the purchase is finalized by a backend webhook.

Capture these cookies early and attach them to the session or cart. Send the original values as context in your server event or internal dispatch envelope, depending on the exact connector you use. Do not fabricate them, do not hash them, and do not treat them as a replacement for eligible first-party identifiers like hashed email. They are strongest when paired with IP address, user agent, screen dimensions, and a stable conversion_id.

function readCookie(name: string) {
  return document.cookie
    .split("; ")
    .find((part) => part.startsWith(name + "="))
    ?.split("=")[1] || null;
}

await fetch("/api/cart/reddit-context", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    rdt_uuid: readCookie("rdt_uuid"),
    reddit_uuid2: readCookie("_reddit_uuid2"),
    user_agent: navigator.userAgent,
    screen_dimensions: {
      width: window.screen.width,
      height: window.screen.height
    }
  })
});
Deduplication

Dedup with Pixel

Deduplication prevents Reddit Pixel and CAPI from turning one action into two conversions. Generate one conversion_id per meaningful action, pass it to the browser event, and reuse the same value in the server payload. A readable convention is entity_action_result: cart_10492_add, lead_77821_submit, or ord_10492_purchase. The ID should be unique per action, stable across retries, and visible in diagnostics.

const conversionId = "ord_10492_purchase";

rdt("track", "Purchase", {
  conversionId,
  value: 129.95,
  currency: "USD",
  itemCount: 2
});

await fetch("/api/tracklayer/reddit-capi", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    event_at: new Date().toISOString(),
    event_type: {
      tracking_type: "Purchase"
    },
    event_metadata: {
      value: 129.95,
      currency: "USD",
      item_count: 2,
      conversion_id: conversionId
    },
    user: {
      email: sha256(normalizeEmail(customer.email)),
      ip_address: requestClientIp,
      user_agent: navigator.userAgent
    }
  })
});
Validation

Testing with Events Manager

1

Send one known browser and server pair

Trigger a Reddit Pixel event and a CAPI event from the same session with the same tracking_type and conversion_id. Use a realistic landing URL, consent state, user agent, and order value.

2

Inspect Events Manager diagnostics

Confirm the event reaches the correct pixel and ad account. Review rejected fields, token errors, stale timestamps, malformed metadata, missing identifiers, and domain verification warnings.

3

Compare reporting after processing

Wait for Reddit processing before judging attribution. API acceptance proves delivery, while reporting needs matching, deduplication, attribution window eligibility, and campaign activity.

Policy

Consent Mode handling

Reddit's EU consent handling is more limited than Google Consent Mode, so do not assume the platform can model around a denied signal in the same way. Your tracking layer should decide whether Reddit receives the event, which identifiers are removed, and whether browser Pixel and server CAPI are treated symmetrically. If advertising storage or ad measurement is denied, suppressing the destination is often cleaner than sending a nearly anonymous purchase that your legal and media teams interpret differently.

A durable pattern is to capture consent at the event edge, store it with the order or lead event, and evaluate Reddit routing just before dispatch. Internal analytics can still retain operational purchase truth, while Reddit receives only events and identifiers that match the user's region, CMP decision, and your policy.

Diagnostics

Troubleshooting

401 or 403 authentication errors

Regenerate the conversion_access_token from Reddit Ads Manager and confirm it has access to the ad account in the endpoint and the pixel_id in the payload.

Events accepted but not visible

Check pixel_id ownership, domain verification, event_at freshness, processing delay, and whether you are looking at the same ad account used in the API path.

Duplicate purchases

Generate conversion_id once per action and reuse it for both Pixel and CAPI. Do not let the browser, backend, and retry job mint different IDs.

Low match or attribution quality

Preserve rdt_uuid and _reddit_uuid2, add permitted email or external_id, forward the true client IP and user agent, and suppress placeholder identifiers.

Invalid event metadata

Send value as a number, currency as an ISO code, item_count as a number, and tracking_type as one of Reddit's supported event names.

FAQ

Common questions

Can Reddit CAPI replace the Reddit Pixel?

Usually no. The Pixel captures browser context, retargeting audiences, and immediate interaction signals. CAPI strengthens delivery and conversion truth, especially after redirects or blockers. The most reliable setup runs both and deduplicates them.

Which event types should I start with?

Start with PageVisit, ViewContent, AddToCart, Lead, SignUp, and Purchase if those actions exist on your site. Avoid sending low-quality backend noise until the lower-funnel events are accepted and deduplicated.

Do I need both rdt_uuid and _reddit_uuid2?

Capture both when present because cookie behavior can vary by Reddit Pixel version, browser state, and traffic source. Do not invent these values. If the cookies are absent, send other eligible identifiers and context.

Should I hash IP address or user agent?

No. Hash normalized personal identifiers such as email when required. Send IP address, user agent, device advertising IDs, click identifiers, and screen dimensions in the format Reddit expects.

How long should I keep event logs?

Keep enough history to diagnose attribution and replay failures across your refund, attribution, and reporting windows. For most teams, 30 to 90 days of request and response logs is the minimum useful range.

Next reads

Related implementation guides

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.