RekomiRekomiBlogPricing
Rekomi Docs
Rekomi Docs
Welcome to Rekomi
Quickstart for brandsPlans and trialsIntegrationsStripe Connect (sales tracking)Organization settingsTeam managementNotifications
Install tracking

Payment platforms

Install on StripeStripe Marketplace appInstall on PaddleInstall on BraintreeInstall on ShopifyInstall on Lemon SqueezyInstall on ChargebeeInstall on PolarInstall on RecurlyInstall on GumroadInstall on CreemInstall on Dodo PaymentsS2S API (any gateway)

Membership and course platforms

Install on MemberstackInstall on OutsetaInstall on PodiaInstall on TeachableInstall on Thinkific

Newsletter and creator platforms

Install on GhostInstall on beehiivInstall on Kit (ConvertKit)

Site builders

Install on WordPressInstall on WebflowInstall on FramerInstall on SquarespaceInstall on WixInstall on BubbleInstall on Carrd

Frameworks

Install on Vanilla JavaScriptInstall on Next.js App RouterInstall on Next.js Pages RouterInstall on React (Vite, CRA, Remix)Install on VueInstall on RailsInstall on Django

Campaigns and commissions

CampaignsCommission modelsPay per click or lead (CPC & CPL)Coupon-code attributionSub-affiliate recruitingTracking and attribution

Affiliates

Recruit affiliatesManage affiliatesAI co-pilotApply to the curated network

Money flow

SalesPayoutsMulti-currencyTax formsReports

Email

Sending domainBroadcasts
For brandsInstall tracking
|Brands|

Install on Gumroad

Connect Gumroad natively: click Connect, approve once on Gumroad's consent screen, and Rekomi registers the sale, refund, dispute, and membership notifications for you. Sales, renewals, refunds, and disputes are tracked automatically; ?rekomi_ref on the product link carries the referral.

Gumroad logo

Gumroad is a Merchant of Record for digital products and memberships, and Rekomi supports it natively with the simplest connect flow of any rail: one click. You press Connect Gumroad, approve Rekomi once on Gumroad's consent screen (read-only sales access), and Rekomi registers the sale, refund, dispute, and membership lifecycle notifications in your Gumroad account itself. There is no Ping URL to configure, no webhook to paste, and no relay code to write or maintain. Still evaluating? See Why Rekomi for Gumroad →.

Connect in Rekomi

Step 1. Go to /dashboard/setup/gumroad and click Connect Gumroad. You are sent to Gumroad's consent screen, which asks only for read-only sales access (view_sales).

Step 2. Approve. You land back in Rekomi already connected: Rekomi resolves your seller identity and registers six resource subscriptions in your Gumroad account (sale, refund, dispute, cancellation, subscription_ended, subscription_restarted). The setup page lists them as chips so you can see all six are live.

Advanced fallback: paste an access token. If the button flow is unavailable to you, the setup page has a collapsed "Advanced" section that accepts an access token from an application you create in Gumroad (Settings > Advanced > Applications). Know the trade-off: a token created that way grants access to your entire Gumroad account, not just sales, which is why the Connect button (scoped to view_sales only) is the recommended path. Either way the token is stored encrypted and never shown again.

Connecting is Owner-only in Rekomi, and reconnecting at any time is safe: Rekomi cleans up its old registrations and rotates your webhook credentials automatically.

Attribution: the rekomi_ref link param

Gumroad hosts its checkout on its own domain, so the affiliate referral travels as a query parameter on the product link: ?rekomi_ref=AFFILIATE_SLUG. Gumroad preserves the landing URL's query parameters onto the sale notification, which is how Rekomi knows which affiliate drove the sale.

  • Affiliate links generated by Rekomi carry the parameter automatically. If your campaign links point straight at your Gumroad product pages, there is nothing to do.
  • Sending buyers to Gumroad from your own marketing site? Install the Rekomi head script there (your site platform's recipe in the install hub covers it) and decorate your Buy links:
// Decorate Gumroad product links with the captured referral
const ref = window.Rekomi?.getReferral?.();
const url = new URL("https://yourname.gumroad.com/l/your-product");
if (ref) url.searchParams.set("rekomi_ref", ref);
// use url.toString() as the href on your Buy button

Renewals never carry the link parameter. Gumroad's recurring membership charges arrive without url_params, so Rekomi credits them from the customer's first attributed sale automatically (the customer-history match every native rail uses for renewals).

What gets tracked

  • Sales. One-time purchases and first membership charges record as one-time conversions; recurring membership charges record as recurring conversions for the same affiliate. Gumroad settles every charge in US dollars, so amounts are always USD.
  • Refunds. A full refund claws the commission back in full, automatically. Partial refunds do not reduce commissions automatically: Rekomi records that the partial refund happened but leaves the commission intact for you to adjust if it matters. A series of partial refunds that reaches 100% claws back once, in full.
  • Disputes. A chargeback claws the commission back like a full refund.
  • Membership lifecycle. Cancellations, ended subscriptions, and restarts are tracked as subscription events, so churn-aware reporting and recurring commissions stay correct (a restarted membership resumes crediting the original affiliate).
  • Test purchases. Gumroad flags a seller's own test purchases, and Rekomi deliberately records them as connection checks, not commissions: a test purchase updates "last event" on the setup page so you can verify the pipe end to end without creating money. Free-trial starts ($0 sales) create no conversion either; the first real charge does.

How Rekomi authenticates Gumroad's notifications

Stated plainly: Gumroad does not sign its webhook notifications. There is no signature to verify, so Rekomi authenticates deliveries with layered checks instead:

  • Your notifications arrive on a per-workspace secret URL that Rekomi registered at Gumroad. Treat it like a password: the dashboard shows it to workspace Owners only, and it rotates on every reconnect.
  • Every delivery is bound to your seller identity; events for any other seller are rejected.
  • For every money event (sale, refund, dispute), Rekomi reads the sale back from Gumroad's API with your token and records amounts from that authoritative read, never from the raw notification, cross-checking the identifiers along the way. A notification that fails the readback is rejected.

The readback means money is only ever recorded after Gumroad's own API confirms the sale exists and matches. It also means the connection's access token is load-bearing for tracking: if it is revoked, tracking stops (see connection health below).

Delivery is lossy: gaps and backfill

Gumroad retries a failed delivery only a handful of times inside roughly 14 minutes, and only when your endpoint answers with specific server errors; a delivery that times out or fails to connect is dropped without retry. Rekomi's handler is built to answer well inside Gumroad's delivery window, but if Rekomi or Gumroad's API is unreachable for longer than the retry ladder, a sale in that window can be missed.

The fix is the sales-history importer as a backfill lane: open Settings > Migrate, pick Gumroad, and run the Step 2 sales pull with From set to the gap's start date. Your connected account's token is used automatically, and re-running is safe (already-recorded sales are skipped as duplicates). One caveat: sales refunded or charged back inside the gap window are skipped by the importer (that money was clawed at Gumroad), so review those manually if any commissions from the gap need reversing.

Import your existing Gumroad affiliates and history

Migrating an existing Gumroad affiliate program? The importer is two steps:

  1. Roster CSV. Gumroad's dashboard exports your affiliates list (exports over 500 affiliates arrive by email). Upload it under Settings > Migrate. Gumroad /a/ affiliate links cannot carry over (their opaque ids only route inside Gumroad), so imported affiliates get fresh Rekomi links; each affiliate's fee percentage and product scope land in the per-row import notes.
  2. Sales history via API. After the roster completes, pull each affiliate's past sales directly from Gumroad's API. History imports as settled records (Gumroad paid its affiliates biweekly), so stats and recurring attribution carry over but nothing becomes payable and balances are never retro-credited.

The full guide is Migrating from Gumroad.

Quirks worth knowing

  • One conversion source per workspace. Gumroad Connect is mutually exclusive with Stripe Connect, Paddle, Braintree, Shopify, Lemon Squeezy, Chargebee, Polar, Recurly, Creem, Dodo Payments, and the S2S API, so the same sale is never counted twice. Disconnect one before connecting another.
  • Gumroad's own marketplace affiliates keep working. Gumroad ships a built-in affiliates feature; connecting Rekomi does not touch it. Run both side by side, or wind the built-in one down; Rekomi adds cross-platform affiliate accounts, approval and anti-fraud controls, and real payout rails on top.
  • Access tokens do not expire, but revocation is silent. Revoking the Rekomi app in Gumroad kills the token AND silently stops the notifications. Rekomi's health check probes the connection periodically and flags it broken (with a reconnect email) when that happens; the dashboard also shows a persistent reconnect banner.
  • Disconnect cleans up remotely. Disconnecting deletes the six resource subscriptions in your Gumroad account and wipes the stored token. Reconnecting mints fresh credentials; the old webhook address stops working.

Test the install

Make a test purchase of one of your products with ?rekomi_ref=test on the link (or use Gumroad's test purchase flow as the seller). The delivery shows up as "last event" on /dashboard/setup/gumroad within a minute; seller test purchases verify the pipe without creating a commission. Then have a real purchase ride an approved affiliate's link and confirm the conversion on the campaign's Activity tab.

Troubleshooting

"Connection needs attention" banner or reconnect email. The Rekomi app's access was revoked in Gumroad (which also silently stops notifications), or the sale notification registration disappeared. Click Connect Gumroad again; reconnecting re-registers all six feeds and rotates credentials. Tracking history is preserved.

Sales arrive but no affiliate is credited. The sale reached Rekomi but carried no rekomi_ref. Check the link the buyer used actually had ?rekomi_ref=SLUG on the Gumroad product URL, the slug belongs to an approved affiliate, and (for links from your own site) the head script ran before the buyer clicked through. Renewals are credited from the customer's first attributed sale, so an unattributed first sale means unattributed renewals too.

A sale is missing entirely. Check the Gumroad connection is healthy on the setup page, then run the backfill pull (Settings > Migrate > Gumroad > Step 2) for the affected date range; Gumroad drops timed-out deliveries without retrying, so extended downtime windows need the backfill.

Legacy: Ping URL relay (S2S)

Before the native connection, Gumroad tracking ran through a self-hosted relay: Gumroad's Ping URL POSTs each sale to a handler you run, and your handler forwards it to Rekomi's S2S endpoint with an HMAC signature. The recipe remains here for sellers who have not connected Gumroad natively; if you can use the Connect button, prefer it (no infrastructure, plus refunds, disputes, and membership lifecycle included).

In Gumroad, open Settings > Advanced > Ping URL and point it at a handler on your backend. Gumroad does not sign pings, so protect the inbound leg with a shared secret in the URL (and/or IP-allowlisting); the HMAC below protects your relay's call to Rekomi, not Gumroad's call to you. This legacy relay reads the historical ?via= parameter; the native rail's canonical parameter is rekomi_ref.

// Node example with express
const express = require('express');
const crypto = require('crypto');

app.post('/webhooks/gumroad', express.urlencoded({ extended: true }), async (req, res) => {
  // 1. Verify shared secret (or IP allowlist at the edge).
  if (req.query.secret !== process.env.GUMROAD_SHARED_SECRET) {
    return res.sendStatus(401);
  }

  const sale = req.body;

  // 2. Pull the affiliate slug from url_params[via]. Gumroad nests the original URL query
  //    under url_params; extended: true makes urlencoded parse the nested keys.
  const referral = sale.url_params?.via || sale.url_params?.ref || sale.url_params?.fpr;
  if (!referral) return res.sendStatus(200); // No affiliate involved.

  // 3. Refunds: the ping fires again with refunded=true. Reverse instead of recording.
  if (sale.refunded === 'true' || sale.refunded === true) {
    const refundBody = JSON.stringify({
      external_event_id: sale.sale_id, // Same id as the original sale
      refund_reason: 'platform_refund',
    });
    const refundSig = crypto.createHmac('sha256', process.env.REKOMI_S2S_SECRET)
      .update(refundBody).digest('hex');
    await fetch('https://api.rekomi.com/api/tracking/refund', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-Rekomi-Signature': refundSig },
      body: refundBody,
    });
    return res.sendStatus(200);
  }

  // 4. Relay the sale to Rekomi. Gumroad already sends price in cents (integer),
  //    so do NOT multiply by 100.
  const body = JSON.stringify({
    external_event_id: sale.sale_id,
    affiliate_slug: referral,
    amount_cents: parseInt(sale.price, 10),
    currency: 'USD', // Gumroad settles every charge in USD
    customer_email: sale.email,
  });
  const signature = crypto.createHmac('sha256', process.env.REKOMI_S2S_SECRET)
    .update(body).digest('hex');

  await fetch('https://api.rekomi.com/api/tracking/s2s', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-Rekomi-Signature': signature },
    body,
  });
  res.sendStatus(200);
});

Relay quirks, corrected against Gumroad's current behavior:

  • Gumroad sends price in cents already (integer). Multiplying by 100 gives a 100x commission, the single most common bug on this install. The currency field on the ping is the product's display-pricing label, not the settlement currency; money is always USD cents.
  • Form-encoded body with nested keys. Gumroad POSTs application/x-www-form-urlencoded, not JSON. Use a parser that supports nested keys so url_params[via] resolves.
  • Retries are few and narrow. Gumroad retries a failed delivery up to 4 times inside roughly 14 minutes, and only when your handler answers 499, 500, 502, 503, or 504. Anything else that goes wrong, including a handler timeout or a connection failure, is dropped without retry. Make the relay idempotent (external_event_id de-dupes on Rekomi's side), keep it fast, and run it on infrastructure with strong uptime; queue-and-retry on your side is the robust pattern.
  • The Ping URL fires on every sale, including ones with no affiliate. Return 200 early for those so the delivery is considered handled.
  • Affiliate links must carry the parameter explicitly. Gumroad has no cookie layer Rekomi controls; the slug has to be in the URL the buyer lands on.

Related

  • Migrating from Gumroad
  • S2S tracking API reference
  • Refund handling

Install on Recurly

Connect Recurly natively: pick your US or EU region and paste a read-only API key into Rekomi, add the Rekomi webhook in Recurly, and paid invoices, subscription renewals, and refunds are tracked automatically. Carry rekomi_ref on the subscription so each sale credits the right affiliate.

Install on Creem

Connect Creem natively: add one webhook in Creem's dashboard with all events selected, paste the signing secret and an API key into Rekomi, and sales, subscription renewals, refunds, and chargebacks are tracked automatically. Carry rekomi_ref in checkout metadata so each sale credits the right affiliate.

On this page

Connect in RekomiAttribution: the rekomi_ref link paramWhat gets trackedHow Rekomi authenticates Gumroad's notificationsDelivery is lossy: gaps and backfillImport your existing Gumroad affiliates and historyQuirks worth knowingTest the installTroubleshootingLegacy: Ping URL relay (S2S)Related