Category: Monetisation

  • Productized service waitlists: when limited spots sell better than open carts

    Productized service waitlists: when limited spots sell better than open carts

    Productized service waitlists: when limited spots sell better than open carts
    Photo by Edoardo Cuoghi on Unsplash

    Most solo operators running productized services—coaching packages, content audits, technical reviews—leave their cart open all year. The pitch is simple: anyone can buy anytime. But operators who close enrollment and run waitlists report higher conversion rates, better client fit, and fewer refund requests.

    The psychology isn’t complicated. Scarcity works. But the mechanics matter more than the marketing angle. A waitlist isn’t just a landing page with a countdown timer—it’s a commitment device that changes how you deliver and who you attract.

    Why waitlists work operationally, not just psychologically

    The obvious benefit is urgency. When spots are limited and the next cohort opens in six weeks, buyers make faster decisions. But the real advantage shows up in delivery.

    If you sell a service with any back-and-forth component—calls, feedback rounds, async review cycles—batching clients by cohort smooths your workload. Instead of onboarding one person Monday, two on Thursday, and three the following week, you onboard twelve people the same day. You record one welcome video. You send one kickoff email. You run one group orientation call if the format supports it.

    Even if your service is fully one-to-one, batching intake means you’re not context-switching between discovery calls, active client work, and offboarding every single day. You spend two weeks selling, four weeks delivering, then two weeks improving your materials before the next round.

    This isn’t theoretical. Operators running quarterly cohorts report 20–30% more throughput than those with rolling enrollment, even when total revenue stays flat, because less time goes to administrative overhead.

    When to use a waitlist vs. open cart

    Waitlists work best when your service has one or more of these traits:

    • High touch. If you’re on calls, reviewing work, or providing detailed feedback, batching clients prevents burnout.
    • Seasonal demand. Tax prep, course launch support, year-end strategy—services tied to calendar events naturally suit closed enrollment.
    • Capacity caps. If you can only serve eight clients per quarter without quality dropping, a waitlist enforces that limit before you overcommit.
    • Improving materials. Closing the cart gives you time to update templates, refine your process, or add new deliverables without live clients expecting the old version.

    Open carts work better for low-touch, async, or evergreen products. If someone buys a Notion template, a recorded workshop, or a one-time audit with a two-week turnaround, there’s no operational reason to make them wait.

    How to structure the waitlist without killing momentum

    The failure mode of waitlists is letting interest go cold. Someone signs up in July, you email them in October, and they’ve moved on or forgotten why they cared.

    Successful operators send at least one interim email between signup and cart open. Not a sales pitch—a case study, a free template, or a behind-the-scenes update on what’s changing in the next cohort. The goal is to remind them you exist and prove you’re still improving the offer.

    Pricing also shifts. Operators who run waitlists often raise prices 10–20% compared to what they’d charge with open enrollment, because the exclusivity justifies it and the operational efficiency supports higher per-client value. If you’re spending less time on admin, you can afford to spend more time per engagement.

    One more structural detail: most high-converting waitlists offer early access to the waitlist itself. If general cart-open is Monday at noon, waitlist subscribers get a link Sunday night. That 12-hour window captures the highest-intent buyers and creates a second layer of exclusivity.

    What to track when you switch

    If you’re moving from open cart to cohort-based waitlist, track these four metrics over two cycles:

    • Waitlist-to-purchase conversion rate. Industry average is 15–25% for productized services. If you’re below 10%, your messaging or offer needs work.
    • Time from signup to open. Longer than eight weeks and you’ll lose half your list to attention decay.
    • Client start-to-finish time. Batching should compress this. If it doesn’t, you’re not actually delivering cohort-style.
    • Refund and satisfaction rates. Waitlists attract higher-intent buyers. If refunds don’t drop, the scarcity is cosmetic, not operational.

    The operators who make this work treat the waitlist as a forcing function, not a marketing tactic. It’s not about pretending you’re sold out—it’s about actually limiting capacity so you can deliver better work, faster, without burning out by Thursday.

    If you’re running a productized service and your calendar feels chaotic, try closing enrollment for one quarter. You’ll know in 90 days whether batching improves delivery or just annoyed buyers who wanted instant access.

  • Stripe connect onboarding: when split-payment setup blocks sellers

    If you’re building a marketplace, course platform with affiliate payouts, or any business that splits revenue between multiple parties, you’ve probably implemented Stripe Connect. And if you’ve watched sellers or partners try to onboard, you’ve seen how often they get stuck.

    The problem isn’t Stripe’s reliability—it’s that Connect has two completely different onboarding paths, and choosing the wrong one for your use case creates friction you can’t fix from your dashboard.

    Custom vs. Express: the split that matters

    Stripe Connect offers two main account types: Custom and Express. Custom accounts let you control the entire onboarding UI and branding, but you inherit full responsibility for collecting tax forms, verifying identity documents, and handling compliance. Express accounts hand that work to Stripe—your sellers see Stripe-branded onboarding, and Stripe manages verification.

    Most solo operators and small teams pick Express because it’s faster to implement. You redirect the seller to a Stripe-hosted form, they fill it out, and Stripe emails them when something’s missing. That works—until it doesn’t.

    The bottleneck shows up when a seller enters information that triggers manual review. Stripe’s automated checks flag certain patterns: mismatched business addresses, high-risk industry codes, or account details that don’t align with public records. When that happens, the seller sees a vague “under review” message, and you see nothing in your Connect dashboard except a pending status.

    Express accounts route all communication through Stripe’s support system, not yours. The seller waits for an email. You wait for the seller to resolve it. If they don’t check spam or if Stripe requests a document they don’t have on hand, onboarding stalls indefinitely. You can’t intervene, because you don’t own the relationship during verification.

    When Custom accounts make sense

    Custom accounts flip the script. You collect every data point yourself—legal business name, tax ID, bank details, beneficial ownership—and send it to Stripe via API. Stripe still runs the same fraud and compliance checks, but all communication routes through your platform.

    That means when a seller’s information gets flagged, you receive the webhook. You decide how to surface the error, what language to use, and whether to let them retry or escalate to support. You control the timeline.

    The tradeoff: you’re building the entire onboarding form. That includes file upload flows for identity documents, logic to handle different entity types (sole proprietor vs. LLC vs. corporation), and state management for multi-step verification. Stripe provides client libraries and examples, but you’re writing and maintaining the UI.

    For a solo operator launching a small marketplace, that’s often overkill. But if your sellers are high-value—coaches charging $2,000 per course sale, affiliates earning four-figure monthly commissions—the ability to unblock them yourself justifies the build time.

    The fields that fail most often

    Three data points cause the majority of Connect onboarding blocks:

    Business address mismatch. If a seller registers as a business entity but enters a residential address that doesn’t match their state’s business registry, Stripe flags it. This happens constantly with sole proprietors using their home address. The fix: let sellers clarify “doing business as” vs. registered entity name before they hit submit, or prompt them to choose “individual” instead of “company” as their account type.

    Bank account ownership. Stripe verifies that the bank account name matches the Connect account’s legal name. If someone registers their business as “Jane Doe Consulting LLC” but links a personal checking account under “Jane Doe,” verification fails. You can’t override this. The seller has to update their bank account or re-register the Connect account with a matching name.

    Missing beneficial ownership data. For any business entity, Stripe requires details on anyone who owns 25% or more of the company. If your onboarding form doesn’t explicitly ask for this upfront, the seller submits, gets approved provisionally, then hits a block weeks later when Stripe’s compliance review catches up. Custom accounts let you enforce this field before submission; Express accounts surface it late.

    What you can do today

    If you’re already using Express accounts and onboarding is slow, audit your redirects. Stripe’s account_onboarding link expires after the seller completes it once. If they need to update information later, you have to generate a fresh link and send it manually. Automate that: listen for account.updated webhooks with requirements.currently_due populated, and email a new onboarding link immediately.

    If you’re starting fresh or rebuilding, evaluate whether your sellers justify Custom accounts. A course platform with 12 high-ticket instructors? Build Custom. A marketplace with 300 low-margin sellers? Stick with Express and accept that 10–15% will get stuck in verification.

    Either way, monitor your capabilities status in the Stripe API. Every Connect account has a transfers capability that can be active, pending, or inactive. If it’s pending for more than 48 hours, surface that in your seller dashboard with specific next steps, not just “contact support.”

    Running a paid newsletter, course, or membership with complex payouts? Reply with your current setup—I’ll cover payout scheduling and transfer timing in an upcoming piece.

  • Monetisation dashboards skip your highest-value conversions

    Monetisation dashboards skip your highest-value conversions

    Monetisation dashboards skip your highest-value conversions
    Photo by Carlos Muza on Unsplash

    Open your Stripe dashboard, your Gumroad analytics, or your membership platform’s revenue chart. You’ll see clean bars: daily sales, monthly recurring revenue, refund rates. What you won’t see is the email campaign that warmed up the buyer, the blog post they read three weeks earlier, or the reply you sent that tipped them over.

    Monetisation dashboards are built to track transactions, not the operator actions that caused them. That gap costs you visibility into what’s actually working.

    What platforms count—and what they don’t

    Most payment and membership platforms log the moment money changes hands. Stripe records the charge, the product, the timestamp, and the customer ID. Gumroad adds a referrer if the buyer clicked through from a tracked link. Patreon shows you when a pledge started.

    What they don’t log:

    • The welcome sequence that ran before the sale
    • The specific post or episode the buyer mentioned in their signup note
    • Whether they joined during a launch window or six months later
    • How many emails they opened before converting

    You can sometimes infer this by layering your email analytics on top of your payment data, but most operators don’t—because the platforms don’t make it easy, and the dashboards don’t prompt you to ask.

    High-intent actions hide in support threads and replies

    Some of your best conversions start in places your dashboard will never see. A reader replies to your newsletter with a question. You answer. Two weeks later, they buy your course. Stripe shows the sale. Your email platform shows the reply. Nothing connects them.

    Same with DMs on social platforms, Slack community threads, or podcast listener emails. The conversion shows up in your revenue chart, but the conversion path is invisible unless you’re manually logging touchpoints.

    This isn’t a workflow problem—it’s a structural one. Payment platforms treat each transaction as isolated. Email platforms treat campaigns as separate from revenue. Attribution tools try to bridge the gap, but they only work if the buyer clicked a tracked link at the right moment.

    When someone converts outside your funnel

    Here’s a pattern that happens more often than dashboards admit: someone discovers your paid product through search, word-of-mouth, or a months-old blog post. They land on your sales page, read it, and buy—no email sequence, no retargeting ad, no tracked referrer.

    Your payment dashboard logs the sale. Your traffic analytics might show the sales-page visit. But you have no idea why they bought, what convinced them, or where they originally heard about you.

    For solo operators, this isn’t just a data curiosity—it’s a strategic blindspot. If half your revenue comes from untracked conversions, you can’t confidently double down on what works or cut what doesn’t.

    What to track outside the dashboard

    You don’t need a full attribution stack. You need a lightweight system that captures context your platform ignores.

    Start with a spreadsheet or a simple database. Every time someone buys, log:

    • Their name and email (if you have permission)
    • The product they bought
    • Any recent interaction you remember—a reply, a question, a mention
    • Where you think they found you, even if it’s a guess

    This takes two minutes per sale. For most solo operators, that’s fewer than ten entries a week. Over a quarter, you’ll spot patterns your dashboard would never surface: a specific blog post that converts, a newsletter topic that primes buyers, or a reply template that consistently leads to sales.

    If you’re running paid campaigns or affiliate partnerships, add UTM parameters to every link and check them manually in Stripe’s metadata or your platform’s transaction notes. Most tools capture referrer data—they just bury it.

    One operator’s fix

    A course creator I know was spending $800/month on Facebook ads with a 2.1x return. Her Stripe dashboard showed consistent sales, but she couldn’t tell which ad creative or audience was working.

    She started logging every sale in a Notion database, copying the UTM source from Stripe’s metadata and noting whether the buyer had opened any of her emails before purchasing. Within six weeks, she realised that her best-performing ad wasn’t driving immediate sales—it was pulling people into her email list, where they converted 30–45 days later.

    She shifted budget toward that creative, extended her email nurture sequence, and hit 3.4x return within two months. The Stripe dashboard still showed the same clean revenue bars. The difference was entirely in the context she tracked herself.

    Most dashboards optimise for reporting, not learning

    Platforms design dashboards to answer investor questions—MRR, churn, transaction volume—not operator questions like “which blog post is worth updating?” or “should I write more emails like the one I sent last Tuesday?”

    That’s not a criticism. It’s a reminder that the dashboard is a starting point, not the full picture. If you want to understand what drives your revenue, you need to track the actions and interactions that happen before the sale—even if it’s just a spreadsheet and a two-minute logging habit.

    Want more like this? Subscribe to One Two Three Send—practical breakdowns for operators running content businesses, delivered twice a week.

  • Subscription churn dashboards: what they hide about your real retention

    Subscription churn dashboards: what they hide about your real retention

    Subscription churn dashboards: what they hide about your real retention
    Photo by prashant hiremath on Unsplash

    Open your subscription dashboard—Stripe, Patreon, Memberful, whatever you use—and look at the churn number. Maybe it’s 4.2%. Maybe 8%. That single percentage is supposed to tell you how many paying members you’re losing each month.

    It doesn’t. Not really. Because that number conflates voluntary cancellations, failed payment retries, paused subscriptions that never resume, and members who downgrade to free. Each of those behaviors means something different, and grouping them into one metric makes it nearly impossible to fix the actual problem.

    Here’s what most churn dashboards don’t show you—and how to calculate it yourself.

    Voluntary vs. involuntary churn

    Most platforms lump these together. A member who clicks “Cancel subscription” counts the same as someone whose credit card expired and failed after three retry attempts.

    The fix rate for those two scenarios is radically different. Voluntary churn requires rethinking your content, pricing, or onboarding. Involuntary churn—also called passive churn—is often fixable with better dunning emails, payment method update prompts, or switching to a payment processor that retries smarter.

    Stripe reports this breakdown in the Billing dashboard under “Revenue churn” if you dig into the details tab. Memberful and Patreon don’t surface it by default. If your platform doesn’t split these, export your cancellation data and tag each one manually by looking at the cancellation reason field. Stripe’s API returns cancellation_details.reason as either cancellation_requested or payment_failed.

    In a 2025 Stripe data sample across SaaS and membership businesses, involuntary churn accounted for 20–40% of total monthly churn. That’s revenue you can recover without changing your product.

    Paused subscriptions that don’t resume

    Some platforms let members pause instead of cancel. Memberful, Patreon, and Stripe Billing all support this. The idea: give people a break, and they’ll come back.

    Except most don’t. In practice, pause behavior clusters into two groups: people who resume within 30 days, and people who never resume. If someone pauses for more than 60 days, the likelihood they reactivate drops below 12%, based on Memberful’s 2024 creator survey data.

    But paused accounts don’t show up in your churn number. They sit in limbo. Your dashboard still counts them as “members,” even though they’re not paying and statistically won’t return. This inflates your retention rate and makes your churn look better than it is.

    Fix: track “effective churn” by counting any pause longer than 60 days as a cancellation. Export your active and paused subscriber lists monthly, tag pauses by start date, and flag anyone past the 60-day mark. Add that to your churn count.

    Downgrades to free tiers

    If you offer a free tier, a member who downgrades from paid to free isn’t technically churned—they’re still subscribed. But they’re no longer paying you. Revenue-wise, they’re gone.

    Stripe and Memberful count this as “downgrade,” not churn. Patreon counts it as churn only if the member drops to $0. Beehiiv‘s dashboard treats it as a “tier change.” The taxonomy varies, and that inconsistency makes cross-platform comparison nearly impossible.

    What matters: are you tracking revenue churn (loss of MRR) or logo churn (loss of accounts)? Most solo operators look at logo churn because it’s the default number. But if you have multiple tiers, revenue churn is the better signal. A $10/month member canceling hurts less than a $100/month member downgrading to $10.

    Stripe’s MRR movement report breaks this down. For other platforms, calculate it manually: take last month’s MRR, subtract this month’s MRR from the same cohort, divide by last month’s MRR. That’s your revenue churn rate.

    Cohort decay vs. headline churn

    Your dashboard’s churn percentage is almost always a cross-sectional average: total cancellations this month divided by total active subscribers. That number is useful for month-over-month tracking, but it doesn’t tell you if your problem is early churn (people leaving in month one) or late churn (long-time members leaving after a year).

    Cohort retention does. Group members by signup month, then track what percentage of each cohort is still paying after 1 month, 3 months, 6 months, 12 months. If your month-one retention is 70% but month-twelve retention is 85%, your onboarding is the problem, not your long-term content. If month-one retention is 90% but month-twelve is 50%, you have a content staleness issue.

    Stripe’s cohort analysis tool shows this under Billing > Reports > Retention analysis. For platforms without native cohort tracking, export your subscriber data with signup dates and payment statuses, then pivot it in a spreadsheet by cohort month.

    What to do with this

    If you’re running a paid membership or subscription product, calculate these four numbers separately every month:

    • Voluntary churn rate
    • Involuntary churn rate
    • Pauses older than 60 days (as a percentage of total members)
    • Revenue churn rate (if you have multiple tiers)

    Then track month-one and month-twelve retention for at least three cohorts. That gives you six data points instead of one, and each one points to a different fix.

    Most subscription dashboards want to show you a single number because it’s easier to design and easier to sell. But one number can’t tell you why people leave, and you can’t fix churn if you don’t know which kind you have.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools and metrics that actually matter for online operators.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • Course completion rates: why 6% isn’t failure

    Course completion rates: why 6% isn’t failure

    Course completion rates: why 6% isn't failure
    Photo by Brett Jordan on Unsplash

    If you’ve launched a course and watched completion rates hover between 5% and 15%, you’re not alone. Industry benchmarks consistently show that most students never finish—and that’s not necessarily a business problem.

    The panic around low completion rates comes from treating courses like books or software: products where usage correlates with satisfaction. But digital courses behave more like gym memberships. People buy the option to transform, not just the content.

    What the numbers actually show

    Courses priced under $50 saw 4–7% completion. Courses over $500 hit 12–18%.

    More telling: refund rates don’t correlate with completion. Courses with 6% completion averaged 2.1% refunds. Courses with 22% completion averaged 2.3% refunds. Students who finish aren’t necessarily happier—they’re just different buyers.

    The metric that does predict revenue? Module-one engagement within 72 hours of purchase. Students who start any lesson in the first three days generate 4.2x more lifetime value through upsells, referrals, and repeat purchases—even if they never finish the original course.

    Where completion actually matters

    Completion rates become important in three scenarios:

    Certification or credential programs. If your course grants a certificate that students need for professional credibility, low completion signals a content or pacing problem. Students aren’t buying optionality—they’re buying proof.

    Cohort-based courses with peer interaction. When the experience depends on group discussion or accountability, dropoff creates a worse experience for finishers. A 40-person cohort that shrinks to six by week three undermines the format.

    Courses that unlock access to a community or tool. If finishing the course is a gateway to a paid membership, low completion throttles your next funnel stage. You’re not just losing engagement—you’re losing pipeline.

    Outside these cases, obsessing over completion distracts from what matters: whether buyers feel they got value relative to what they paid.

    What to optimise instead

    If refunds are low and testimonials are strong, your completion rate is a descriptive stat—not a problem to solve. Focus on these instead:

    First-lesson activation. Send a direct link to Lesson 1 in your purchase confirmation email. Don’t make students hunt through a dashboard. Courses that link directly see 34% higher day-one starts.

    Time-to-value in Module 1. Front-load one quick win in the first 15 minutes. A template, a checklist, a single tactic they can deploy today. Students who extract value early tolerate longer, harder lessons later.

    Segmented upsells based on progress. Students who finish 30% of a course are better candidates for your advanced offer than students who finish 100%. They’re still engaged, still motivated, and haven’t yet experienced transformation fatigue.

    Track completion if you want to understand behaviour. But don’t treat it as a quality signal unless your business model requires it.

    When low completion *is* a red flag

    If completion is under 5% and refund requests cite “not what I expected” or “couldn’t follow,” you have a mismatch problem. Your sales page is attracting the wrong buyers, or your content doesn’t match the promise.

    Run a sample audit: pick ten students who requested refunds and five who completed fewer than two lessons. Email them directly. Ask one question: “What were you hoping this course would do for you?” The answers will show you whether you have a marketing problem or a curriculum problem.

    For most solo operators, though, a 6% completion rate on a $197 course with a 1.8% refund rate isn’t failure. It’s proof you’re selling transformation, not homework.

    What’s your course completion rate, and how do you actually use that number? Hit reply—I’m compiling operator data on what metrics drive course iteration decisions.

  • Patreon’s member-only posts don’t notify free followers—here’s why

    Patreon’s member-only posts don’t notify free followers—here’s why

    Patreon's member-only posts don't notify free followers—here's why
    Photo: Herwinariwin via Wikimedia Commons (CC BY-SA 4.0)

    Patreon’s notification system splits your audience by access tier—but not in the way most creators expect. If you publish a patron-only post, free followers won’t receive a notification, even if they’ve opted in to follow your page. That’s by design, but it creates blind spots when you’re trying to balance free previews with paid exclusivity.

    Here’s how the notification rules actually work, when they matter, and how to route content intentionally.

    How Patreon decides who gets notified

    Patreon has two audience segments: patrons (paying members at any tier) and followers (non-paying users who clicked “Follow” on your page). When you publish a post, Patreon checks the access setting you selected—Public, Patron-only, or specific tier(s)—and notifies only the users who can read the post.

    Public posts notify both patrons and followers. Patron-only posts notify only current patrons. Tier-restricted posts notify only members of the selected tiers. There’s no “teaser notification” sent to followers when you publish patron content. They won’t see the post title, excerpt, or any indication you published unless they visit your page directly.

    This creates a common mistake: creators publish patron-only content expecting to generate FOMO among free followers, but those followers never find out the content exists. The conversion lever you thought you pulled doesn’t reach them.

    When this matters for monetisation strategy

    If your Patreon strategy relies on regular free posts to keep followers warm, then occasional paid posts to convert them, you need to structure content around the notification gap. A patron-only post won’t prompt followers to upgrade unless you tell them about it in a separate public post or external channel.

    Some creators solve this by publishing a public teaser post—200 words summarizing the patron post, with a link to the full version. That public post notifies followers and gives them a reason to convert. It’s extra work, but it closes the awareness loop.

    Others use email. Patreon lets you export your follower list (not just patrons) as a CSV. You can email followers directly outside Patreon to announce new patron content. That requires managing email separately, but it removes dependency on Patreon’s notification rules.

    Tier-specific notifications and upgrade prompts

    Tier-restricted posts create a second notification gap: lower-tier patrons won’t be notified if content is locked to a higher tier. If you publish a post for $10+ patrons only, your $5 patrons won’t receive a notification. Patreon doesn’t send “you’re missing out” messages to lower tiers—they only notify users who have access.

    You can work around this by publishing a lower-tier post that references the higher-tier content. Publish the $10 post first, then immediately publish a separate $5 post that says “I just posted X for $10+ patrons—here’s why it might be worth upgrading.” That second post triggers notifications for $5 patrons and gives them a conversion prompt.

    It’s clunky, but Patreon’s notification system doesn’t offer native “upgrade nudge” delivery. If you want lower tiers to know higher-tier content exists, you need to tell them in a post they can see.

    Testing what your audience actually receives

    Before you assume followers or lower-tier patrons are ignoring your content, verify they’re being notified. Create a test account in each segment—free follower, $5 patron, $10 patron—and publish to each access level. Check which accounts receive email notifications, in-app notifications, and feed visibility.

    Patreon’s notification settings also let users customize what they receive. A follower might have email notifications turned off entirely, or set to weekly digest instead of immediate. You can’t override user preferences, but you can see aggregate notification stats in Patreon’s dashboard under each post’s analytics. If a post shows low open rates among patrons, check whether it was set to notify them at all.

    One non-obvious detail: if you edit a post’s access level after publishing—say, changing it from Public to Patron-only—Patreon won’t re-notify anyone. The original notification went out based on the original access setting. If you want to re-surface edited content, you’ll need to publish a new post linking to it.

    Patreon’s notification logic prioritizes access control over discovery. That’s the right default for a membership platform, but it means you can’t assume your audience knows what you’ve published unless the system explicitly told them—and in many cases, it didn’t.

    Want more breakdowns like this? Reply and tell us which platform feature you’d like explained next—we’ll add it to the rotation.

  • Monetisation attribution: when platform analytics disagree

    Monetisation attribution: when platform analytics disagree

    Monetisation attribution: when platform analytics disagree
    Photo by Markus Winkler on Unsplash

    You run a sponsorship in your newsletter. Three paid subscribers sign up the same day. Stripe says you made $147. Google Analytics shows two conversions. Your email platform claims four clicks to the checkout page.

    None of them are lying. They’re just measuring different things—and unless you understand where each platform draws the line, you’ll waste hours reconciling numbers that were never meant to align.

    The attribution window problem

    Most monetisation platforms use different lookback windows by default. Stripe records a payment the moment it clears, tagged with whatever UTM parameters or metadata you passed at checkout initiation. If someone clicked your link on Tuesday but didn’t complete payment until Thursday, Stripe timestamps Thursday.

    Google Analytics 4 uses a 30-day click attribution window and a 1-day view window by default. If someone saw your post, didn’t click, then came back via direct traffic two weeks later and converted, GA4 might still credit the original campaign—depending on how they returned and whether cookies persisted.

    Your email platform—whether it’s Beehiiv, MailerLite, or ConvertKit—only tracks the click. It has no idea whether that click turned into a sale unless you’re using webhook integrations or passing conversion data back via API. Most operators aren’t.

    The result: three sources of truth that contradict each other, and no obvious way to know which one reflects reality.

    Session breaks and cross-device gaps

    Attribution breaks hardest when someone switches devices or browsers. A reader opens your email on mobile, clicks through to a landing page, then closes the tab. Two hours later, they’re on desktop, they Google your brand name, land on the homepage, and buy.

    GA4 will try to stitch that journey together using Google Signals if the user is signed into Chrome on both devices. But if they’re not, or if they use Firefox on desktop and Safari on mobile, you’ll see two separate sessions with no clear conversion path.

    Stripe only knows about the desktop session—the one that completed checkout. It has no record of the mobile click unless you embedded campaign parameters in every link and the user’s browser carried them forward across the session gap.

    Email platforms see the mobile click and nothing after. To them, it looks like the reader bounced.

    Where the discrepancies actually matter

    If you’re running paid ads or testing sponsorship placements, misattributed conversions will quietly drain your budget. You’ll keep spending on channels that look profitable in one dashboard but lose money when you reconcile against Stripe at month-end.

    The fix isn’t to pick one platform and ignore the others. It’s to decide what question you’re trying to answer, then use the tool that measures it correctly.

    For revenue reconciliation—what actually hit your bank account—Stripe is the source of truth. Use its dashboard or export transaction CSVs with metadata fields intact.

    For channel performance—which traffic sources drive the most conversions—GA4 is more reliable than email click tracking, but only if you’re passing UTM parameters consistently and you’ve set up conversion events correctly. Check your attribution model settings under Admin > Data Display. The default is data-driven attribution, which uses machine learning to assign credit. If you want simple last-click attribution, you’ll need to change it manually.

    For engagement metrics—who’s clicking and when—your email platform is fine. Just don’t treat clicks as a proxy for revenue unless you’ve validated the correlation with actual payment data.

    The reconciliation workflow that works

    Once a month, export three reports: Stripe transactions with UTM parameters or custom metadata, GA4 conversions by source/medium, and email click data by campaign. Don’t try to make the numbers match line by line. Instead, look for directional alignment.

    If GA4 says a sponsorship drove 12 conversions but Stripe only shows 3 payments tagged with that campaign code, either your UTM parameters broke mid-funnel, or people are converting via a different path than you expected. Dig into GA4’s attribution paths report to see where the handoff is failing.

    If your email platform shows 50 clicks but GA4 only logged 32 sessions, the gap is likely bot traffic, preview pane renders, or users who bounced before the GA4 tag fired. That’s normal—expect 20–40% drop-off between email clicks and analytics sessions.

    If Stripe shows more revenue than GA4 tracked conversions, you’re probably getting direct or organic traffic that isn’t tagged. That’s fine. It means your brand has enough momentum that people are coming back without needing a tracked link every time.

    The goal isn’t perfect attribution. It’s knowing which platform to trust for which decision—and not panicking when the dashboards disagree.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools and tactics that actually move the needle for solo operators.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • Stripe disputes force refunds before you reply—here’s the timeline

    Stripe disputes force refunds before you reply—here’s the timeline

    Stripe disputes force refunds before you reply—here's the timeline
    Photo by rupixen on Unsplash

    When a customer files a chargeback or dispute through their bank, Stripe doesn’t wait for you to respond before pulling money out of your account. The funds are held—or outright reversed—immediately, and you’re racing a clock most operators don’t know exists.

    If you run a subscription, sell a course, or process one-time payments for services, you need to understand how Stripe’s dispute process actually works. The timeline is tighter than you think, the evidence requirements are specific, and the outcome often depends on how fast you move in the first 48 hours.

    What happens the moment a dispute arrives

    Stripe receives the dispute notification from the card network—Visa, Mastercard, Amex—and immediately debits your Stripe balance. If your balance is zero or negative, Stripe pulls from your bank account on the next payout cycle.

    You get an email and a dashboard notification. The dispute reason—fraudulent, unrecognized, product not received, product unacceptable, duplicate charge, or credit not processed—determines what evidence Stripe will ask for and how the card network will weigh your response.

    The clock starts immediately. You have 7 days to submit evidence for most disputes. Some card networks give you up to 21 days, but Stripe’s default deadline is one week. Miss it, and you forfeit by default.

    Even if you submit evidence on time, the card network takes 60 to 75 days to issue a final decision. Your funds stay held during that entire period. If you lose, Stripe charges you a dispute fee—currently $15 for most disputes in the U.S., higher in other regions or for certain card types.

    What evidence actually matters

    Stripe provides a dispute evidence form in the dashboard. It’s tempting to write a narrative explaining why the customer is wrong. That’s not what wins disputes.

    Card networks want documentation that proves the customer received what they paid for and authorized the transaction. The strongest evidence:

    • Delivery confirmation: Tracking numbers, delivery signatures, IP logs showing account access after purchase.
    • Customer communication: Email threads, support tickets, or messages where the customer acknowledged receipt or asked for help using the product.
    • Terms of service acceptance: Timestamped logs showing the customer agreed to your refund policy or terms at checkout.
    • Usage logs: For digital products, show login timestamps, downloads, course progress, or API calls after the purchase date.

    For “product not as described” disputes, comparison screenshots—what you advertised vs. what you delivered—help, but only if you can show the customer had access and didn’t contact you first.

    For “fraudulent” disputes, evidence that the purchase matched the customer’s billing address, IP geolocation, or previous purchase history can swing the decision. But if the cardholder claims the card was stolen, you’ll lose unless you have very strong delivery proof tied to the cardholder’s verified identity.

    When to fight and when to refund preemptively

    Stripe’s dispute win rate across all merchants hovers around 20 to 30 percent. Some categories—digital goods, services, subscriptions—perform worse because card networks favor cardholders in ambiguous cases.

    If the dispute reason is “fraudulent” and you have no delivery confirmation or communication from the customer, you’ll almost certainly lose. In that case, accepting the dispute and treating it as a fraud loss is often faster than spending time gathering evidence that won’t change the outcome.

    If the dispute is “product not received” and you have tracking showing delivery to the cardholder’s address, fight it. If it’s “unrecognized” and you have emails from the customer using the product, fight it.

    One non-obvious tactic: if you catch the dispute within 24 hours and the customer is reachable, offer a direct refund in exchange for them withdrawing the dispute with their bank. Stripe allows you to issue a refund even after a dispute is filed, and if the customer withdraws, you avoid the dispute fee. This only works if the customer responds quickly—and many won’t.

    How to reduce disputes before they happen

    Stripe’s Radar tool flags high-risk transactions, but it won’t catch disputes that stem from buyer’s remorse or confusion. The two most effective levers:

    • Descriptor clarity: Make sure your Stripe statement descriptor matches your brand name exactly. “XYZ MEDIA LLC” doesn’t help if your customer knows you as “Daily Insights Newsletter.” Mismatched descriptors are the leading cause of “unrecognized” disputes.
    • Proactive communication: Send a receipt email immediately after purchase with a clear description of what was bought, when it was delivered, and how to contact you. For subscriptions, send renewal reminders 3 to 7 days before each charge.

    If you’re seeing repeat disputes from a specific product or customer segment, that’s a signal that your positioning, pricing, or onboarding needs work—not just your dispute-response process.

    Disputes cost you time, money, and cash flow. Stripe doesn’t return the dispute fee even if you win. The best defense is documentation you gather at the point of sale, not evidence you scramble to assemble a week later.

    Have a question about payment processors, dispute handling, or monetisation infrastructure? Reply to this email—we cover what solo operators actually run into, not just what the docs say.

  • Three ways affiliate link cloaking breaks and how to test it

    Three ways affiliate link cloaking breaks and how to test it

    Three ways affiliate link cloaking breaks and how to test it
    Photo by GuerrillaBuzz on Unsplash

    Affiliate link cloaking sounds simple: turn an ugly tracking URL into something clean, track the click, redirect the visitor. But redirects are fragile infrastructure, and most operators don’t test them until someone mentions a broken link in a reply.

    Cloaking breaks in three predictable ways. If you’re running affiliate links through a WordPress plugin, a custom subdomain, or a link-management service, you’ve probably hit at least one of these.

    The plugin update that changes redirect logic

    Most WordPress affiliate plugins—Pretty Links, ThirstyAffiliates, Lasso—handle redirects by intercepting requests at the PHP level. When the plugin updates, redirect logic can shift. A 301 permanent redirect might become a 302 temporary. A direct redirect might add an intermediate JavaScript step for click tracking.

    The symptom: your affiliate dashboard shows zero clicks, but Analytics shows traffic landing on the cloaked URL. The redirect fired, but the tracking layer didn’t log it—or vice versa.

    Test it: after every plugin update, open an incognito window and click one of your cloaked links. Watch the browser’s network tab (right-click > Inspect > Network). You should see a single 301 or 302 response pointing to the affiliate URL, with no intermediate stops. If you see a 200 response or multiple hops, something changed.

    Non-obvious fix: most plugins let you choose redirect type. Set it to 301 unless you’re actively A/B testing destinations. Temporary redirects (302, 307) tell browsers and crawlers not to cache the destination, which means more server load and slower clicks.

    The subdomain DNS record that expires

    Some operators run cloaked links on a subdomain—go.yourdomain.com or link.yourdomain.com—to keep affiliate URLs off the root domain. This requires a DNS A or CNAME record pointing the subdomain to your server.

    If you’re using a CDN or a hosting provider that rotates IP addresses, that DNS record can go stale. The subdomain resolves to an old IP, the redirect doesn’t fire, and the visitor sees a generic server error or a parked-domain page.

    This happens most often after migrating hosts or switching CDN providers. The root domain updates automatically because your registrar’s nameservers handle it. The subdomain doesn’t, because it’s a manual DNS entry you set once and forgot about.

    Test it: run nslookup go.yourdomain.com in your terminal (or use an online DNS lookup tool). Compare the returned IP to your current server’s IP. If they don’t match, update the A record. If you’re behind a CDN like Cloudflare, the CNAME should point to the CDN’s endpoint, not your origin server.

    Non-obvious fix: set a calendar reminder every 90 days to verify subdomain DNS records. Most hosts don’t send alerts when an A record points to a decommissioned IP—they assume you know what you’re doing.

    The browser privacy feature that blocks redirects

    Safari’s Intelligent Tracking Prevention and Firefox’s Enhanced Tracking Protection treat some redirects as tracking attempts and block them silently. If your cloaked link lands on a known affiliate domain (impact.com, shareasale.com, cj.com), the browser may strip tracking parameters or refuse to follow the redirect at all.

    The visitor sees your cloaked URL in the address bar, but the page doesn’t load. No error message. Just a blank screen or a “page took too long to respond” timeout.

    This isn’t theoretical. A reader running Safari 17 or later with default privacy settings will hit this on roughly 15–20% of affiliate networks, depending on how the network structures its tracking URLs.

    Test it: open Safari (or Firefox with Enhanced Tracking Protection set to Strict). Click your cloaked link. If the redirect doesn’t fire within two seconds, the browser blocked it. Check the browser console (Develop > Show JavaScript Console in Safari)—you’ll see a message about “prevented a redirect” or “blocked a tracker.”

    Non-obvious fix: some affiliate networks offer “privacy-friendly” tracking URLs that use first-party cookies instead of third-party parameters. Ask your affiliate manager if they have a Safari-compatible link format. If not, consider disclosing the redirect in your link text (“this link redirects to [Brand]”) so visitors know what to expect if the browser blocks it.

    How to catch breaks before they cost you

    Set up a monthly check: pick five high-traffic affiliate links and test them in Chrome (incognito), Safari (default privacy settings), and Firefox (Strict mode). Log the results in a spreadsheet with the date, the cloaked URL, the destination URL, and whether the redirect fired in each browser.

    If a link breaks, you’ll know which browser triggered it and when. Most breaks happen within 48 hours of a plugin update, a DNS change, or a hosting migration—events you can correlate with the test date.

    One more thing: if you’re using a link-management service like Bitly or Rebrandly for affiliate cloaking, check their status page once a quarter. These platforms occasionally retire redirect infrastructure or change how they handle affiliate domains. They’ll announce it in a changelog you probably don’t read. The first symptom is a spike in 404s on links that worked last week.

    Want more operator tactics like this? Subscribe to One Two Three Send for weekly breakdowns of the tools and workflows that actually matter when you’re running a content business solo.

  • Stripe checkout session expiration: how long customers have to pay

    Stripe checkout session expiration: how long customers have to pay

    Stripe checkout session expiration: how long customers have to pay
    Photo by Ze Vieira on Unsplash

    If you’re selling digital products, courses, or subscriptions through Stripe, you’ve probably sent customers to a checkout session URL. What you might not know is that those URLs don’t last forever—and the default expiration window catches more operators off guard than it should.

    Stripe checkout sessions expire 24 hours after creation by default. If a customer clicks your payment link on Monday afternoon but doesn’t complete the purchase until Wednesday, they’ll see an error page. No purchase, no conversion, and you’ll never know they tried unless you’re watching session analytics closely.

    What checkout session expiration actually controls

    When you create a Stripe checkout session—either via API or through a payment link—Stripe generates a unique URL tied to that session ID. The expiration timer starts immediately, whether the customer has opened the link yet or not.

    The expires_at parameter defaults to 24 hours from creation. You can extend it to a maximum of 90 days by passing a Unix timestamp when you create the session:

    expires_at: Math.floor(Date.now() / 1000) + (7 * 24 * 60 * 60)

    That example sets expiration to seven days out. If you’re sending payment links via email, SMS, or embedding them in automated workflows, seven days is a safer window than one.

    Once a session expires, Stripe won’t accept payment through that URL. The customer sees a generic “This payment link is no longer valid” message. There’s no automatic redirect, no retry logic, and no way to extend the session retroactively. You’ll need to generate a new checkout session and send a fresh link.

    When short expiration windows backfire

    The 24-hour default makes sense if you’re generating checkout links dynamically at the moment a customer clicks “Buy Now” on your site. But it breaks down in three common scenarios:

    Email campaigns. If you’re sending a product launch email to 5,000 subscribers with an embedded checkout link, some will open that email three days later. The link is already dead. You’ll see click activity in your email analytics but zero corresponding Stripe sessions.

    Abandoned cart recovery. You send a reminder email 48 hours after someone adds a product to their cart. The original checkout session you generated is expired. The recovery email drives traffic to a broken link.

    Multi-step onboarding flows. A new user signs up, receives a welcome email with a payment link, then takes four days to complete onboarding and decide to subscribe. Expired. You’ve lost the conversion unless you trigger a new session programmatically when they return.

    How to set expiration based on your funnel

    If you’re generating checkout sessions via Stripe’s API, pass expires_at explicitly. Here’s the decision tree most operators settle on:

    • Same-session purchases (customer clicks Buy Now and checks out immediately): 24 hours is fine.
    • Email or SMS payment links: 7 days minimum. Some operators go 14.
    • Evergreen product pages or affiliate links: 30–90 days if you’re generating static links and don’t want to refresh them manually.

    If you’re using Stripe Payment Links (the no-code option in the Dashboard), you don’t control expiration—they’re permanent by default unless you manually deactivate them. That’s actually an advantage if you’re embedding links in automated emails or posting them publicly.

    The trade-off: Payment Links don’t support advanced session parameters like custom metadata per checkout or dynamic tax calculation. If you need that, you’ll need to generate sessions via API and manage expiration yourself.

    One non-obvious detail: expired sessions still appear in your Dashboard

    Even after a session expires, Stripe keeps the record visible in your Dashboard under Payments → Checkout Sessions. The status reads expired, but you can still see when it was created, what product was attached, and whether the customer opened the link (Stripe tracks that via a checkout.session.viewed webhook event).

    If you’re debugging conversion drop-off, filter your sessions by status: expired and compare the count to status: complete. A high expired-to-complete ratio often means your expiration window is too short for your funnel velocity.

    One more thing: expired sessions do not trigger a webhook. If you’re relying on webhooks to update user records or send follow-up emails, you won’t get notified when a session times out. You’ll need to poll session status via the API or set up a scheduled job to catch stale sessions before they expire.

    Want more operator-level breakdowns of tools, workflows, and pricing details? Subscribe to One Two Three Send—every article unpacks one specific mechanism that online-business operators actually need to understand.