Attrifast
ProductAI visibilityPricingDocsBlog
Log inStart free trial
ProductAI visibilityPricingDocsBlogLog in
From traffic to revenue

See which channels bring customers—not just visits.

Install one lightweight script and connect Stripe or Shopify when you are ready.

Start free trialSee live demo
Product
  • Track Website Traffic
  • Website Visitor Tracking
  • Attribution Software
  • AI Revenue Attribution
  • Revenue by Source
  • SEO Dashboard
  • Pricing
AI traffic
  • Track ChatGPT Traffic
  • Track Perplexity Traffic
  • Track Claude Traffic
  • Track Gemini Traffic
  • Track AI Overviews
  • All AI Search Guides
Use cases
  • Stripe Analytics
  • Shopify Analytics
  • Analytics for SaaS
  • For Bootstrapped SaaS
  • Privacy-First Analytics
Compare
  • Attrifast vs Cometly
  • Attrifast vs GA4
  • Attrifast vs Mixpanel
  • Attrifast vs DataFast
  • All Comparisons
Resources
  • Blog
  • Research
  • Documentation
  • Free Tools
  • GEO Hub
  • AI Crawler Directory
  • Live Demo
© 2026 Attrifast · built by Vincent Ruan & Jessica Huang
AboutContactTermsPrivacy
Blog / Attribution

Stripe Attribution in 2026: The Complete Guide to Connecting Payments to Marketing Channels

22 min readUpdated Aug 1, 2026
Vincent Ruan
Vincent RuanFounder, Attrifast · May 26, 2026 · 22 min read

Stripe attribution, the complete 2026 guide: join Stripe payments to marketing channels with webhook code, model trade-offs, and an honest tool comparison.

TL;DR

  • Stripe records the payment, plan, invoice, refund, and customer. It does not know which ad, article, search result, or AI answer brought the buyer to your site. You have to capture that context before checkout and pass it into Stripe metadata.
  • Three webhooks cover most of the work: checkout.session.completed captures the conversion, customer.subscription.created captures activation, and invoice.payment_succeeded lets you report MRR by channel over time.
  • For most bootstrapped SaaS teams, keep both first-touch and last-non-direct attribution. The first shows where the relationship began; the second shows which meaningful visit preceded the conversion.
  • Entry prices range from $9.99/month for Attrifast to $499/month for Wicked Reports, with different audiences and depth. Shopify-heavy and enterprise teams need different tools from a small Stripe-native SaaS.
  • Sigma can report MRR by marketing source only after your own tracker writes that source into Stripe metadata. Sigma handles the query; the capture pipeline supplies the missing data.
  • GA4 will not show you which channel drove your last $10k in Stripe MRR. See the revenue-by-channel breakdown inside Attrifast → Start free trial

A founder asked me for help with a board deck in March. Stripe showed $112,000 in MRR, and Sigma showed the plan mix. One slide was still blank: revenue by acquisition channel.

Marketing claimed the ChatGPT pipeline. The agency claimed LinkedIn. The content team claimed SEO. Stripe could not settle it, GA4 had lost part of the journey, and the BI tool had cleanly joined incomplete fields. The final slide said “directional, multi-touch.” Nobody trusted it.

This guide shows how to fill in that slide. The architecture is straightforward: capture the visit, carry an identifier into Checkout, handle the right webhooks, and write attribution into Stripe metadata. The harder part is choosing a model the team can explain and use consistently.

For AI-specific traffic detection, use the ChatGPT referral analytics guide. AEO vs SEO explains the broader channel strategy, and does GEO actually drive revenue covers the evidence behind AI-driven channels. Here, the focus is Stripe: webhooks, metadata, joins, and attribution models.

Stripe attribution gap: Stripe captures every payment dimension (plan, country, MRR, ARR, refund, dispute) but no marketing channel field exists on any Stripe object unless you write it into metadata yourself

Updated August 2026. Prices changed sharply since the May edition. The underlying Stripe implementation changed very little.

Pricing: I re-checked every entry price against the vendor's site on 31 July 2026. SegMetrics replaced its $175/month Essentials tier with Launch at $57. Wicked Reports moved from a $249 Foundation plan to a $499 Measure plan. Triple Whale added a free tier and moved its first paid tier to $179. Baremetrics, ChartMogul, Northbeam, and Stripe Sigma also changed their packaging. Sigma now charges by successful monthly payments rather than events, making DIY reporting cheaper for subscription businesses with relatively few charges.

Implementation: client_reference_id, Checkout Session metadata, the 50-key and 500-character metadata limits, the core webhooks, and the three-day retry window are unchanged. Stripe now calls webhook endpoints “event destinations” in Workbench and calls test mode “sandboxes.” It also recommends restricted API keys for new integrations. Stripe no longer publishes a fixed 30-second handler timeout; the guidance is to return 2xx before slow work. This edition also adds Payment Links.

Quick Facts

MetricValueSource
Stripe processed payment volume (FY2024)Roughly $1.4 trillionStripe annual letter [1]
Stripe webhook event types available200+Stripe webhook docs [2]
Webhook events that matter for attribution3 core, ~6 with refunds/churnAuthor's analysis
Stripe Sigma availabilityAll paid Stripe accountsStripe Sigma docs [3]
Stripe Customer metadata key limit50 keys per object, 40-char key names, 500 chars per valueStripe API reference [4]
Median time from trial start to paid conversion (B2B SaaS, 2025)11-18 daysOpenView SaaS benchmarks [5]
Median trial-to-paid conversion rate (B2B SaaS, 2025)14-23%ChartMogul benchmark [6]
% of SMB SaaS using GA4 as primary attributionRoughly 71%Baremetrics blog survey [7]
% of those who can name their top revenue-driving channel correctlyRoughly 38%Author's audit, n=42
SegMetrics entry price (Jul 2026)$57/mo LaunchSegMetrics pricing page [8]
Wicked Reports entry price (Jul 2026)$499/mo MeasureWicked Reports pricing [9]
TripleWhale entry price (Jul 2026)$179/mo Starter, free tier below it (Shopify-first)TripleWhale pricing [10]
Polar Analytics entry price (Jul 2026)GMV-quoted, roughly $300+/moPolar pricing page [11]
Baremetrics entry price (Jul 2026)$75/mo Launch ($49 annual)Baremetrics pricing [12]
Northbeam entry price (Jul 2026)$1,500/mo Starter (published)Northbeam pricing [13]
Attrifast entry price (Jul 2026)$9.99/mo Starter, $49/mo ProAttrifast pricing
Median ROI of attribution investment, per McKinsey15-20% lift in marketing efficiencyMcKinsey on marketing analytics [14]

Two numbers frame the problem. Stripe exposes more than 200 webhook event types, giving you detailed financial events across the customer lifecycle. Yet only 38% of operators in my audit could name their top revenue-driving channel correctly. The payment data exists; the acquisition context is missing.

Why Stripe alone cannot tell you where revenue came from

Stripe knows what happened after the buyer reached the payment flow. It does not see the visit that came before it. Customer, Subscription, Invoice, Charge, PaymentIntent, and Checkout Session objects all accept custom metadata, subject to a 50-key limit and 500 characters per value [4]. Stripe stores the attribution fields you send, but it cannot create them from a web session it never observed.

A useful mental model is simple: Stripe is the ledger; your analytics system provides the route to the ledger. Attribution joins the two.

Here is the side-by-side of what Stripe knows about a typical paying customer versus what you need to know for attribution:

DimensionStripe knows it natively?Where it livesWhat you need to add
Customer emailYesCustomer.emailNothing
Plan and priceYesSubscription.items[].price.idNothing
Currency, country, taxYesCustomer.address, Invoice.taxNothing
MRR per customerComputableSubscription.items[].price.unit_amountNothing
Lifetime valueComputableSum of Invoice.amount_paidNothing
Refunds, disputes, chargebacksYesCharge.refunded, DisputeNothing
First-touch marketing channelNoNoneMust write to metadata yourself
Last-touch marketing channelNoNoneMust write to metadata yourself
UTM source/medium/campaignNoNoneMust capture upstream and pass through
Landing pageNoNoneMust capture upstream and pass through
ReferrerNoNoneMust capture upstream and pass through
Session duration before purchaseNoNoneMust capture upstream
Number of pageviews before purchaseNoNoneMust capture upstream
AI engine source (ChatGPT, Perplexity, etc.)NoNoneMust capture upstream via referer fingerprinting
Ad campaign ID (Meta, Google, LinkedIn)NoNoneMust capture from URL params, pass through metadata
Coupon attributionPartialCustomer.discount.coupon.idUseful as a proxy for some campaigns
Affiliate / partner attributionNoNoneMust implement via metadata convention
Sales rep attributionNoNoneManual write at customer.created
Trial source (organic vs paid)NoNoneMust capture upstream
Activation channel (different from acquisition)NoNoneCustom metric, must derive

The lower half of the table contains the fields that guide marketing budgets, and Stripe does not collect any of them. Capture those signals on your site and pass a summary into metadata, or the payment record will have no channel context.

Stripe Atlas publishes useful articles about marketing attribution [15], but Stripe does not offer a product called “Stripe Attribution.” Sigma is the closest native reporting tool. It can query Stripe's own fields and any metadata you add, but it cannot capture the original visit. You still need a tracker and a way to carry its identifier into Stripe.

Stripe primitiveWhat it doesHelpful for attribution?
DashboardManual UI for inspecting customers, chargesRead-only, not built for channel analysis
Reports (in Dashboard)Pre-built financial reportsPre-built, no attribution dimension
SigmaSQL over Stripe dataYes if metadata is populated; useless otherwise
Data PipelineStreams Stripe data to your warehouseBuilding block, requires custom ETL
WorkflowsVisual automationCan write to metadata; not a capture engine
Customer PortalSelf-serve subscription UIOutside attribution scope
AppsStripe-built integrationsMarketplace varies; few attribution apps
WebhooksReal-time event streamYes, this is where capture happens
Metadata fieldsOpen key-value storageThe destination for attribution data

Stripe provides the building blocks. Your application — or an attribution product — has to connect them.

The three Stripe webhook events that matter for attribution

Stripe has more than 200 event types [2], but three cover most SaaS and ecommerce attribution. Two more handle refunds and churn. You may need other events elsewhere in the product, but not for a basic channel report.

The core three

Event 1: checkout.session.completed. This fires when Checkout completes. The session contains the metadata set when it was created, so the handler can read the first-party visitor ID and copy attribution into Customer and Subscription metadata. For ecommerce, it is also a natural point to record the order's channel.

Event 2: customer.subscription.created. This marks the start of a subscription. In a trial flow, later subscription updates may mark the move to paid; without a trial, creation often occurs near checkout completion. Keep it separate because the channel that brought the signup may differ from the one that drove activation.

Event 3: invoice.payment_succeeded. This fires for successful invoice payments, including renewals. Add each event to the customer's acquisition channel to build MRR and lifetime value by channel. Without renewals, you only know the value of the first payment.

The webhook payload shape, at a glance:

Event typeTriggers whenKey payload fields for attributionIdempotency notes
checkout.session.completedA Checkout Session completesid, customer, subscription, metadata, client_reference_id, payment_intentUse session id as idempotency key
customer.subscription.createdNew Subscription beginsid, customer, metadata, items, status, trial_endUse subscription id as idempotency key
invoice.payment_succeededRecurring or one-off invoice paidid, customer, subscription, amount_paid, billing_reasonUse invoice id as idempotency key
customer.createdNew Customer object createdid, metadata, emailUse customer id as idempotency key
customer.subscription.updatedSubscription plan/status changesid, customer, previous_attributes, statusUse (id, occurred_at) for idempotency
customer.subscription.deletedSubscription canceledid, customer, canceled_atUse subscription id
charge.refundedRefund issuedid, customer, amount_refundedUse charge id plus refund id
invoice.payment_failedRecurring payment failsid, customer, attempt_countUse invoice id
customer.updatedCustomer email/address/metadata changedid, previous_attributesUse (id, occurred_at) for idempotency
payment_intent.succeededOne-off payment completes (non-Checkout)id, customer, metadata, amountUse payment intent id

The two edge-case events

Event 4: charge.refunded. For ecommerce attribution, refund rates vary enormously by channel. Paid social drives higher refund rates than organic search at most DTC sites; ignoring refunds inflates paid social ROI by 10-30%. Subtracting refunded amount from the original channel's revenue gives a more honest channel ROI.

Event 5: customer.subscription.deleted / customer.subscription.updated. For SaaS, churn-by-channel is the second-most-important question after acquisition-by-channel. The combination of these two events lets you compute net-MRR-by-channel, which is the metric that actually moves budget decisions long-term.

A full webhook event map for attribution

Webhook eventFrequency at typical SMB SaaSRequired for basic attribution?Required for advanced attribution?
checkout.session.completedHigh (every conversion)YesYes
customer.subscription.createdMediumRecommendedYes
invoice.payment_succeededHighest (every renewal)Yes (for MRR over time)Yes
customer.createdMediumOptionalYes (for first-touch lock-in)
customer.subscription.updatedMediumOptionalYes (for expansion attribution)
customer.subscription.deletedLowOptionalYes (for churn-by-channel)
charge.refundedLow-mediumOptionalYes (for ecommerce net-rev)
invoice.payment_failedLow-mediumNoUseful (for dunning attribution)
payment_intent.succeededVariableYes if not using CheckoutYes
payout.paidDaily/weeklyNoUseful for cash-basis reconciliation

For a new SaaS implementation, start with checkout.session.completed, customer.subscription.created, and invoice.payment_succeeded. Make each handler idempotent and write first-touch plus last-touch to Customer metadata. Add churn and refund events once those distinctions matter to your decisions.

A worked example: Node.js webhook handler that writes attribution

The example below is a minimal idempotent Express and Node.js handler. The same sequence works in Fastify, Hono, Next.js route handlers, FastAPI, or Rails.

// webhooks/stripe.js — minimal Stripe attribution capture handler

import express from 'express'
import Stripe from 'stripe'
import { db } from '../db.js'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET

export const router = express.Router()

router.post(
  '/webhooks/stripe',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    let event
    try {
      event = stripe.webhooks.constructEvent(
        req.body,
        req.headers['stripe-signature'],
        endpointSecret,
      )
    } catch (err) {
      return res.status(400).send(`Webhook signature failed: ${err.message}`)
    }

    // Idempotency: skip if we have already processed this event
    const alreadyProcessed = await db.processedEvents.findById(event.id)
    if (alreadyProcessed) return res.status(200).send('ok-duplicate')

    try {
      switch (event.type) {
        case 'checkout.session.completed':
          await handleCheckoutCompleted(event.data.object)
          break
        case 'customer.subscription.created':
          await handleSubscriptionCreated(event.data.object)
          break
        case 'invoice.payment_succeeded':
          await handleInvoicePaid(event.data.object)
          break
        case 'customer.created':
          await handleCustomerCreated(event.data.object)
          break
      }
      await db.processedEvents.insert({ id: event.id, processedAt: new Date() })
      res.status(200).send('ok')
    } catch (err) {
      // Stripe will retry on 5xx, so we surface the failure
      console.error('webhook handler error', err)
      res.status(500).send('handler-failed')
    }
  },
)

async function handleCheckoutCompleted(session) {
  // 1. Pull the first-party identifier from session metadata (we set it on create)
  const firstPartyId = session.metadata?.first_party_id
  if (!firstPartyId) return // pre-attribution checkout, no upstream session

  // 2. Look up the upstream session row written by the tracker
  const upstreamSession = await db.sessions.findFirstPartyId(firstPartyId)
  if (!upstreamSession) return

  // 3. Compute first-touch and last-non-direct touch
  const touches = await db.touches.findByFirstPartyId(firstPartyId)
  const firstTouch = touches[0]
  const lastNonDirectTouch =
    [...touches].reverse().find((t) => t.channel !== 'direct') ?? firstTouch

  // 4. Write attribution into Customer metadata (immutable forever)
  if (session.customer) {
    await stripe.customers.update(session.customer, {
      metadata: {
        attr_first_channel: firstTouch.channel,
        attr_first_source: firstTouch.source ?? '',
        attr_first_campaign: firstTouch.campaign ?? '',
        attr_first_at: firstTouch.occurredAt.toISOString(),
        attr_last_channel: lastNonDirectTouch.channel,
        attr_last_source: lastNonDirectTouch.source ?? '',
        attr_last_campaign: lastNonDirectTouch.campaign ?? '',
        attr_last_at: lastNonDirectTouch.occurredAt.toISOString(),
      },
    })
  }

  // 5. Also stamp the conversion row in our own DB for fast joins later
  await db.conversions.insert({
    stripeCustomerId: session.customer,
    stripeSessionId: session.id,
    firstPartyId,
    firstChannel: firstTouch.channel,
    lastNonDirectChannel: lastNonDirectTouch.channel,
    amountPaid: session.amount_total,
    currency: session.currency,
    occurredAt: new Date(session.created * 1000),
  })
}

async function handleSubscriptionCreated(subscription) {
  // Capture activation-time attribution distinct from signup-time
  const customer = await stripe.customers.retrieve(subscription.customer)
  const firstChannel = customer.metadata?.attr_first_channel ?? 'unknown'
  await stripe.subscriptions.update(subscription.id, {
    metadata: {
      attr_activation_channel: firstChannel,
      attr_activation_at: new Date().toISOString(),
    },
  })
}

async function handleInvoicePaid(invoice) {
  // Accumulate MRR-by-channel for over-time reporting
  const customer = await stripe.customers.retrieve(invoice.customer)
  const channel = customer.metadata?.attr_last_channel ?? 'unknown'
  await db.mrrEvents.insert({
    stripeCustomerId: invoice.customer,
    stripeInvoiceId: invoice.id,
    channel,
    amount: invoice.amount_paid,
    currency: invoice.currency,
    billingReason: invoice.billing_reason,
    occurredAt: new Date(invoice.created * 1000),
  })
}

async function handleCustomerCreated(customer) {
  // No-op for most cases; useful if you want to lock the first-touch immediately
  // and not wait for checkout.session.completed
}

Before this reaches production, check the following:

CheckWhy it mattersCommon failure
Signature verification on every requestWithout it, attribution data is forgeable by anyone with your URLSkipped during local testing, never re-enabled
Raw body used for signature, not parsed JSONStripe signs the raw bytesBody parsed by Express middleware before reaching verifier
Idempotency table keyed on event.idStripe retries on 5xx and timeoutsHandler treats each retry as new event
Returns 2xx before any slow workStripe marks slow deliveries "timed out" and retries themLong-running sync work ahead of the response
Returns 200 quickly for unhandled event typesAvoids unnecessary retriesReturns 500 for events you don't care about
Wraps Stripe API calls in retry-on-rate-limitStripe API can rate-limit at burstSingle failed update silently drops attribution
Logs the event ID and type on entryDebugging requires the event IDLogs without IDs are unparseable
Stores raw event payload for replayLets you reprocess after handler bugsReplay impossible if payload is gone
First-touch is write-once, not overwriteCustomer.metadata is mutable from Stripe's sideLast touch silently replaces first touch on update
Sandbox and live mode events routed separatelyMixing modes corrupts attributionSingle endpoint handles both, attribution leaks across
Restricted API key, not a secret keyStripe now recommends RAKs over secret keys for new integrationsFull-access sk_live_ key sitting in an env var

Always verify the signature. Stripe's webhook security docs [16] require verification before you act on an event. Verify against the raw request body, not parsed JSON. Otherwise, anyone who finds the endpoint could forge attribution updates. You can add another layer by restricting the endpoint to Stripe's published webhook IP ranges.

Current Stripe terminology. The console now calls a webhook endpoint an event destination, configured under Webhooks in Workbench [28]. “Test mode” is now “sandboxes.” The payload, Stripe-Signature header, library methods, and test-key prefixes are unchanged.

Use a restricted API key. Stripe advises new integrations to use restricted keys (rk_live_) because secret keys cannot be scoped [27]. Attribution needs read access to Checkout Sessions and Invoices plus write access to Customer and Subscription metadata. It does not need refunds, payouts, or Connect. Scope the key to those operations and, if possible, restrict where it can be used.

Make the handler idempotent. Stripe guarantees at-least-once delivery, so the same event may arrive again. A 500 response can trigger retries for up to three days in live mode. Store the event.id after a successful run and check it at the start of the handler. Without that guard, a retry can duplicate revenue or overwrite attribution.

Return quickly. Stripe no longer gives a fixed timeout in its guidance. Verify the signature, enqueue the event, return 2xx, and perform slower Stripe API writes in a worker. A slow synchronous handler risks a timeout and another delivery.

Protect first-touch in your own code. Stripe lets any later update overwrite Customer metadata. Check customer.metadata.attr_first_channel before writing it again. The sample omits that branch for brevity.

Keep metadata small. Stripe allows 50 keys and 500 characters per value [4]. Store the channel summary and join key in Stripe; keep the full visit history in your own database.

A worked SQL example: revenue by channel from your Stripe + session join

Once Customer metadata and session rows contain the attribution keys, revenue by channel is a straightforward join. This PostgreSQL example assumes a local stripe_customers mirror plus your own sessions and mrr_events tables.

-- Revenue by acquisition channel, current quarter, last-non-direct attribution
SELECT
  sc.metadata->>'attr_last_channel' AS channel,
  COUNT(DISTINCT sc.id) AS paying_customers,
  SUM(me.amount) / 100.0 AS revenue_usd,
  SUM(me.amount) / 100.0 / NULLIF(COUNT(DISTINCT sc.id), 0) AS arpu_usd
FROM stripe_customers sc
JOIN mrr_events me ON me.stripe_customer_id = sc.id
WHERE me.occurred_at >= date_trunc('quarter', now())
  AND me.occurred_at < date_trunc('quarter', now()) + INTERVAL '3 months'
GROUP BY 1
ORDER BY revenue_usd DESC;

The same shape with first-touch attribution swapped in is a single column change. Sigma syntax differs slightly but the pattern is identical.

The two queries side by side often produce dramatically different channel rankings:

ChannelLast-non-direct revenueFirst-touch revenueDelta
Google organic$42,180$31,440-$10,740
ChatGPT / AI$14,180$19,840+$5,660
Email$11,820$4,200-$7,620
Paid social$9,310$8,640-$670
Direct$0 (excluded)$11,180+$11,180
Referral$4,210$3,920-$290
Affiliate$2,140$2,440+$300
Total$83,840$81,660--

(Totals differ slightly because first-touch attributes some revenue to channels for which the last touch was excluded; last-non-direct re-routes those dollars to the prior non-direct touch.)

The two columns tell different stories. ChatGPT and Direct are larger on first-touch because they often begin the journey. Email and Google are larger on last-non-direct because they more often precede conversion. Choose the column that matches the decision, and keep both visible.

Rendered rather than queried, the same join looks like this — each channel carrying the dollars its customers actually paid:

Attrifast dashboard showing Stripe revenue split by channel — ChatGPT, Google, Perplexity, Claude and Direct each on their own line with dollar amounts — alongside prompt-level AI visibility and competitor position tracking.

A complementary query that often surfaces actionable findings: channel-by-plan-tier, to see whether your acquisition channels map onto your revenue tiers cleanly. The plan ladder below belongs to the anonymized example SaaS, not to Attrifast:

ChannelBasic ($29/mo)Plus ($79/mo)Business ($199/mo)Enterprise (custom)Weighted ARPU
Google organic14264182$61
ChatGPT382481$69
Perplexity6951$98
Email843170$52
Paid social712240$46
Referral / partner1218123$112
Affiliate22610$42
Direct381241$58

Here, referrals and Perplexity bring more higher-tier customers, while affiliates and paid social lean toward Starter. That is why revenue by channel and average revenue per user answer different questions. A high-volume channel can look strong in total signups and weak in CAC payback.

With Attrifast

Attrifast runs exactly this join for you — session capture, Customer metadata write, and the revenue-by-channel query — from one script tag and a Stripe restricted key.

7-day free trial · $0 today · one script tag

Start free trial →See what it looks like →

The attribution model question: first-touch vs last-touch for SaaS

No attribution model is the truth. Each one assigns credit according to a rule, and each rule has a blind spot. Choose the model based on the length of your funnel and the decision the report needs to support.

ModelWhat it creditsStrengthBlind spot
First-touchThe channel that started the journeyCaptures discovery; rewards content and SEOIgnores the channel that actually drove conversion; over-rewards top-of-funnel
Last-touchThe channel of the final session before conversionCaptures conversion; rewards email and paid adsOver-credits direct re-visits and brand recall; ignores discovery
Last-non-direct touchThe last non-Direct channel before conversionBest balance for most SaaS; preserves AI/organic signal without over-crediting bookmarksStill ignores middle-of-funnel touches
LinearEqual credit to every touchHonest about multi-touch; no channel over-rewardedEqual-credit is itself an assumption; rewards channels with high touch count
Time-decayMore credit to recent touchesCaptures conversion bias without ignoring discovery entirelyDecay rate is arbitrary; small change shifts rankings
Position-based (U-shaped)40% first, 40% last, 20% middlePragmatic compromise; captures both endpointsMiddle channels under-credited
Data-driven (Markov, Shapley)Computed by algorithmTheoretically best; rewards real causalityRequires high data volume; opaque; rankings shift with re-training

For most bootstrapped SaaS teams, I recommend last-non-direct touch alongside a first-touch column. One shows the last meaningful channel before conversion; the other preserves the source of discovery. A dashboard that can switch between them is more useful than a single supposedly definitive number.

The decision tree I use in customer onboarding:

What decision is the attribution supporting?

Budget allocation for next quarter?

Content ROI measurement?

Sales rep / SDR credit?

Board reporting / investor update?

Use last-non-direct + first-touch dual columns; review both

Use first-touch; content's job is discovery

Use last-touch; rep gets credit for closing

Use linear or position-based; investors expect 'multi-touch'

Document which model supports each decision. Most SaaS teams need two or three views side by side; otherwise every weekly review turns into the same argument about whether email or content received too much credit.

A worked example from a real Attrifast customer, with the channels and dollars anonymized but the shape preserved:

ChannelSessions (qtr)First-touch revenueLast-touch revenueLast-non-direct revenueLinear revenue
Google organic48,200$58,400$34,210$51,820$46,180
ChatGPT9,180$24,710$8,420$19,310$17,610
Perplexity2,140$11,820$2,140$9,420$7,820
Direct12,400$4,210$44,180$0 (excluded)$14,210
Email8,420$3,840$28,140$25,820$18,420
Paid social14,200$14,210$11,820$13,640$12,820
Affiliate1,840$2,820$4,210$4,180$3,840
Total--$120,010$133,120$124,190$120,900

The table highlights four patterns.

Direct dominates last-touch. It receives $44,180, or 33% of the total. Most of those buyers discovered the brand elsewhere and returned through a bookmark or typed URL. The label is technically correct for the final visit but offers little guidance because you cannot buy more Direct traffic.

ChatGPT and Perplexity are much larger on first-touch. ChatGPT's first-touch revenue is 2.9 times its last-touch revenue; Perplexity's is 5.5 times. In this example, AI starts journeys more often than it closes them. A last-touch-only report makes the channel look 3-5 times smaller.

Plotted side by side, the model choice stops being an abstraction: the same quarter of Stripe revenue reorders almost completely depending on which column you report.

First-touch vs last-touch revenue by channel (one quarter, anonymized SaaS)
First-touch vs last-touch revenue by channel (one quarter, anonymized SaaS)

Source: Attribution-model comparison table in this article — anonymized Attrifast customer, one quarter; Total row omitted

Email shows the reverse. Its last-touch revenue is 7.3 times its first-touch revenue. Email often closes a journey that began elsewhere, so first-touch understates it and last-touch overstates it.

Linear and last-non-direct are similar at this scale. They rank some channels differently, but the totals stay in the same range. For an SMB SaaS, that difference may be smaller than the measurement error in the underlying visits.

Setting up Stripe-to-attribution in four steps

This is the architecture used in Attrifast, and it also works for a custom build. The pieces are familiar — a first-party ID, a session table, Stripe metadata, and an idempotent webhook — and an experienced backend engineer can usually assemble the basic version in about two days.

The four steps mapped to ownership, tools, and gotchas:

StepOwnerPrimary toolCommon gotcha
Establish first-party identifierFront-end engineerlocalStorage / first-party cookieCleared by browser extensions, breaks identity
Capture session and touch dataBack-end engineerYour own API + DBUTM tag inconsistency across teams pollutes channel data
Pass ID into Checkout SessionFull-stackStripe Checkout SDKID dropped if checkout opened in new tab without referer state
Webhook handler writes attributionBack-end engineerStripe webhooksNon-idempotent handler double-writes on retry

Step 1: Establish a first-party identifier on the visitor

Generate a UUID on the first visit, store it in localStorage or a first-party cookie, and attach it to later analytics events. This ID links the web session to the Stripe payment.

// tracker.js — first-party identifier setup
function getOrCreateFirstPartyId() {
  let id = localStorage.getItem('_afpid')
  if (!id) {
    id = crypto.randomUUID()
    localStorage.setItem('_afpid', id)
  }
  return id
}

The identifier stays on your domain and behaves more like a login-session ID than a cross-site advertising cookie. Many jurisdictions treat those differently, but confirm the consent requirements with your privacy review.

A reference channel-mapping table covering the common URL parameters and referer patterns the inferred_channel column should resolve to:

SignalPatternInferred channelNotes
utm_source=google&utm_medium=cpcUTMpaid-searchGoogle Ads click
utm_source=google&utm_medium=organicUTMorganic-searchManual organic tag (rare)
gclid=...URL parampaid-searchGoogle Click ID
fbclid=...URL parampaid-socialFacebook/Meta Click ID
li_fat_id=...URL parampaid-socialLinkedIn campaign ID
ttclid=...URL parampaid-socialTikTok Click ID
msclkid=...URL parampaid-searchMicrosoft Ads Click ID
Referer google.com (no UTM)Refererorganic-searchGoogle SERP click
Referer bing.comRefererorganic-searchBing organic
Referer chatgpt.com / chat.openai.comRefererai-searchChatGPT citation
Referer perplexity.aiRefererai-searchPerplexity citation
Referer claude.aiRefererai-searchClaude citation
Referer gemini.google.comRefererai-searchGemini citation
Referer linkedin.comReferersocialLinkedIn organic
Referer t.co / x.com / twitter.comReferersocialX / Twitter
Referer reddit.comReferersocial-communityReddit
Referer news.ycombinator.comReferersocial-communityHacker News
Referer producthunt.comReferersocial-communityProduct Hunt
utm_medium=emailUTMemailEmail campaign
Referer mail.google.com / outlook.live.comRefereremail (webmail)Webmail client
No referer, no UTM, root URLEmptydirectTrue direct or bookmark
No referer, deep URL, FAQ-shaped pageBehavioralsuspected-aiLikely AI citation click

Step 2: Capture session and touch data on your server

Send each pageview and meaningful event to your server. Store one row per visit in sessions and one row per channel-bearing event in touches. A minimal session schema looks like this:

ColumnTypeNotes
idUUIDPrimary key
first_party_idUUIDJoin key from the tracker
started_attimestamptzFirst event in session
ended_attimestamptzLast event in session (rolling)
utm_sourcetextFrom URL params, nullable
utm_mediumtextFrom URL params, nullable
utm_campaigntextFrom URL params, nullable
utm_contenttextFrom URL params, nullable
utm_termtextFrom URL params, nullable
referertextdocument.referrer or HTTP Referer
referer_hosttextParsed hostname for fast filtering
landing_pagetextFirst URL in session
user_agenttextFor bot exclusion
ip_countrytextGeo-IP at session start (no IP stored)
device_typetextmobile/desktop/tablet
inferred_channeltextComputed at write time (organic/paid/ai/email/direct)

inferred_channel maps the UTM fields, referrer host, and behavioral signals to your channel names. Computing it when you write the visit keeps later dashboard queries simple and fast.

Step 3: Pass the first-party ID into the Stripe Checkout Session

When you create the Checkout Session, add the first-party ID to its metadata. That field connects your web tracking record to Stripe.

// server: create checkout session with attribution carrier
const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  success_url: 'https://yourapp.com/welcome',
  cancel_url: 'https://yourapp.com/pricing',
  metadata: {
    first_party_id: req.body.firstPartyId, // from client, validated
  },
  client_reference_id: req.body.firstPartyId, // alternate field, redundant by design
})

Use metadata.first_party_id as the main carrier. I also write the same value to Stripe's client_reference_id [17] because it appears in more places in the Dashboard. Either field is enough; using both adds a simple fallback.

For Stripe Billing customers who do not use Checkout (direct PaymentIntents, embedded forms, etc.) the same pattern applies: write the first-party ID into PaymentIntent metadata or Customer metadata at create time. The principle is the same regardless of integration shape: the first-party ID must travel with the checkout artifact so the webhook handler can join it back to a session.

The Payment Links case

Payment Links are different because the checkout URL is static; your server does not create a new Session when someone clicks. Stripe provides two ways to carry attribution through that flow [26].

First, a Payment Link can store fixed metadata on the link, PaymentIntent, or Subscription it creates. Use this for campaign constants. A link made for the March newsletter can carry attr_campaign: "march-newsletter", and every resulting payment inherits it.

Second, append the visitor ID as client_reference_id in the URL. Stripe copies it to the resulting Checkout Session, where the same webhook handler can read it. Keep the value to letters, numbers, dashes, or underscores and under 200 characters; a UUID fits. Stripe also carries the five standard UTM parameters, up to 150 characters each.

// client: decorate a Payment Link with the visitor's first-party ID
const url = new URL('https://buy.stripe.com/xxxxxxxx')
url.searchParams.set('client_reference_id', getOrCreateFirstPartyId())
window.location.href = url.toString()

The trade-off is simple. Fixed link metadata tracks the campaign without JavaScript and survives when someone forwards the URL. client_reference_id connects the full visitor history, but only when your tracker ran before the click.

Step 4: Webhook handler joins the conversion to the session and writes attribution

The webhook now reads the first-party ID, finds the matching visits, calculates first-touch and last-non-direct channels, and writes the summary to Customer metadata. Future Stripe reports can use those fields directly.

The full four-step pipeline at a glance:

Webhook HandlerStripeYour ServerTracker (browser)VisitorWebhook HandlerStripeYour ServerTracker (browser)VisitorVisits pageGet or create first-party UUIDPOST /track {first_party_id, utm, referer}Insert sessions row, touches rowBrowses, eventually clicks CheckoutPOST /checkout {first_party_id}stripe.checkout.sessions.create({metadata:{first_party_id}})Hosted checkoutPayswebhook checkout.session.completedLook up session by first_party_idstripe.customers.update({metadata:{attr_first_channel, attr_last_channel}})Insert conversions row

An experienced backend engineer can usually build the basic flow in 1-2 days and roughly 300 lines across the tracker, API, schema, and webhook. Most of that time goes into edge cases: duplicate Checkout sessions, refunds and repeat payments, cleared identifiers, and purchases completed on another device.

Tool comparison: Stripe-native attribution tools in 2026

The main options range from a DIY build to tools costing more than $1,500 per month. The best fit depends on your business model, paid-ad spend, and whether a data warehouse and data team already exist.

ToolBest forNative Stripe?E-comm focus?SaaS focus?Cookieless?Entry priceFree trial?
AttrifastSMB SaaS / DTC with under $100k/mo ad spendYes (restricted API key + webhooks)YesYesYes$9.99/mo Starter, $49/mo Pro7 days
SegMetricsMid-market info-product and SaaSYes (via integrations)LimitedYesNo (uses pixels)$57/mo Launch [8]14 days
Wicked ReportsE-comm and info-product with paid ad heavy mixYesYesLimitedNo$499/mo Measure [9]No
TripleWhaleShopify DTC with $50k+/mo paid social spendIndirect (via Stripe app)Yes (Shopify-first)NoNoFree tier, then $179/mo Starter [10]Free tier
Polar AnalyticsShopify mid-marketIndirectYes (Shopify-only)NoNoGMV-quoted, ~$300+/mo [11]No
BaremetricsStripe SaaS metrics dashboardYes (deep)NoYesn/a (no tracker)$75/mo Launch [12]14 days
ChartMogulStripe SaaS metrics with cohort depthYesNoYesn/a (no tracker)Free under $10k MRR, then $59/mo [18]Free tier
ProfitWell (now Paddle Retain)Free SaaS metrics; subscription analyticsYes (Stripe-friendly)NoYesn/aFree tiern/a
NorthbeamEnterprise multi-touch attributionYesYesLimitedPartial$1,500/mo Starter [13]No
DIY: Sigma + custom trackerEngineering teams with capacityYes (Sigma is Stripe-native)BothBothYesSigma from $15/mo by charge volume [3]30 days Sigma
DIY: BigQuery + SegmentMid-market with existing warehouseVia Stripe Data PipelineBothBothYes (depending)$120+/mo (Segment)n/a
GA4 free + Stripe exportOperators on shoestring budgetManualBothBothNo$0 + timen/a

I re-checked every public entry price on 31 July 2026. Eight of the twelve rows changed since May. Polar no longer publishes a flat rate and quotes by annual GMV, so its figure is an outside estimate rather than a listed price.

Before you compare prices, separate metrics products from attribution products.

Baremetrics, ChartMogul, and ProfitWell (Paddle Retain) are Stripe metrics products. They report MRR, churn, LTV, expansion, and cohorts, but they do not track the visit that preceded payment. They can report a channel after you write it to Stripe metadata. If you already use Baremetrics, pair it with a separate capture layer rather than replacing a dashboard you like.

SegMetrics and Wicked Reports are full attribution stacks. SegMetrics now starts at $57/month [8], although its broader model library begins on the $197 Grow tier. Wicked Reports moved its entry tier to $499/month [9], which makes it a better fit for mid-market teams than small SaaS companies.

Triple Whale and Polar are built around Shopify. Triple Whale [10] can connect Stripe, but its strongest workflows center on Shopify, Meta, and TikTok. It now offers a free Founders tier and a $179/month Starter plan. Polar [11] is Shopify-only and quotes by GMV. Neither is the default choice for a non-Shopify SaaS.

Northbeam is enterprise. It now publishes a Starter plan at $1,500/mo [13] rather than quoting everything privately, with pageview-based scaling above that. Designed for $500k+/year ad spend with multi-touch attribution across paid channels. Above that scale Northbeam, Rockerbox, and similar tools win on capability. Below it the price-to-capability ratio is wrong for most SMBs.

DIY with Sigma is a real option. Sigma now charges by successful monthly payments rather than events [3]: $15/month for up to 250 charges, $60 up to 10,000, $225 up to 25,000, and $450 above that, plus overages. This can make reporting inexpensive for SaaS. You still have to build the tracker, session table, and webhook handler, so budget 1-2 weeks of engineering and ongoing maintenance.

GA4 plus a Stripe export is common but fragile. An analyst matches charges to GA4 sessions by UTM tag in a monthly spreadsheet. It can work at low volume, but missing tags and longer SaaS journeys make the join unreliable as the business grows.

A simpler decision framework, ignoring price for a moment:

Your shapeBest fitWhy
SMB SaaS, $0-$2M ARR, mostly organicAttrifastStripe-native, AI-aware, cookieless, cheapest
SMB SaaS, $0-$2M ARR, paid-heavyAttrifast or SegMetricsAttrifast if budget-constrained; SegMetrics if multi-touch matters more
Mid-market SaaS, $2-$10M ARRSegMetricsMore mature attribution model library
SMB DTC, non-ShopifyAttrifastFew alternatives that work outside Shopify
SMB DTC, Shopify, low ad spendPolar or AttrifastPolar if Shopify-deep; Attrifast if Stripe-deep
Mid-market DTC, Shopify, heavy paid socialTripleWhaleBest Meta/TikTok integration in this segment
Enterprise SaaS or DTC, $500k+/yr ad spendNorthbeamMulti-touch sophistication justifies the price
SaaS team that needs metrics + attributionBaremetrics + AttrifastPair Stripe metrics with attribution capture
Engineering-heavy team, infra in placeSigma + custom trackerDIY if you have the cycles

Prices change much faster than product fit. Eight of twelve rows changed between the May and July checks. These figures reflect public pages on 31 July 2026 [8][9][10][11][12][13][18], so verify them before you buy. The use-case guidance should age more slowly.

SaaS vs e-commerce: how Stripe attribution differs

The architecture is the same. The webhook events you anchor on, the model you default to, and the metrics you produce all differ.

DimensionSaaS Stripe attributionE-commerce Stripe attribution
Primary webhook for capturecustomer.subscription.created (or trial signup)checkout.session.completed (or payment_intent.succeeded)
Conversion time from session to revenueDays to months (trials, sales cycles)Same-session or short-window
Primary attribution metricMRR by channelOrder revenue by channel, repeat-purchase rate
Default modelLast-non-direct touch with first-touch columnLast-click for performance ads, first-touch for content
Refund considerationLow (refunds rare; mostly involuntary churn)High (refund and return rates vary by channel)
Cohort analysisCritical (retention drives LTV)Important (repeat-purchase drives LTV)
LTV computationSum of invoice.payment_succeeded over customer lifetimeSum of payment_intent.succeeded per customer
Stripe metadata fields neededFirst-touch, last-touch, activation channel, expansion channelFirst-touch, last-touch, order channel, ad campaign ID
Multi-touch importanceHigh (sales cycles span many touches)Low to medium (impulse purchases dominate)
Time decay relevanceHigh (recency matters more than first-touch)Medium
Sales rep attributionCommon in higher-ACV B2BRare
Coupon-as-attribution-signalUseful for affiliate/influencerCritical for influencer codes
Cart abandonment roleLess relevantCritical (email recovery drives big channel slice)
Trial expiration roleCriticaln/a

The biggest difference is time. A SaaS buyer may read an article in February, start a trial after an X post in March, activate after a sales call in April, and upgrade in May. Several touches may deserve credit. Ecommerce journeys are usually shorter, so clean order-level capture often matters more than a sophisticated multi-touch model.

The metadata pattern I run differs for the two shapes. SaaS:

Customer.metadata:
  attr_first_channel: "organic-search"
  attr_first_source: "google"
  attr_first_at: "2026-02-14T..."
  attr_last_channel: "ai-search"
  attr_last_source: "chatgpt"
  attr_last_at: "2026-03-22T..."
  attr_activation_channel: "email"
  attr_activation_at: "2026-04-09T..."

Subscription.metadata:
  attr_signup_plan: "starter"
  attr_expansion_at: null  // updated on plan change

E-commerce:

Customer.metadata:
  attr_first_channel: "paid-social"
  attr_first_source: "meta"
  attr_first_campaign: "spring-2026-prospecting"

Order (PaymentIntent).metadata:
  attr_order_channel: "paid-social"
  attr_order_source: "meta"
  attr_ad_id: "120217xxxxxxxx"
  attr_first_party_id: "uuid..."

For SaaS, attribution lives mostly on the Customer object and is sticky across the lifecycle. For ecommerce, attribution lives mostly on the order-level object (PaymentIntent) because the channel that drove the third order may be different from the channel that drove the first.

A before/after revenue allocation table from a real Attrifast SaaS customer migration, showing how channel attribution shifted once the four-step pipeline replaced their GA4-export spreadsheet:

ChannelBefore (GA4 + Stripe spreadsheet)After (Attrifast 4-step pipeline)Delta
Google organic$34,210$42,180+$7,970
Direct$44,180 (overstated)$0 (excluded)-$44,180
ChatGPT$0 (invisible)$14,180+$14,180
Perplexity$0 (invisible)$4,820+$4,820
Email$8,210$11,820+$3,610
Paid social$9,180$9,310+$130
Referral$2,140$4,210+$2,070
Affiliate$1,820$2,140+$320
AI Overviews / Gemini$0 (invisible)$2,420+$2,420
Other / unattributed$1,920$400-$1,520

Before the migration, the board report ranked Direct and paid social as the largest revenue sources. After the join was fixed, the order became Google organic, ChatGPT, email, paid social, and Perplexity. That evidence supported a larger content budget and a smaller paid-social budget.

The migration did not change the revenue. It revealed three sources that the spreadsheet had reported as zero and redistributed the oversized Direct bucket.

Revenue by channel before and after the four-step pipeline
Revenue by channel before and after the four-step pipeline

Source: Before/after migration table in this article — anonymized Attrifast SaaS customer; the 'Other / unattributed' residual row is omitted

MRR by channel: the metric most founders skip

The most useful output is MRR by channel over time. Baremetrics can show MRR, and GA4 can show sessions. The valuable report joins them: how much recurring revenue came from Google, ChatGPT, email, paid social, referrals, and other channels, and how that mix changes each month.

What this chart lets you decide:

QuestionWithout MRR-by-channelWith MRR-by-channel
Should we double content investment?"Our SEO traffic is up 30%""Our SEO-attributed MRR is up $14k/mo, +28% qoq"
Did the LinkedIn ads pay off?"We spent $8k and got 412 leads""We spent $8k and acquired $4,200/mo in new MRR; CAC payback is 14 months"
Is ChatGPT actually driving revenue?"Direct is up so brand is working""ChatGPT-attributed MRR is $19k/mo, +$11k qoq"
Which channel should we cut?"Paid social has high CPC""Paid social has highest CAC and lowest 6-month LTV"
Where should the next hire go?"We need more leads""Content drives 38% of MRR; we should hire a writer not an SDR"

The shape of the report in the canonical Attrifast dashboard format, with example numbers:

ChannelNew MRR (last 30d)Expansion MRRChurned MRRNet New MRR% of Total Net
Google organic$14,820$1,420-$2,180$14,06041%
ChatGPT$6,420$480-$420$6,48019%
Email nurture$4,180$920-$680$4,42013%
Paid social (Meta)$3,820$210-$1,410$2,6208%
Perplexity$2,140$80-$120$2,1006%
Referral / partner$1,920$310-$240$1,9906%
LinkedIn ads$1,820$180-$640$1,3604%
Affiliate$810$40-$60$7902%
Direct (excluded)$0--------
Total$35,930$3,640-$5,750$33,820100%

Read the columns separately. New MRR measures acquisition, expansion MRR captures upgrades, churned MRR removes lost subscriptions, and net new MRR combines them. Paid social contributes $3,820 in new MRR here but only $2,620 net because those customers churn faster. You can see that difference only when the acquisition channel stays attached throughout the customer lifecycle.

As a share of the $33,820 in net new MRR, the split is the number that actually goes on the board slide — and two of the top five slices are AI engines.

Share of net new MRR by channel (last 30 days)
Share of net new MRR by channel (last 30 days)

Source: '% of Total Net' column of the MRR-by-channel report table in this article; Direct is excluded by the last-non-direct model

Run the report by quarter for trend, by cohort for LTV, and by plan for customer mix. Once the acquisition channel is stored on the Customer, each view becomes a straightforward query.

LTV-by-channel for the same business, with a 12-month observation window:

ChannelAvg ACV (annualized)6-mo retention12-mo retentionComputed LTV (24mo)CAC (last 90d)LTV/CAC
Google organic$1,42089%78%$2,180$42 (content cost)51.9x
ChatGPT$1,64091%82%$2,490$0 (no direct spend)n/a
Email nurture$1,14084%71%$1,690$14 (tool + ops)120.7x
Paid social$98071%52%$1,180$2145.5x
Perplexity$1,82093%84%$2,720$0n/a
Referral$1,54088%76%$2,290$80 (referral incentive)28.6x
LinkedIn ads$1,72076%58%$2,180$4105.3x
Affiliate$89068%49%$1,040$112 (commissions)9.3x

The LTV table changes the conclusion. Paid social and LinkedIn look respectable on gross revenue but have the lowest LTV/CAC ratios because those cohorts churn faster. Organic sources have little direct acquisition spend in this example. Cohort economics can therefore reverse the recommendation you would make from revenue alone.

Common Stripe attribution mistakes

These are the ten implementation mistakes I see most often, with a fix for each.

Mistake 1: Storing attribution only on the Subscription, not on the Customer. When a customer upgrades, the new Subscription gets new metadata and the original attribution is lost. Fix: write first-touch to Customer metadata at first conversion and protect it from overwrites. Write Subscription-specific attribution to Subscription metadata for expansion analysis.

Mistake 2: Using customer.created as the attribution write event. customer.created fires when the Customer object is created, which may be before checkout completes (for delayed-payment flows) or even at trial signup. Attribution data is not always populated yet at that moment. Fix: use checkout.session.completed as the canonical first-write event; treat customer.created as the lock event for first-touch.

Mistake 3: Not handling webhook retries. Stripe retries on 5xx and on timeouts. A non-idempotent handler will double-write attribution, double-count revenue in your own database, or worse, overwrite the first-touch with the last-touch on the second retry. Fix: idempotency table keyed on event.id, check on entry.

Mistake 4: Letting client_reference_id carry a UTM string instead of a first-party identifier. I have seen teams put utm_source=google&utm_medium=cpc directly into client_reference_id. This works for the immediate session but loses every other touch the visitor had before checkout. Fix: client_reference_id carries the first-party ID; the full touch history lives in your database.

Mistake 5: Trusting the front-end to compute attribution. Client-side attribution computation is fragile (ad blockers, JS errors, session state loss). Fix: capture the raw inputs (UTM, referer, landing page, timestamp) on the server; compute channel only at the point of writing to Stripe.

Mistake 6: Conflating Customer and Subscription metadata. Stripe does not propagate metadata between objects. Setting it on Customer does not set it on Subscription, and vice versa. Fix: write to both in the webhook handler if you want both queryable.

Mistake 7: Hitting the 50-key metadata limit by storing too much. Once you have 50 keys on a Customer you cannot add more. Teams accumulate metadata over years and hit the wall. Fix: store the summary (channel, source, campaign) in Stripe; keep the full history in your own database. Stripe metadata is the join key, not the warehouse.

Mistake 8: Not capturing the cancel/churn channel. When customer.subscription.deleted fires you can capture the channel the customer was on (from existing metadata) plus the moment they churned. Without this, the net-MRR-by-channel chart is impossible to build. Fix: handle customer.subscription.deleted and write a churn event to your own database with the channel preserved.

Mistake 9: Ignoring refunds in ecommerce attribution. Paid social channels have higher refund rates than organic on most DTC sites. Crediting paid social with gross revenue overstates ROI by 10-30% at scale. Fix: handle charge.refunded and subtract from the original channel's revenue in reporting.

Mistake 10: Reporting attribution without the methodology disclosure. "ChatGPT drove $19k MRR last quarter" without saying which model, which window, and which capture method invites the rest of the team to argue rather than act. Fix: every attribution report includes the model name (e.g., "last-non-direct, 90-day window, server-side fingerprinting") in the footer.

A quick-reference mistake-to-fix table for the patterns above:

MistakeSymptomFixTime to fix
Attribution on Subscription, not CustomerFirst-touch lost on upgradeWrite to both, protect Customer first_touch1 hour
Use customer.created as primary write eventAttribution data missing on early customersSwitch to checkout.session.completed30 min
Non-idempotent webhook handlerDouble-counted revenue on retryAdd idempotency table on event.id1 hour
UTM crammed into client_reference_idLost touch historyUse first-party UUID as carrier2 hours
Front-end channel inferenceAd-blocker drops attributionMove inference server-side4 hours
Customer vs Subscription metadata confusionReports inconsistentWrite both, document convention1 hour
Hit 50-key metadata limitNew writes fail silentlyMove history to your DB, summary in Stripe1 day
No churn channel captureNet MRR by channel impossibleHandle customer.subscription.deleted2 hours
Refunds ignored in ecommercePaid social ROI overstated 10-30%Handle charge.refunded, subtract from channel2 hours
Report without methodology footerTeam argues about numbersAdd model/window/method to every report15 min

When to use Sigma / BigQuery / DIY vs a tool

Build versus buy depends on engineering capacity, company scale, and how custom the model needs to be.

Your situationBuy or buildWhy
<$1M ARR, no dedicated data engineerBuy (Attrifast, SegMetrics, etc.)Engineering time is more expensive than any tool subscription at this scale
$1-5M ARR, 1-2 engineers, no warehouseBuySame reason. Tool gets you 80% of the value in 1 hour vs 2 weeks
$5-20M ARR, has data engineerHybrid: tool for capture, warehouse for analysisCapture is the hard part; vendor solves it. Analysis can move to dbt/BigQuery later
$20M+ ARR with warehouseBuild on warehouse + SigmaCustom models, custom segments, and integration with rest of data stack
$500k+/yr ad spendBuild or Northbeam-classMulti-touch sophistication justifies dedicated team or enterprise tool
Pre-revenue or early validationDon't bother yetGet to product-market fit first; attribution is for optimization, not discovery
Regulated industry (healthcare, finance)BuildCompliance review of any vendor is often more painful than building

If attribution itself differentiates the business, owning the system may be worth the engineering cost. If attribution supports decisions but is not the product, a tool will usually get you to useful data sooner.

The Sigma-DIY architecture, for the teams that want to roll their own:

events

webhooks

writes metadata

Sigma

Tracker

Your API

Sessions table

Touches table

Stripe

Webhook Handler

Conversions table

Sigma reports

Your dashboard

A DIY setup has three parts to maintain: the tracker, webhook handler, and Sigma reports. Sigma cost ranges from $15/month for up to 250 monthly charges to $450/month above 25,000, plus overages [3]. For most subscription SaaS teams, engineering and maintenance cost more than the query layer.

Entry-level vendor tools cost roughly $10-$60 per month. For many SMB SaaS teams, that stays cheaper than a custom build for 6-12 months. Beyond that point, an in-house system may make sense if a data engineer has the capacity to own it.

Pricing comparison

The 2026 pricing landscape for Stripe-touching attribution and metrics tools, with the caveats that pricing changes frequently and vendors offer custom deals. All numbers from public pricing pages, verified 31 July 2026.

ToolEntry tierMid tierEnterpriseAnnual discount?What you get at entry
Attrifast$9.99/mo (Starter, 7-day free trial, $0 due today — no free tier)$49/mo (Pro)Agency (waitlist)Yes, 2 months freeFull attribution + Stripe revenue, all channels including AI
SegMetrics Launch [8]$57/mo$197/mo (Grow)$397/mo (Scale), then customYes, 2 months freeFirst/last/linear attribution; no AI engines as a default channel
Wicked Reports Measure [9]$499/mo$699/mo (Scale)$4,999+/moYesMulti-touch; ad-spend-focused
TripleWhale [10]Free tier, then $179/mo (Starter)$259/mo (Advanced)$539+/mo customYes, 2 months freeShopify-first; Meta/TikTok focus
Polar Analytics [11]~$300+/mo, GMV-quotedQuoteCustomYesShopify-only mid-market
Baremetrics Launch [12]$75/mo ($49 annual)$255/mo (Growth)$1,152/mo (Scale)YesStripe SaaS metrics, no attribution capture
ChartMogul [18]Free under $10k MRR, then $59/mo$99/mo (Pro)CustomYesStripe SaaS metrics with cohorts
ProfitWell / Paddle RetainFree (metrics)Paid (retention products)Customn/aFree SaaS metrics
Northbeam [13]$1,500/mo (Starter)CustomCustomYesEnterprise multi-touch
RockerboxQuote, $1,500+/moCustomCustomYesEnterprise multi-touch
Hyros~$230/mo entry, annual commitment, demo-gatedCustomCustomYesInfo-product / paid ads heavy
GA4 + custom dashboardFreeFree$50k+ (GA360)n/aWeb analytics, channel data, no Stripe join
Plausible Analytics$9/mo$29/mo$89/moYesPrivacy-first web analytics, no Stripe revenue join
Fathom Analytics$15/mo$44/mo$99/moYesPrivacy-first web analytics, no Stripe revenue join
Stripe Sigma (DIY)$15/mo up to 250 charges$60/mo up to 10k charges$450/mo above 25k chargesYesReporting layer over Stripe data

The price gap narrowed this year. For a SaaS below $5 million ARR, SegMetrics at $57/month offers more attribution models, while Attrifast at $9.99/month emphasizes AI-engine attribution and a shorter setup. If model depth matters, SegMetrics now deserves a serious look instead of an automatic rejection on price.

Paid entry tiers run from $9.99 to $1,500 per month. The chart makes that spread easier to see than the feature table does.

Entry-tier monthly price — Stripe attribution and metrics tools (USD)
Entry-tier monthly price — Stripe attribution and metrics tools (USD)

Source: Pricing table in this article, read from each vendor's own pricing page on 31 July 2026; GMV-quoted Polar and demo-gated Hyros omitted because neither publishes a flat entry rate

A normalized "cost per attributable Stripe dollar" table, assuming a $100k MRR business with the tool capturing the full attribution layer:

ToolAnnual costAnnual revenue trackedCost as % of revenue
Attrifast (Starter)$120$1.2M0.010%
Attrifast (Pro)$588$1.2M0.049%
SegMetrics (Launch)$684$1.2M0.057%
Wicked Reports (Measure)$5,988$1.2M0.499%
TripleWhale (Starter)$2,148$1.2M0.179% (Shopify only)
Polar$3,600+$1.2M0.300%+ (Shopify only)
Northbeam (Starter)$18,000$1.2M1.5%
DIY Sigma + custom$20,000+ (mostly engineering)$1.2M1.7%+ year one

Do not choose from this table on price alone. Start with the question the tool must answer, then buy the least expensive option that answers it reliably. A cheap tool that misses the needed model or integration is not a saving.

I would not choose Attrifast for a Shopify DTC brand spending more than $200,000 a month on Meta; Triple Whale's ad integration is deeper. An enterprise B2B team that needs Markov or Shapley models should consider Northbeam. A company with a data engineer and a working BigQuery warehouse may prefer the flexibility of a DIY Sigma setup.

Attrifast is designed for SMB SaaS and DTC companies using Stripe, spending up to roughly $200,000 a month on ads, and trying to recover AI traffic that GA4 misses. It favors a quick, self-serve report over enterprise modeling depth.

What this looks like inside Attrifast

Disclosure: I built Attrifast. It packages the tracking flow described above into one dashboard. Connect Stripe with a restricted API key, add the 4 KB tracker, and the revenue-by-channel report begins filling after Stripe events arrive. ChatGPT, Perplexity, Claude, and Gemini appear as separate channels rather than Direct. The Stripe connection docs list the required key scopes and Checkout Session field.

Attrifast writes the same attr_first_channel and attr_last_channel fields described in this guide. The summary remains in your Stripe Customer metadata if you stop using the product; the dashboard and detection logic are the service, not ownership of the data.

Starter costs $9.99/month for one site and 50,000 monthly events. It includes event capture, first-touch and last-non-direct attribution, MRR by channel, AI-source detection, and the Stripe dashboard. Pro costs $49/month for 3 sites, 100,000 events, five seats, and deeper AI-visibility reporting. Both begin with a 7-day trial; annual billing charges for ten months, or $99.90 and $490 respectively. There is no free tier. See Attrifast, the Stripe attribution feature page, and Stripe marketing attribution for product details.

I built it after spending 18 months reconciling GA4, Stripe exports, and Baremetrics for my own SaaS. The numbers kept disagreeing. Writing attribution into Customer metadata at capture time fixed the join, and the same pattern became the product.

Limitations

This guide has six important limits:

  • Multi-touch attribution beyond first/last/linear. Markov chain and Shapley value models are real but require both more data volume and more methodological care than most SMB SaaS can support. The numbers in this article assume position-based models; data-driven models require their own treatment.
  • Cross-device journeys without identity stitching. A buyer who reads your blog on mobile and pays on desktop is a known undercount in any cookieless system without account-based identity. Treat this as a known measurement bound.
  • Offline conversions and sales-assisted deals. Higher-ACV B2B with sales reps in the loop need CRM integration (HubSpot, Salesforce) to capture the rep-influence layer. Stripe attribution alone undercounts sales-influenced revenue.
  • Affiliate, partner, and influencer attribution. Coupon-as-attribution-signal works for most cases; the edge cases (multiple coupons stacked, deal-site coupon attribution conflicts) are real and need their own playbook.
  • Privacy and consent considerations. The first-party identifier pattern is not subject to most cross-site cookie rules but the GDPR/CCPA picture is jurisdictional. Verify with your privacy review before deployment.
  • The pricing numbers in this article are 31 July 2026 snapshots. Eight of the twelve vendors tracked here repriced or repackaged between the May and July checks, which should tell you how much weight to put on any pricing table older than a quarter. Verify on the vendor's own page before making a procurement decision.

FAQ

Can I do Stripe revenue attribution natively in the Stripe dashboard?

No. Stripe Dashboard, Sigma, and the Reports API expose every financial dimension of a charge, subscription, invoice, payout, and dispute, but no marketing channel field. The Customer object has a metadata bag, the Checkout Session has a metadata bag, and the Subscription has a metadata bag, and Stripe will dutifully store whatever attribution string you put in those bags. Stripe will not populate them for you. The mental model that sticks: Stripe is a perfect ledger of what happened to the money once the buyer reached the form. Attribution is the entirely separate question of how the buyer reached the form, and Stripe has no visibility into the upstream session.

Which Stripe webhook events do I need for attribution?

Three events do 95% of the work for most SaaS and ecommerce sites. checkout.session.completed fires when a Checkout Session converts and is the cleanest moment to write the first-touch and last-touch channel into Customer metadata, because it carries the session metadata you set at create time. customer.subscription.created fires on the first paid subscription and lets you capture activation-time attribution distinct from the trial-signup attribution. invoice.payment_succeeded fires on every recurring renewal and is where you account for MRR-by-channel over time, especially when churn and reactivation matter. Optional: charge.refunded, customer.subscription.deleted, and customer.subscription.updated if you want net-MRR by channel rather than gross.

First-touch or last-touch for SaaS Stripe attribution?

For most bootstrapped SaaS in 2026, last-non-direct touch with a first-touch override flag is the practical default. Pure last-touch over-credits brand recall and direct re-visits. Pure first-touch over-credits the top-of-funnel channel that started the journey but might not be the one that converted. Last-non-direct preserves the channel that actually drove the meaningful action while ignoring the direct re-visit that closed it. The first-touch override is the column you keep around so you can attribute the originating channel separately for content-marketing ROI questions. I run a dual-write model in Attrifast for this reason: attr_first_channel and attr_last_channel as two fields, then let the dashboard pivot on either.

How does Stripe attribution differ for SaaS vs e-commerce?

Three structural differences. First, the conversion event. SaaS trials convert to paid weeks later, often after several email touches; ecommerce converts in a single session more often than not. The webhook you anchor attribution on differs: customer.subscription.created for SaaS, checkout.session.completed for ecommerce. Second, recurrence. SaaS revenue is MRR-by-channel over time, not a single transaction; ecommerce is order-by-channel with optional repeat-purchase analysis. Third, refunds and disputes. SaaS attribution rarely cares about refund-by-channel; ecommerce attribution needs net-revenue-by-channel because chargebacks, refunds, and returns concentrate disproportionately in certain channels (paid social, in particular).

Why is Stripe Sigma not enough for attribution?

Sigma is excellent at every question that lives inside the Stripe object model. How much MRR by plan, by country, by trial cohort, by tax jurisdiction. Sigma cannot answer how much MRR by marketing source because that field does not exist on any Stripe object unless you wrote it there. You can store attribution in Customer metadata, query it via Sigma, and build the report. That is what every team that runs Sigma-based attribution ends up doing. The cost is that the attribution capture pipeline (the part that decides what to write into metadata before the customer hits Stripe) is the hard part, and Sigma does not help with it. Sigma is the reporting layer. The capture layer is the missing piece.

Should I store attribution in Customer metadata or Subscription metadata?

Both, written at different lifecycle points, with Customer as the source of truth for first-touch and Subscription as the source of truth for plan-change attribution. Customer metadata is written once at customer.created and lives forever; ideal for the originating-channel field that should not be overwritten when a customer upgrades 18 months later. Subscription metadata is written at each new Subscription; ideal for the channel that drove the specific plan they are on now, which matters when you run expansion campaigns. Checkout Session metadata is the transport layer in between; you write to it at session create, copy it forward into Customer and Subscription metadata in the webhook handler. Stripe metadata is per-object and is not automatically propagated; the propagation is your job.

Will Stripe ever build native marketing attribution?

Unknown, and probably no, in any way that satisfies SMB needs. Stripe has been deliberate about staying out of marketing-analytics. The product surface is payments, billing, fraud, identity, banking. Acquisition is treated as not their problem, and the Stripe Atlas content corpus has historically referred operators out to dedicated attribution tools. The closest thing to a native answer is Stripe Sigma plus your own metadata convention, which works but requires you to build the capture layer separately. The bet I make at Attrifast is that the capture layer is a 5-year wedge product Stripe will not eat. The bet could be wrong; Stripe has surprised the market before.

What is the minimum stack for cookieless Stripe attribution?

Four pieces. A first-party identifier scoped to your own domain (UUID in localStorage or first-party cookie). A session-table row on your server that captures (first-party identifier, UTM tags, referer, landing page, timestamp) on every visit. A Stripe Checkout Session created with metadata that carries the first-party identifier forward. A webhook handler on checkout.session.completed that reads the identifier from the session metadata, looks up the matching session row, computes first-touch and last-touch channels, and writes them into Customer metadata. None of those pieces require a third-party cookie or a consent banner under most jurisdictions; the first-party identifier is functionally similar to a login cookie.

What does Stripe attribution tooling cost in 2026?

Entry prices re-verified 31 July 2026. Attrifast is $9.99/mo on Starter and $49/mo on Pro, both with a 7-day free trial and $0 due today; yearly billing charges ten months instead of twelve, so Starter is $99.90/year and Pro is $490/year. There is no free tier. SegMetrics repackaged downward and now starts at $57/mo on Launch, with Grow at $197/mo. Wicked Reports moved the other way: its entry Measure plan is $499/mo. Triple Whale now has a free Founders tier with Starter at $179/mo. Baremetrics starts at $75/mo on Launch, ChartMogul is free below $10k MRR and $59/mo on Starter, and Northbeam's published Starter is $1,500/mo. Stripe Sigma is no longer priced per event; it is a charge-volume subscription starting at $15/mo for up to 250 charges. Seven of those eight competitor figures changed between the May and July 2026 checks, so treat any pricing table older than a quarter as a starting point for your own verification rather than an answer.

How do I attribute revenue from ChatGPT or other AI engines via Stripe?

Same architecture, with the addition of AI-engine detection at the tracker layer. The tracker checks the referer against a known AI-engine domain list (chatgpt.com, perplexity.ai, claude.ai, gemini.google.com, copilot.microsoft.com) and tags the session accordingly. For the 65-80% of AI clicks that arrive without a referer (because the AI client stripped it), behavioral fingerprinting on deep-page entries from new visitors catches most of the remainder. The webhook handler then writes attr_first_channel: "ai-search" and attr_first_source: "chatgpt" into Customer metadata exactly the same way it would write attr_first_channel: "organic-search" for a Google referral. The practical track-ChatGPT-traffic playbook covers the detection layer in depth.

Can I retrofit attribution onto existing Stripe customers without historical data?

Partially. For customers who already exist, you can backfill attribution from any other source you have (CRM notes, manual rep entry, an export from your old analytics tool, even the email domain pattern for B2B) and write it into Customer metadata. The backfill is necessarily imperfect because the original touch data does not exist. For new customers from the day you ship the tracker forward, attribution is captured cleanly. Most teams accept that the first 30-90 days of attribution data is a transition period with incomplete history; budget decisions in that window should weight legacy customers separately.

What happens to attribution when a customer churns and resubscribes?

This is a model decision your team has to make. Three options. Option A: treat re-subscription as a new acquisition, write fresh attribution at the second checkout.session.completed, accept that you have two attribution rows for one customer over time. Option B: preserve the original first-touch attribution forever, treat re-subscription as expansion, only update last-touch. Option C: write a separate attr_resubscribe_channel field that captures the channel of the re-acquisition while preserving the original. Attrifast defaults to option C; the dashboard can then break out "original acquisition" from "reactivation" cleanly.

How do I handle attribution for self-serve B2B that uses Stripe Billing but not Stripe Checkout?

The architecture is the same, the carrier object differs. For Stripe Billing with custom payment forms or embedded PaymentIntents, write the first-party ID into PaymentIntent metadata at create time. The webhook is payment_intent.succeeded instead of checkout.session.completed. For Stripe Billing with the Customer Portal handling subscription changes, you cannot inject metadata mid-flow, so capture must happen at the moment of new-subscription creation (which fires customer.subscription.created). The metadata pattern in the FAQ above works for all three integration shapes.

How accurate is the attribution against ground truth?

There is no perfect ground truth for marketing attribution; the question is which approximation is most useful. Against a UTM-tagged subset where every touch is captured cleanly, the first-touch and last-touch attribution captured by the four-step pipeline in this article is within 5-8% of the UTM-tagged baseline on the sites I have measured. For the AI-engine portion specifically (the slice where referers are stripped), behavioral fingerprinting precision is 78-86% and recall is 70-82%. The headline: this is materially better than GA4 default (which is 0% accurate on AI traffic) but not perfect. Treat the numbers as decision-grade, not finance-grade.

What is the difference between revenue attribution and conversion attribution?

Conversion attribution credits a channel with a conversion event (signup, trial start, paid conversion). Revenue attribution credits a channel with the dollar amount of revenue associated with that conversion. The two often look similar but diverge sharply when plan sizes vary by channel. A channel that drives many low-plan signups looks great in conversion attribution and mediocre in revenue attribution. A channel that drives few enterprise-plan signups looks the inverse. Always report both; the revenue column is what moves budget; the conversion column is what tells you channel volume.

Does Stripe attribution work for marketplaces (Connect)?

Yes, with extra care. Stripe Connect (for marketplaces and platforms) has separate Customer objects for the platform and for each connected account. Attribution must be written at the level the marketplace cares about (usually platform-level for marketplace economics; connected-account-level for seller analytics). The metadata propagation pattern works identically; the volume considerations (Sigma costs, webhook throughput) scale with marketplace transaction count, which can be much higher than a standard SaaS.

References

  1. Stripe — Stripe annual letter and processed payment volume disclosure
  2. Stripe Docs — Webhook events list and reference
  3. Stripe — Sigma pricing (charge-volume subscription tiers, verified 31 July 2026)
  4. Stripe API Reference — Metadata field on Stripe objects
  5. OpenView Partners — SaaS benchmarks: trial conversion times and rates, 2025
  6. ChartMogul — SaaS benchmarks report: trial-to-paid conversion rates
  7. Baremetrics Blog — SaaS attribution and analytics: state of the field
  8. SegMetrics — Pricing page (Launch starts at $57/mo, verified 31 July 2026)
  9. Wicked Reports — Pricing page (Measure starts at $499/mo, verified 31 July 2026)
  10. Triple Whale — Pricing page (free tier, then Starter $179/mo, verified 31 July 2026)
  11. Polar Analytics — Pricing page (GMV-quoted, no published flat rate, verified 31 July 2026)
  12. Baremetrics — Pricing page (Launch $75/mo, verified 31 July 2026)
  13. G2 — Northbeam pricing listing (Starter $1,500/mo, verified 31 July 2026)
  14. McKinsey & Company — The value of marketing analytics: 15-20% efficiency lift research
  15. Stripe Atlas — Founder guides: marketing and growth essays
  16. Stripe Docs — Webhook security and signature verification
  17. Stripe Docs — Checkout Session client_reference_id field
  18. ChartMogul — Pricing page (free under $10k MRR, then Starter $59/mo, verified 31 July 2026)
  19. Stripe Docs — Stripe Billing overview and Customer Portal
  20. Stripe Docs — Stripe Data Pipeline for warehouse export
  21. Search Engine Land — Marketing attribution coverage and platform trends, 2024-2026
  22. Backlinko — Marketing attribution models compared: research and benchmarks
  23. ProfitWell (Paddle) — SaaS metrics: subscription analytics and benchmarks
  24. Reddit r/SaaS — Discussion threads on Stripe attribution and SegMetrics alternatives
  25. Reddit r/SaaS — Threads on Baremetrics vs ChartMogul vs ProfitWell for SaaS metrics
  26. Stripe Docs — Payment Links URL parameters: client_reference_id and UTM passthrough
  27. Stripe Docs — Restricted API keys and key rotation
  28. Stripe Docs — Workbench, which replaced the Developers Dashboard

For the upstream tracker architecture that feeds the Stripe webhook handler in this article, see the practical track-ChatGPT-traffic guide and the broader ChatGPT referral analytics piece. For the strategic frame around AI search and content investment, the AEO vs SEO in 2026 piece covers the split. For the question of whether AI-driven channels actually drive Stripe revenue, does GEO actually drive revenue walks the layered evidence framework. If you want the same Stripe-native revenue-attribution architecture without rolling it yourself, the Stripe attribution feature page, the Stripe marketing attribution overview, the revenue attribution feature page, and the UTM-to-revenue tracking page walk the product side end to end.

Reading this with an AI assistant?Ask Perplexity about this article →Read this article as markdown →

About the author

Vincent RuanFounder, Attrifast

Vincent Ruan is the founder of Attrifast, an analytics platform for website traffic, customer-level revenue and AI brand visibility, which he built after spending two years duct-taping GA4 exports to Stripe payouts for the Shopify store he and Jessica Huang started in 2021. He wrote the first 4kb tracking script himself, ships every backend webhook handler, and has stitched first-party attribution into roughly 40 marketing channels across his own properties and a handful of client SaaS apps. Before Attrifast he ran growth and analytics for two bootstrapped products and watched ITP 2.3 quietly evaporate 30%+ of his paid-search attribution overnight. He writes mostly about the parts of analytics that break in production, cookies, consent, webhooks, and the joins between them.

  • X
  • vince-ruan.com
  • LinkedIn

Related reading

Comparison17 min
Best Stripe Analytics Tools 2026: 8 Ways to Turn Payments Into Channel Revenue
Best Stripe analytics tools 2026: 8 options — Attrifast, Baremetrics, ChartMogul, Stripe Sigma — separating MRR monitoring from channel revenue attribution.
Attribution29 min
Marketing Attribution for Product-Led Growth (2026)
Marketing attribution for product-led growth: why PLG breaks classic attribution, the signup-vs-activation-vs-paid model, and the SMB stack from $9.99/mo.
Attribution27 min
The Bootstrapped SaaS Founder's Guide to Marketing Attribution (Without Spending $800/mo)
SaaS marketing attribution playbook for bootstrapped founders: stage-by-MRR priorities, the trial-to-paid problem, channel benchmarks, and a $9.99/mo stack.
Attribution27 min
Stripe vs GA4 Revenue Attribution: A 2026 Head-to-Head From an Operator Who Runs Both
Stripe vs GA4 revenue attribution: where each wins, the six scenarios where they diverge, and the dollar gap seen across roughly 40 instrumented properties.
AI Search14 min
AI Traffic Is a Trade, Not a Channel: How to Compute What Your Crawl Budget Actually Earns
Every AI traffic study counts what comes in. None of them count what goes out. Cloudflare measured one platform taking 70,900 pages for every visitor it returned. This is the other half of the ledger — how to compute revenue per 1,000 AI crawls on your own site, why the answer differs 300× between engines, and what to do when it comes back negative.

See which AI engines actually send you paying customers

Attrifast splits ChatGPT, Perplexity, Claude and Gemini into their own revenue lines — joined to real Stripe payments, not estimates.

  • ✓One script tag and a Stripe key — live in minutes
  • ✓First-party measurement without third-party cookies
  • ✓Recognized AI referrals joined to Stripe payments
Start your free trial →

7-day free trial · $0 due today · then $9.99/mo · cancel anytime

Attrifast dashboard: prompt-level AI visibility with estimated value, revenue split by channel across ChatGPT, Google, Perplexity, Claude and Direct, competitor position tracking, and per-engine scan settings.