Web App Affiliate

Let affiliates promote your web app or SaaS product and earn commissions on every sale, powered by Stripe.

How it works

End-to-end flow from app creation to payout.

1

Business owner creates a web affiliate app on Affiliateo.

2

Sets commission rate (percentage or flat) and connects their Stripe account.

3

Adds the Affiliateo tracking SDK to their website.

4

Affiliates join the app and get unique referral links.

5

When someone clicks a referral link and makes a purchase, the affiliate earns commission.

6

On the 1st of the next month, commissions become payable.

7

Business owner clicks "Pay" to transfer commissions to affiliate wallets.

Commission structure

Flexible commission models for your business.

Type
Example
Description
Percentage20% of each saleAffiliate earns a percentage of the transaction amount
Flat rate$5 per saleAffiliate earns a fixed amount per conversion
Per-product custom$5 on one product, 15% on anotherSet one default rate for the app, then override individual products with their own percentage or flat amount. Products you don't customize fall back to the default rate.

A 5% platform fee applies to each affiliate-referred sale, in addition to the commission you set.

Commission rate is locked in when an affiliate joins. The rate cannot be lowered for existing affiliates.

Payment providers

Affiliateo connects to six different payment platforms. Each provider has its own setup and install instructions, but all of them feed into the same affiliate tracking + commission logic.

Stripe

OAuth Connect

Best for SaaS and digital products. Click Connect → approve in Stripe popup → done. Our SDK or paste-in script captures the affiliate, you pass it to Stripe metadata at checkout.

Storefront install

npm install @affiliateo/web (or paste t.js)

Polar

OAuth Connect

Open-source Stripe alternative for digital creators. Same OAuth shape as Stripe. single click to connect.

Storefront install

npm install @affiliateo/web (or paste t.js)

Paddle

Paste API key

Merchant-of-Record platform for SaaS. Paste a Paddle API key from your dashboard; we auto-create the webhook subscription on your account.

Storefront install

npm install @affiliateo/web (or paste t.js)

Whop

Paste API key

Creator monetization platform (memberships, communities, courses). Paste a Whop Company API key; we auto-create the webhook.

Storefront install

npm install @affiliateo/web (or paste t.js)

Shopify

Paste store credentials

For Shopify dropshippers. Create a custom app in your Shopify admin, paste shop domain + access token + API secret. We auto-create the webhooks.

Storefront install

Paste shopify-affiliate.js script into theme.liquid

WooCommerce

OAuth Connect

For WordPress-based stores. Type your shop URL → click Connect → approve in your WC admin popup. WooCommerce generates and sends us the keys directly.

Storefront install

Download the Affiliateo WordPress plugin and activate

SDK integration

Add the Affiliateo SDK to your website to track affiliate referrals and attribute purchases.

Applies to Stripe, Polar, Paddle, and Whop. Shopify and WooCommerce use their own install paths. see below.

1. Install

Terminal
npm install @affiliateo/web

2. Add the provider to your app

app/layout.tsx
import { AffiliateoProvider } from '@affiliateo/web';

export default function RootLayout({ children }) {
  return (
    <AffiliateoProvider campaignId="YOUR_CAMPAIGN_ID">
      {children}
    </AffiliateoProvider>
  );
}

3. Pass attribution to Stripe checkout

Checkout button (client)
'use client'
import { getAttribution } from '@affiliateo/web';

async function handleCheckout() {
  const attribution = getAttribution();
  const res = await fetch('/api/checkout', {
    method: 'POST',
    body: JSON.stringify({ attribution }),
  });
  const { url } = await res.json();
  window.location.href = url;
}
app/api/checkout/route.ts
export async function POST(req) {
  const { attribution } = await req.json();

  const session = await stripe.checkout.sessions.create({
    line_items: [...],
    mode: 'payment',
    metadata: attribution,
  });

  return Response.json({ url: session.url });
}

That's it! The provider tracks sessions and captures affiliate attribution automatically. Stripe metadata links each purchase back to the referring affiliate.

Track conversion goals

Pageviews auto-track. For specific moments that matter to your funnel (signup_completed, trial_started, initiate_checkout, etc.), you have two options depending on your integration: npm SDK users call track() from a React hook (and trackPageview() for modal or virtual-route pageviews). Script-tag users can additionally drop a data-affiliateo-goal attribute on any button, or data-affiliateo-scroll on a section to fire when it scrolls into view (great for landing pages where you want to know which sections convert). Goal names must be lowercase letters, digits, underscores, hyphens, or colons.

Fire a custom goal from React

app/signup-success/page.tsx
'use client'
import { useEffect } from 'react'
import { useAffiliateRef } from '@affiliateo/web'

export default function SignupSuccess() {
  const { track } = useAffiliateRef()
  useEffect(() => {
    track('signup_completed', { plan: 'free' })
  }, [])
  return <div>Welcome!</div>
}

Track virtual pageviews (modals, SPA routes)

Modal or virtual route open handler
'use client'
import { useEffect } from 'react'
import { useAffiliateRef } from '@affiliateo/web'

export default function PricingModal({ open }: { open: boolean }) {
  const { trackPageview } = useAffiliateRef()
  useEffect(() => {
    // Fire a pageview for the modal so it shows up in your funnel
    // even though no real route change happened.
    if (open) trackPageview('/pricing-modal')
  }, [open])
  return null
}

Identify signed-in users

Without identify(), the same person browsing on phone and buying on laptop counts as two unrelated visitors and your funnel splits across devices. Call it once after sign-in so Affiliateo can stitch the journey to one person. Idempotent. safe to fire on every page load.

Stitch this browser to a logged-in user

After sign-in (top-level layout)
'use client'
import { useEffect } from 'react'
import { useAffiliateRef } from '@affiliateo/web'
import { useUser } from './your-auth'

export default function AuthBoundary({ children }) {
  const { identify } = useAffiliateRef()
  const user = useUser()
  useEffect(() => {
    if (user) identify(user.id)
  }, [user])
  return <>{children}</>
}

Multi-domain attribution

If your property spans more than one domain (marketing site on marketing.com and your app on app.merchant.com), affiliate ref codes die at every domain boundary because browsers sandbox storage by origin. Without help, an affiliate who sends traffic to your marketing site gets no commission when the visitor signs up on your app domain. Add the other domains via data-allowed-hostnames (script tag) or allowedHostnames (npm SDK prop) and the SDK auto-decorates outbound links with the visitor identity. The receiving domain reads those params on landing, strips them from the URL bar, and the funnel sees one continuous visitor. Both sides need the SDK installed and both need to list the OTHER domains (each side names everyone except itself).

Pass allowedHostnames to the provider

app/layout.tsx (multi-domain merchants)
import { AffiliateoProvider } from '@affiliateo/web';

export default function RootLayout({ children }) {
  return (
    <AffiliateoProvider
      campaignId="YOUR_CAMPAIGN_ID"
      allowedHostnames={['app.merchant.com', 'docs.merchant.com']}
    >
      {children}
    </AffiliateoProvider>
  );
}

Development & debugging

By default the SDK is configured for production safety: localhost is blocked (so npm run dev doesn't pollute your funnel), iframes are blocked (so scrapers and preview tools don't count as pageviews), and debug logs are silent. Turn any of these on with the props or attributes below. Also exposed: a flush() method to force queued events out the door right before a redirect, so they don't get lost when the page navigates away.

Opt-in dev flags (allowLocalhost, allowIframe, debug)

app/layout.tsx (dev / debugging)
import { AffiliateoProvider } from '@affiliateo/web';

export default function RootLayout({ children }) {
  return (
    <AffiliateoProvider
      campaignId="YOUR_CAMPAIGN_ID"
      // Turn on for end-to-end tests against localhost.
      // Leave false (the default) in production.
      allowLocalhost={process.env.NODE_ENV !== 'production'}
      // Print decision logs to the browser console. Useful when
      // investigating "why aren't my events showing up?".
      debug={process.env.NODE_ENV !== 'production'}
      // Set to true if your site is legitimately embedded inside
      // an iframe (e.g. an embed widget shipped to partners).
      // allowIframe
    >
      {children}
    </AffiliateoProvider>
  );
}

Force flush before a redirect

Checkout button
'use client'
import { useAffiliateRef } from '@affiliateo/web'

export default function CheckoutButton() {
  const { track, flush } = useAffiliateRef()
  return (
    <button onClick={async () => {
      track('initiate_checkout', { plan: 'pro' })
      // Force events out NOW before the redirect kills the page.
      // Default flush timer is every 5s, too slow for a redirect.
      await flush()
      window.location.href = '/api/checkout'
    }}>
      Subscribe
    </button>
  )
}

allowLocalhost matches localhost, 127.0.0.1, RFC1918 IPs, and the reserved .local / .test / .example / .invalid / .localhost / .lvh.me / .localtest.me TLDs. Production-style hosts (.vercel.app, .pages.dev, custom domains) are always allowed.

Shopify storefront install

Drop a single script into your theme. It captures affiliate ref-codes from URL parameters, syncs them into Shopify cart attributes, and tracks visitor pageviews. all in one tag.

Paste before </body> in layout/theme.liquid

layout/theme.liquid
<script defer
  data-campaign="YOUR_CAMPAIGN_ID"
  src="https://affiliateo.com/shopify-affiliate.js"
></script>

In Shopify admin → Online Store → Themes → Edit code → open layout/theme.liquid → paste before </body> → Save. Works on every Online Store 2.0 theme (Dawn, Crave, Sense, etc.) and on headless / Hydrogen storefronts.

WooCommerce plugin install

Download the Affiliateo WordPress plugin, install it on your store, and paste your app ID. The plugin handles ref-code capture (cookie + checkout hook → order meta_data) and visitor analytics.

1

Download affiliateo-woocommerce.zip from your wizard's install step.

2

In your WordPress admin: Plugins → Add New → Upload Plugin → choose the .zip → Install NowActivate.

3

Go to WooCommerce → Settings → Advanced → Affiliateo and paste your app ID. Save.

4

Affiliate links work immediately. The plugin captures the ?ref= parameter, persists it through checkout, and writes it to the order's _affiliateo_ref meta. which our webhook handler picks up automatically.

Data & privacy

Exactly what we read from your Stripe account, and what we don't.

When a sale happens on your connected Stripe account, Stripe sends us a webhook event. We don't make API calls against your account or pull data on our own, we only read what's needed to attribute the sale and pay the affiliate.

What we read from each sale

Amount paid and currency
Sale type: one-time, subscription, trial, or renewal
Stripe's internal IDs (customer, subscription, payment intent), opaque pointers, not personal data
The affiliate attribution metadata your code attaches to the checkout session
The product name, only if you include it in checkout metadata

What we never read or store

Customer email, name, or phone number
Billing or shipping addresses
Card numbers or any payment method details
Tax IDs or VAT numbers
Line item details beyond an optional product name
Any other customer or transaction in your Stripe account

Stripe Connect doesn't offer a read-only scope for payment platforms, every Connect platform uses the same access level. We don't poll your account or run reports; we only listen for webhook events from sales that flowed through an affiliate-tagged checkout session.

Payout schedule

When and how affiliates get paid.

Commissions are tracked in real time as purchases happen. On the 1st of the next month, commissions become payable.

1

Affiliate drives a sale, commission is recorded immediately.

2

On the 1st, pending commissions become payable.

3

Business owner reviews and clicks "Pay" to transfer to affiliate wallets.

Stripe payment processing fees apply separately. See the Fees page for full pricing details.