Headless Coupons
How coupon-based attribution works on a headless site. The hybrid path is straightforward, but fully-headless commerce has gaps worth knowing about up front.
Requires Siren Essentials
Last updated: April 30, 2026
Whether headless coupons need any code from you depends on one question: does WordPress still run the transaction? If a supported commerce plugin (WooCommerce, EDD, North Commerce, LifterLMS) is on the install, the answer is yes and you have nothing to do beyond passing the coupon through. If checkout has moved off WordPress entirely, you’ve stepped outside Siren’s public surface for coupons and the rest of this page is about which workaround to pick. See coupon code tracking for the full per-integration breakdown of how coupon attribution works inside Siren.
Hybrid: WordPress commerce plugin still runs the transaction
If your install runs a supported commerce extension and checkout still happens server-side through it, do nothing special. The extension fires CouponApplied when the customer enters the code, and Siren’s BoundCouponUsed engagement trigger handles the rest.
The only requirement on the frontend is making sure the coupon code reaches the WordPress checkout, typically inside the cart payload. Don’t apply the discount entirely on your own and skip the WordPress side. That bypasses the hook the integration depends on.
Fully headless: no WordPress commerce plugin
If checkout happens in your frontend or an external system with no WooCommerce or EDD on the install, coupon attribution gets harder. The public surface for it is missing. The event endpoint exposes only site-visited, sale, and refund. There’s no coupon-applied slug. CouponApplied is broadcast internally by commerce extensions and has no public REST entry point. No event, no engagement.
Three options, in order of preference.
Option 1: Keep WooCommerce as the transaction layer
Keep WooCommerce installed and route the transaction through it from your frontend via the WooCommerce REST API. The coupon hook fires, Siren picks up the rest, and you write no custom code. The storefront stays fully headless because WordPress is still doing the commerce work in the background.
Option 2: Ship a small Siren extension that registers the event
If routing through WooCommerce isn’t an option, ship a Siren extension that registers a CouponApplied event factory. The extension declares a slug, parses the coupon code and opportunity ID out of the request body, and builds the event. Siren’s pipeline takes over from there. The extension quickstart and event bindings and transformers cover the patterns. This means shipping PHP onto the WordPress install, so it’s only worth doing when you genuinely cannot run a commerce extension.
Option 3 (last resort): POST conversions directly
The escape hatch is to skip the event system and call the conversions create endpoint directly from your frontend’s server runtime, passing the opportunity ID in the same X-Siren-OID header used everywhere else. The endpoint requires admin auth, so it has to come from a server runtime holding a WordPress application password. The browser cannot call it. This works, but you give up real things the event-driven path produces for free:
- The activity-feed note that normally records “coupon CODE redeemed on opportunity #N” comes from
CouponApplied. Direct conversion creates skip it, so support staff lose the audit trail. - Without
BoundCouponUsed, Siren can’t resolve which collaborator owns a coupon. You keep that mapping outside the alias system and resolve it before posting. RefundTriggerednormally cancels the matching conversion and subtracts value from collaborator metrics. Without an extension behind the sale, refunds are your job. POST/event/refundyourself or the credit stands.
Reach for this path only when the other two are genuinely closed off, and document the workarounds so the gaps don’t catch a teammate by surprise later.