Skip to content

BlogHow To Guides

Reddit Conversions API: Setup, Deduplication and CRM Events

The Reddit Pixel reports what a browser lets it see. The Conversions API reports what your server tells it, including stages that happen in the CRM after the form. The v3 endpoint and body, the access token, match keys and hashing, deduplication against the Pixel, the click ID you have to keep yourself, test mode, limits, and what Reddit will credit from a CRM.

Reddit Conversions API: a CRM stage sent server to server to Reddit Ads with the click ID and a conversion ID
Contents
  1. Quick summary
  2. Pixel vs CAPI
  3. Four ways to connect
  4. Token and Pixel ID
  5. The v3 request
  6. Match keys
  7. Click ID persistence
  8. Deduplication
  9. Testing and limits
  10. CRM events
  11. Stage mapping
  12. v2 vs v3
  13. How LeadJourney does it
  14. Further Reading
Summarise this article with AI

Opens the page with a ready prompt in:

Nothing is sent until you pick a service.

The Reddit Pixel sees what happens in a browser that lets it run. Ad blockers, browser restrictions and a thank-you page that never finishes loading all take events out of it, and it cannot see anything that happens after the visitor leaves your site: the lead your sales team qualified on Tuesday, the deal that closed in the CRM three weeks after the click.

The Conversions API is Reddit's server to server path for those events. This is the reference for building it: the v3 endpoint and the body it expects, the token, the fields that are required and the ones that decide your match rate, deduplication against the Pixel, the click ID you have to keep yourself, test mode and limits, and what Reddit will and will not credit when the event comes from your CRM.

Quick Summary: The Reddit Conversions API

In short

The Reddit Conversions API is one endpoint, POST https://ads-api.reddit.com/api/v3/pixels/{pixel_id}/conversion_events, called from your server with a conversion access token from Events Manager. Every event needs event_at in epoch milliseconds, an action_source and a tracking type; the rest (the rdt_cid click ID, email, phone, IP, user agent, value, a conversion ID) is optional and decides how many events Reddit can match. Reddit recommends running it next to the Pixel and deduplicating the two on a shared conversion ID. Events have to reach Reddit within seven days of happening and Reddit's longest click window is 28 days, so a CRM deal that closes two months after the click is never credited in Ads Manager, however well it is sent.

So the Conversions API is the right pipe for everything after the form, with one caveat: it rewards stages that happen soon after the click. The sections below follow the build in the order you would do it, then deal with CRM events and what they can and cannot achieve.

What the Conversions API Adds to the Reddit Pixel

The Pixel is JavaScript in the head of your pages. It reads the rdt_cid click ID from the landing page URL, keeps a first-party _rdt_uuid cookie and sends each event from the visitor's browser. Whatever stops the script stops the event. Reddit describes the Conversions API as a secure server to server connection and says server-side connections are "more resilient to signal loss". Your backend, your CRM or a tracking platform posts the event, and the conversion does not have to happen on your website at all.

  • Reddit Pixel

    Browser JavaScript. Page visits, on-site events, retargeting audiences. Picks up the click ID by itself. Loses whatever the browser blocks.

  • Conversions API

    Server to server events from your backend or CRM. Nothing runs in the browser, and the event can describe something that happened days later.

  • Both together

    What Reddit recommends "for best performance". The same conversion sent twice has to be deduplicated, and Reddit keeps the copy with more data.

Deduplication is only needed for events that travel both ways. If the Pixel sends PageVisit and AddToCart and the server sends Purchase alone, Reddit says there is nothing to deduplicate. The browser side is its own job: the Reddit Pixel setup guide covers the base code, Google Tag Manager and Shopify, and Reddit conversion tracking shows how the two fit into one system.

Four Ways to Send Events to the Reddit Conversions API

Reddit lists three routes: a direct integration, Google Tag Manager and supported partners. Tag Manager comes in two shapes, so in practice there are four. The API underneath is the same in every case; what differs is who maintains the connection and what it knows when the event is built.

  • A direct integrationYour server posts to the endpoint. Reddit recommends it "if you want more flexibility and control of your data" and says it needs in-house developer resources. You own the token, retries, hashing and the click ID storage.
  • Reddit's official server GTM tag"Reddit Conversions API", published by Reddit for server containers, with fields for the access token, the event source, a test ID, the conversion ID, advanced matching and Limited Data Use. It keeps the click ID in a _rdt_cid cookie for 90 days.
  • The Ads Manager GTM flowConfigure Source > Conversions API > Google Tag Manager links your GTM account and publishes the containers for you. It needs a web container, a server container provisioned on your Google Cloud billing and a GA4 measurement ID, and maps standard gtag events such as generate_lead, sign_up and purchase.
  • A listed partnerActionIQ, Adobe through Event Forwarding, Census, Elevar, Hightouch, MetaRouter, mParticle, Rudderstack, Segment, Tealium and the WooCommerce plugin, per Reddit's partner list.

Three details decide more projects than the choice of route. Reddit's Shopify app does not send Conversions API events: it is a codeless pixel plus catalog sync, and Reddit's own help article says "The Reddit Conversions API (CAPI) isn't supported" through it. The WooCommerce plugin shares events through both the Pixel and CAPI by default. And Stape maintains its own v3 tag for server GTM, but Stape is not on Reddit's partner list, and neither are Zapier or LeadsBridge.

Offline sources need a direct or GTM integration

Events whose action_source is not WEBSITE (an app, a physical store, anything else) are supported through direct and GTM integrations only. Reddit says "File upload and partner integrations are not." Reddit documents no CSV upload of offline conversions in Ads Manager: the Conversions API is the documented route.

Step 1: The Pixel ID and a Conversion Access Token

Two values before any code. The Pixel ID is in Events Manager and names the account that receives the events; Reddit's Pixel Helper validates it as t2_ or a2_ followed by characters, which is why older guides call it an account ID. The token is a bearer token with the adsconversions scope, and Reddit recommends a conversion access token over a developer access token because it does not expire.

  1. In Ads Manager, open Events Manager > Conversions API and select Generate Access Token. Only business admins can do this.
  2. Give the token a name that says which system uses it, so the right one can be deleted later.
  3. Select Generate and copy the value. Reddit shows it once: after the pop-up closes it cannot be retrieved, only replaced.
  4. Store it as a secret on the server that sends events. It belongs in an environment variable or a secret store, never in page code.

A business can hold up to 25 conversion access tokens, and any Pixel in that business accepts them. Deleting a token revokes access for everyone using it, so one token per sending system makes a rotation painless. A bearer token you already used for v2 stays valid for v3.

Step 2: The v3 Request, Field by Field

One endpoint per Pixel, the events wrapped in a data object, up to 1,000 events per call. Here is a single Lead event carrying every match key a web form can supply. Values in angle brackets are placeholders; 1790605800000 is 28 September 2026, 14:30 UTC, in epoch milliseconds.

HTTP request, Conversions API v3 (placeholders in angle brackets)
POST https://ads-api.reddit.com/api/v3/pixels/<PIXEL_ID>/conversion_events
Authorization: Bearer <CONVERSION_ACCESS_TOKEN>
Content-Type: application/json
User-Agent: <YOUR_OWN_DESCRIPTIVE_USER_AGENT>

{
  "data": {
    "test_id": "<TEST_ID_FROM_EVENT_TESTING>",
    "events": [
      {
        "event_at": 1790605800000,
        "action_source": "WEBSITE",
        "type": {
          "tracking_type": "LEAD"
        },
        "click_id": "<RDT_CID_FROM_THE_LANDING_PAGE_URL>",
        "event_source_url": "https://www.example.com/demo",
        "user": {
          "email": "<EMAIL_PLAIN_OR_SHA256>",
          "phone_number": "<E164_PHONE_PLAIN_OR_SHA256>",
          "external_id": "<YOUR_OWN_USER_ID>",
          "ip_address": "<VISITOR_IP_NOT_SERVER_IP>",
          "user_agent": "<VISITOR_BROWSER_USER_AGENT>",
          "uuid": "<_rdt_uuid_COOKIE_VALUE>"
        },
        "metadata": {
          "conversion_id": "<SAME_ID_AS_THE_PIXEL_CONVERSIONID>"
        }
      }
    ]
  }
}

Two user agents appear in that request and they are not the same thing. The header is your server's, and Reddit says default user agents may be throttled, so give it a unique, descriptive string. The user_agent field is the visitor's browser, one of the match keys. Delete test_id before production traffic.

Required on every event

  • event_at: when the conversion happened, as an integer in Unix epoch milliseconds. The time of the stage change, not the time your job ran.
  • action_source: WEBSITE, APP, PHYSICAL_STORE or OTHER. Required in v3, and it decides which Pixel events a server event can be deduplicated against.
  • type.tracking_type: PAGE_VISIT, VIEW_CONTENT, SEARCH, ADD_TO_CART, ADD_TO_WISHLIST, PURCHASE, LEAD, SIGN_UP or CUSTOM. CUSTOM also needs type.custom_event_name, free-form, case sensitive, up to 64 characters.

Optional, and where the match rate comes from

Optional fields on a Reddit Conversions API v3 event

A valid call answers with a short message such as "Successfully processed 1 conversion events." A call containing invalid events is rejected whole: Reddit's error reads that there were invalid conversion events and "None were processed". Validate before you batch, or one malformed row costs you the other 999.

Match Keys and Hashing

Reddit has to find the Redditor behind every server event, and each identifier you send is a match key. Its pages phrase the minimum differently. The direct integration guide says "At least email + phone number is recommended". The best practices page strongly recommends the IP address and the click ID, suggests email, phone and user agent, adds the UUID when the Pixel runs too, and asks for an external ID unique to one user. Read together: send everything you legitimately have.

  • The click ID (rdt_cid)The identifier of the ad click itself. Reddit says it helps attribute click conversions more accurately. The Pixel sends it on its own; on the server you have to have kept it, see the next section.
  • EmailPlain or SHA-256. To hash it yourself: lowercase, remove the dots and anything after a plus sign in the local part, then SHA-256 as 64 lowercase hex characters. [email protected] and [email protected] then hash to the same value.
  • Phone numberE.164 with the country code, the extension removed, every non-digit removed and a leading plus, so +1 (555) 444-1234 becomes +15554441234 before hashing.
  • IP address and user agentThe visitor's, not your server's. Reddit says IP addresses sent through the Conversions API must be client IPs, and that device signals help it attribute view conversions.
  • UUID and external IDThe _rdt_uuid cookie value when the Pixel runs, and your own ID for the person. Either one on every event is also what session based deduplication needs.

Badly formatted values are accepted with a warning in Events Manager rather than refused, which is exactly why they go unnoticed. Automated advanced matching, the Events Manager setting that picks email and phone off your forms, only feeds the Pixel; on the server you send the keys yourself.

The match quality score

Events Manager scores each event type from 0 to 10, computed from how often each key is present, a quality adjustment and a weight per key. It is recalculated on the last seven days and needs at least 100 events in that period to show at all. It is Reddit's version of event match quality, and the fastest way to see a missing key.

Keeping the rdt_cid Until the Event Is Sent

Reddit appends rdt_cid to your landing page URL on every ad click, automatically. The Pixel reads it from there and shares it by itself. The Conversions API cannot read a URL: Reddit's click ID guide says the advertiser has to persist the value and send it as click_id, and that landing pages must preserve URL parameters through redirects. Reddit lists six ways to keep it and recommends combining them.

  • The URL itself, for simple sites where the parameter can stay visible.
  • A cookie set on the first page load, for multi-page sites. Reddit notes it needs cookie consent and fails when cookies are off.
  • localStorage or sessionStorage, the first surviving between sessions, the second until the tab closes.
  • A hidden form field, so the click ID reaches your server with the submission.
  • The server session, for sites that already keep one.
  • A JavaScript variable, which lasts for the current page view only.

For a web event sent seconds after the form, any of these works. For a CRM event only one does: the click ID has to be on the lead record, because the event is built from the CRM weeks later and no browser is involved any more. A hidden field that writes rdt_cid into a CRM property is the minimum. It fails for the visitor who clicked the ad on Monday and filled in the form on Thursday from a bookmark: the URL no longer carries the parameter, and a sessionStorage value closed with the tab. A first-party value set at the first visit and read by the form closes that gap for as long as it lives.

Reddit's own check is simple. Open a test URL for your ad (test URLs behave like real ads, charges included), confirm the rdt_cid is in the landing page URL, and compare it with data.events[].click_id in the event your server sends. Tealium and the Ads Manager GTM flow pass the click ID automatically. The URL side of this, including why a redirect or a tracker can drop it, is in Reddit Ads UTM parameters.

Deduplication: Conversion ID or Session

When the Pixel and the server both report the same lead, Reddit has to count it once. Its deduplication runs every hour and can take up to 24 hours after both copies arrive. Events must be sent within two days for it to work, both copies must be the same event type (and the same name for custom events), and it only happens within one channel: Pixel events are website events, so they are only deduplicated against server events whose action_source is WEBSITE. The copy with more metadata and match keys is kept.

  • Conversion ID (recommended)

    The same string in the Pixel's conversionId and in metadata.conversion_id on the server. Always preferred when present. One per conversion: an order number, a lead ID, or a hash of the event's own attributes.

  • Session based (the default)

    Used when no conversion ID is sent. Needs a UUID or an external ID on every Pixel and server event. A session is events no more than five minutes apart, and Reddit keeps one source per session.

The same conversion ID on both sides (placeholder ID)
// In the browser, when the form is submitted
rdt('track', 'Lead', { conversionId: '<LEAD_ID>' });

// On the server, in the same conversion's event
"metadata": { "conversion_id": "<LEAD_ID>" }

That is the setup we run on our own demo form: the Pixel fires one Lead with the lead's ID as conversionId, the server sends the same Lead with the same ID, and Reddit counts it once. The one way to break it is reuse. Reddit warns that a conversion ID passed to too many events marks them all as duplicates, and they are then not attributed at all.

Check the result in Events Manager. Its activity counts are before deduplication and split by Pixel and Conversions API. The deduplication panel shows source coverage (the share of events carrying a conversion ID) and a deduplication rate updated hourly; Reddit calls a rate "around 50% within a margin of error" healthy, with the server typically reporting slightly more events than the Pixel.

Step 3: Test Mode, Limits and What Rejects an Event

Send test events before a single production call. In Events Manager's Event Testing, copy the test ID into data.test_id and fire an event. Test events are limited to ten per second, a batch shows only one of its events, and an event can take up to five seconds to appear. Reddit says to remove test_id before production traffic.

  • Rate limits1,000 events per request, 1,000 requests and 10,000 events per second. Too many events in one call returns a 400, too many calls a 429. Reddit's advice for the second is batching and retries with exponential backoff.
  • Rejected event typesReddit rejects an event type once 10% of it shows issues: an unsupported event, an invalid click ID or UUID, a missing action source, an invalid event time, invalid screen dimensions or an invalid IP address.
  • Silence warningsEvents Manager warns when a Conversions API event has not arrived for 48 hours, against six hours for the Pixel. A broken CRM job shows up here first.
  • Last fired atGET /pixels/{pixel_id}/last_fired_at returns when conversion events last arrived, in ISO 8601. Useful for monitoring a job without opening the interface.

Give reporting time as well. Reddit says conversion metrics can take up to three hours to show on the dashboard, and events sent through its GTM integration post within three hours. A test that shows nothing after five minutes is not yet a failed test.

Sending CRM Events: What Reddit Will and Will Not Credit

This is where the Conversions API earns its place, and where most expectations break. Four documented limits decide what an event built from your CRM can do inside Reddit.

  • Seven days to send

    "Events must be sent within seven days after they occur." event_at is the stage change, so send as the stage changes. A monthly backfill of last month's deals is too late.

  • 28 days to be credited

    Reporting runs on the account's window, 28-day click plus 1-day view by default, each window 1, 7 or 28 days. A deal won 60 days after the last Reddit click is not credited, however it is sent.

  • Seven days to optimise

    Delivery optimises on a separate window set on the campaign or ad group: 7-day click, or 7-day click plus 1-day view, fixed once published.

  • Custom events are reporting only

    Conversion goals are Purchase, Lead, SignUp, Add to Cart and Page Visit (Clicks without a Pixel or CAPI). A custom event cannot be one, and a goal cannot change once the ad group is saved.

Two more facts shape the reading. Reddit dates a conversion to the day of the click or view, not the day it happened, so a deal that closes on day 20 raises the numbers of a day three weeks back. And a new ad group needs around 20 optimisation events to leave the learning phase, so the stage you optimise on has to arrive often, and within a week of the click.

The honest plan follows from that. Send an early stage that predicts revenue, usually the qualified lead, as the optimisation signal. Send the won deal as a Purchase with its value for the deals that close inside the window. Read the long tail in your own attribution tool, because Reddit's reporting was never going to see it. The window mechanics and the gap to GA4 and the CRM are covered in Reddit Ads attribution, and attribution for a long sales cycle shows the reporting shape that holds up.

Nobody can promise a month four deal in Ads Manager

Not an agency, not a connector, not us. The event reaches Reddit, the click is outside every window Reddit offers, and the campaign gets no credit. The deal is still real, and it still belongs to the Reddit click that started it: that answer lives in a system without a window.

Which CRM Stage Becomes Which Reddit Event

Reddit publishes no article on CRM stages. What exists are the standard events and custom events, with the limits above, so the mapping is your decision. One shape that respects every constraint:

  • The form fillSignUp or Lead, sent by the Pixel and the server with one shared conversion ID. The volume number, useful to diagnose, weak as a goal.
  • The qualified leadLead, when the form fill is SignUp, or a custom event if you keep Lead for the form. The best optimisation goal when it happens inside a week of the click, often enough.
  • The won deal or paid orderPurchase, with value and currency. Reddit then reports Purchase ROAS, total value over spend, for the deals that close inside the window.
  • Every other stageMeeting booked, proposal sent: custom events for reporting. Only the 20 most recent custom event names are visible in Events Manager and reporting.

The trap is the obvious mapping. Send the form fill as Lead and the qualified stage as Lead too, and every qualified lead counts twice: the two events carry different conversion IDs, so Reddit sees two Leads from one person and your cost per lead drops on paper. Give each event type one meaning.

The action source of a CRM event

action_source says where the conversion happened: WEBSITE, APP, PHYSICAL_STORE or OTHER. All sources feed one optimisation, metrics can be broken down by source, and deduplication only happens within a source. For offline events Reddit's guidance is hashed email and phone and no click ID, UUID or device identifiers; an external ID helps across all sources. Reddit does not say which source a CRM stage of a lead that started on your website should carry, so decide once per event type, write the decision down, and keep it.

Sending the qualified lead instead of the form fill, and what the platform does with it.4:35 minutes

Still on v2? What Changed in v3

Reddit released the v3 Post Conversion Events operation on 1 October 2025. The v2 Ads API is deprecated and every v2 endpoint except the Conversions API has been sunset; Reddit says support for CAPI v2 will continue and publishes no shutdown date. A v2 integration still works. New features such as event_source_url are v3 only.

Reddit Conversions API v2 against v3

Do not send the same events to both versions: Reddit strongly discourages it, because it may count the event twice. It recommends moving production traffic over in percentages, and a bearer token issued for v2 keeps working, so the migration is a payload change rather than a new setup.

How LeadJourney Sends CRM Stages to the Reddit Conversions API

The hard part of all this is not the POST request. It is holding a Reddit click ID from an anonymous first visit until a CRM stage changes weeks later, in a system that also knows the stage. That is LeadJourney's normal job. One script on your site or in your GTM container, live in about 21 minutes without a developer, tracks server-side and first-party at 95%+ accuracy. On the first visit it issues the LeadJourney Click ID, its own visitor identifier, kept in the browser for months, and stores every session under it. The platforms' click IDs, gclid, fbclid, msclkid, li_fat_id and now rdt_cid, are stored on that record as properties of the session they arrived with.

The Reddit Ads integration connects your Reddit Ads account, imports campaigns, ad groups, ads and daily spend, captures the rdt_cid on every Reddit click server-side and follows the lead through your CRM. HubSpot, Salesforce, Microsoft Dynamics 365, Zoho CRM, Pipedrive, Attio, Close, GoHighLevel, ActiveCampaign and Odoo connect natively, anything else by webhook, Zapier or the open API, and Shopify and Stripe natively for orders and payments. It then sends the CRM stages you map, for example a qualified lead as a Lead event and a won deal or a paid order as a Purchase with its value, back through Reddit's Conversions API with the value, the click ID, hashed email and phone, and a conversion ID that deduplicates against a running Reddit Pixel.

It does not change Reddit's windows. A deal that closes after Reddit's 28 days still does not appear in Ads Manager. It does appear in LeadJourney, whose reports carry no attribution window: the journey runs from the first click to closed won however long that takes, under first click, last click, linear, position based, time decay and the other models, switched without re-tracking. Data is processed in Frankfurt under a GDPR data processing agreement.

Read verified reviews on Trustpilot, G2 and leadjourney.io/testimonials.

Further Reading

FAQ

Frequently Asked Questions

What teams ask before they point a server at Reddit.

What is the Reddit Conversions API?

Reddit's server to server endpoint for conversion events. Instead of a script in the visitor's browser, your server, CRM or tracking platform posts each event to https://ads-api.reddit.com/api/v3/pixels/{pixel_id}/conversion_events with a conversion access token. Reddit describes it as more resilient to signal loss than the browser, and the event can describe something that happened after the visit, such as a qualified lead or a paid order.

Where is the Reddit Conversions API documentation?

In two places. Reddit's developer docs at ads-api.reddit.com/docs/v3 have a Conversions API section with guides for the direct integration, click ID persistence, verifying events, error handling, the v2 to v3 migration and best practices, and the published OpenAPI spec lists every field. The Reddit Ads Help Center covers the business side: the conversion access token, deduplication, match keys and Events Manager.

Do I still need the Reddit Pixel if I use the Conversions API?

Reddit recommends running both "for best performance". The Pixel picks up the click ID and the UUID by itself and covers browsing events; the Conversions API covers what the browser loses and what happens after the visit. When both send the same conversion, give it one conversion ID on both sides so Reddit counts it once.

Do I have to hash email addresses before sending them?

No. Reddit accepts email and phone either plain or hashed with SHA-256, and normalises and hashes plain values itself. If you hash them yourself, canonicalise first: lowercase the email and remove dots and anything after a plus sign in the local part, and write phone numbers in E.164 with a leading plus. A value hashed without that step will not match.

How do I stop Reddit counting a conversion twice?

Send the same conversion ID in the Pixel's conversionId and the server event's metadata.conversion_id, as the same event type, within two days, with action_source WEBSITE on the server copy. Reddit then keeps the copy with more data. Without a conversion ID it falls back to session based deduplication, which needs a UUID or an external ID on every event.

Can I send CRM deals to Reddit, and how far back?

Yes, as Purchase events with a value, or as other standard or custom events. Events must be sent within seven days of the stage change, so send them as they happen; last month's deals cannot be backfilled. Reddit also only credits conversions inside its click window, 28 days at most, so a deal that closes later than that is sent but never credited in Ads Manager.

Is Reddit's Conversions API v2 still working?

Yes. The v2 Ads API is deprecated and every other v2 endpoint has been sunset, but Reddit says support for CAPI v2 will continue and has published no shutdown date. New features such as event_source_url are v3 only, and Reddit strongly discourages sending the same events to both versions during a migration.

Does the Reddit Shopify app send Conversions API events?

No. Reddit's help article for the Shopify app says the Conversions API is not supported through it: the app is a codeless pixel plus catalog sync. For server events from a Shopify store you need a direct integration, a Google Tag Manager server container, a listed partner or a platform that sends them for you.

Reddit pipeline

Ready to send Reddit the deals, not just the form fills?

LeadJourney keeps the Reddit click ID from the first visit, follows every lead through your CRM and sends the stages you map back through the Reddit Conversions API, deduplicated against your Pixel. Live in 21 minutes, with a 14-day free trial.

LeadJourney dashboard showing lead sources, campaign performance and attributed revenue side by side