ridebuilder / affiliate
Server-side SDK for RideBuilder FirstParty affiliate tracking: capture click_id and send checkout/return postbacks.
Requires
- php: >=8.1
- ext-curl: *
- ext-json: *
Suggests
- psr/http-client-implementation: Inject your own PSR-18 HTTP client instead of the built-in cURL transport
README
Server-side SDK for RideBuilder's FirstParty affiliate program. It does two things:
- Capture the
click_ida shopper arrives with, so your backend can bind it to the cart/order. - Report checkout and return postbacks to RideBuilder (auth, retries, idempotency handled).
Mirrors the Node/.NET/Python SDKs — same contract, verified by the shared conformance suite.
Install
composer require ridebuilder/affiliate
Requires PHP 8.1+ and ext-curl (bundled with virtually every PHP). No third-party runtime dependencies —
the default transport uses cURL. To run from source without Composer, require 'sdk/php/autoload.php'.
The pattern: capture at landing, bind to the order
Capture the click_id on landing, store it with the cart, and send it at purchase.
use RideBuilder\Affiliate\{RideBuilderClient, Capture, CheckoutInput}; // 1. On landing, read a validated click_id off the request URL and persist it onto YOUR cart record. $clickId = Capture::fromUrl($_SERVER['REQUEST_URI']); if ($clickId !== null) { $cart->ridebuilderClickId = $clickId; } // 2. At order time, send the postback from your backend. $rb = new RideBuilderClient(apiKey: getenv('RIDEBUILDER_API_KEY')); $rb->reportCheckout(new CheckoutInput( orderId: $order->id, subtotal: '199.99', // major units; string keeps it exact currency: 'USD', clickId: $order->ridebuilderClickId, ));
Store the API key server-side (env/secrets) — never in frontend code.
Decoupled frontend (e.g. React) + separate PHP backend
If the frontend is separate, the browser snippet captures the click_id into a first-party cookie, and
you get it to your backend one of two ways:
// Same registrable domain — the cookie rides along; read it off the Cookie header: $clickId = Capture::fromCookieHeader($_SERVER['HTTP_COOKIE'] ?? null); // Cross-domain / mobile — the frontend forwards it in the checkout call: $clickId = Capture::fromHeaders(getallheaders()); // default header: X-RideBuilder-Click-Id
Either way, reportCheckout is unchanged — that's the SDK's real value in a decoupled setup.
Refunds
$rb->reportReturn(new ReturnInput( returnId: $refund->id, orderId: $order->id, refundAmount: '49.95', currency: 'USD', ));
Integration protocol (register / verify / heartbeat)
$rb = new RideBuilderClient(apiKey: $apiKey, environment: 'production'); // or 'sandbox' $reg = $rb->register(); // handshake on install/startup; returns a stable integration id $rb->verify(); // deploy/CI self-test — throws RideBuilderException on a bad/rotated key $rb->heartbeat(); // periodic liveness (call from cron; PHP has no persistent process)
The SDK reports its own type (php_sdk), version, and default capabilities.
Capture helpers
All validate ref == "ridebuilder" and the UUID-v4 click_id, returning null otherwise:
Capture::fromUrl($url)— from an absolute or relative URL.Capture::fromQuery($query)— from a decoded query map.Capture::fromCookieHeader($cookieHeader)— recover it from theridebuilder_attributioncookie.Capture::fromHeaders($headers, $name = 'X-RideBuilder-Click-Id')— from a forwarding header (decoupled path).
Client options
new RideBuilderClient( apiKey: $key, baseUrl: null, // defaults to https://api.ridebuilder.com/v1 maxRetries: 3, // retries on network errors, timeouts, 5xx, 429 timeoutMs: 10000, // per-attempt timeout environment: 'production', transport: null, // inject a RideBuilder\Affiliate\Transport\Transport (e.g. wrap a PSR-18 client) );
reportCheckout / reportReturn return PostbackResult(accepted, status) (202 = accepted, validated
asynchronously). Invalid input throws a non-retryable RideBuilderException; auth/size failures (401,
413) throw with ->status and ->errorCode. Amounts must be > 0 with at most 2 decimal places (pass a
string to avoid float rounding) or the call throws up front.
Tests
Plain PHP, no PHPUnit/Composer required:
php tests/conformance.php # the shared cross-language fixtures php tests/unit.php # validation, capture, money, retry/error, identity
Contract
Wraps the RideBuilder affiliate REST contract — POST /v1/postback/checkout, /postback/return,
/postback/health, the /integration/* endpoints, the /redirect link format, and API-key provisioning.
Verified byte-for-byte against the Node/.NET/Python SDKs by the shared conformance fixtures.