Category: Monetisation

  • Beehiiv Ad Network revenue share: what you keep and when you qualify

    Beehiiv‘s Ad Network promises hands-off sponsorship revenue: they sell the ads, you run them in your newsletter, and you both split the money. For operators who don’t want to cold-pitch sponsors or negotiate rates, it’s a clean trade. But the economics only make sense if you understand the split, the qualification bar, and the payout timing.

    The revenue split and what Beehiiv keeps

    Beehiiv keeps 25% of gross ad revenue; you receive 75%. That split applies to all ad placements served through the network, whether display ads in the body or sponsored content blocks. The figure is published on Beehiiv’s Ad Network page (checked November 2026).

    If an advertiser pays Beehiiv $1,000 for a campaign that runs in your newsletter, you receive $750. Beehiiv handles sales, creative approval, and insertion—your share arrives net of their commission.

    That 25% covers more than platform overhead. Beehiiv’s ad-sales team pitches brands, negotiates CPMs, and manages campaign delivery. For operators who lack a media kit or sponsor pipeline, the commission buys distribution you wouldn’t otherwise capture. For operators who already sell sponsorships direct, the trade-off is less attractive: you’re paying for sales work you can do yourself.

    Eligibility threshold and approval process

    You need at least 1,000 subscribers to apply for the Ad Network. Beehiiv reviews your content, audience, and engagement before approval; meeting the subscriber minimum doesn’t guarantee entry. The threshold is documented in Beehiiv’s support article on Ad Network eligibility (checked November 2026).

    Once approved, ad inventory depends on demand. Beehiiv doesn’t guarantee fill rate—some newsletters see ads every issue, others see sporadic placements. Ad type, vertical, and audience geography all influence match rate. A B2B SaaS newsletter with U.S. readers will see more inventory than a hobbyist cooking list with global traffic.

    If your newsletter qualifies but ad demand is low, revenue can be negligible for months. The network works best for operators who treat it as incremental income, not primary monetisation.

    Payout timing and minimum balance

    Beehiiv pays Ad Network earnings monthly, 30 days after the end of the month in which ads ran. Ads served in November are paid in late December. There’s a $10 minimum payout threshold; balances below that roll forward to the next month. Payment details are outlined in Beehiiv’s Ad Network payment support page (checked November 2026).

    That delay matters if you’re relying on ad revenue to cover operating costs. A campaign that runs in your newsletter today won’t deposit for six to eight weeks. For operators used to Stripe payouts or direct sponsor invoices that clear in days, the lag is a cash-flow adjustment.

    Payments arrive via the method you set in your Beehiiv account settings—typically bank transfer or PayPal. International operators may face currency-conversion fees depending on the payout method and receiving bank.

    When the Ad Network makes sense

    The network works when your time is worth more than the 25% commission. If you’re a solo operator publishing three newsletters a week and don’t want to spend hours pitching sponsors, the trade is efficient. You forfeit a quarter of gross revenue but reclaim the hours you’d spend on sales calls, rate negotiation, and creative back-and-forth.

    It works less well when you already have sponsor relationships or a predictable pipeline. Direct deals let you keep 100% of revenue and negotiate terms—ad placement, creative format, exclusivity—that networks can’t offer. Once your list crosses 5,000 subscribers and you’re fielding inbound sponsor interest, the economics tilt toward direct sales.

    The network also struggles in niches with thin advertiser demand. If your audience is narrow or non-commercial—say, literary fiction or municipal policy—fill rates will be low. Beehiiv’s ad marketplace skews toward categories with established ad spend: tech, finance, e-commerce, productivity.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools and tactics that power online businesses.

    One non-obvious detail: ad creative approval

    Beehiiv reviews advertiser creative before it runs in your newsletter, but you retain veto rights. If an ad doesn’t align with your editorial standards or audience expectations, you can reject it. That approval step is buried in the onboarding flow; many operators assume ads run automatically once they join the network.

    Use the veto. A mismatched ad—crypto pitches in a parenting newsletter, or aggressive upsells in a calm, minimalist publication—damages reader trust faster than the revenue compensates. The 75% you keep only compounds if your list stays engaged.

    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 checkout session expiration: when links die and how to extend

    Stripe checkout session expiration: when links die and how to extend

    Stripe checkout session expiration: when links die and how to extend
    Photo: Politikaner via Wikimedia Commons (CC BY-SA 3.0)

    Stripe checkout sessions—the payment links you generate via the API or dashboard—expire. By default, a session lives for 24 hours. After that, the link returns an error, and your customer sees a blank page or an “expired” message depending on how you built the flow.

    If you’re selling one-time products, launching a course, or running a time-limited offer, session expiration matters. A customer who bookmarks your payment link on Monday may find it dead by Wednesday. Here’s how the mechanism works, how to control it, and when you should shorten or extend the window.

    How Stripe checkout session expiration works

    When you create a checkout session via the Stripe API, you can set an expires_at parameter. This is a Unix timestamp. If you don’t set it, Stripe defaults to 24 hours from session creation (Stripe API reference, checked November 2026).

    The maximum allowed expiration is 24 hours. You cannot extend a session beyond that window without creating a new session. The minimum is effectively immediate—you can set expiration as soon as the session is created, though there’s no practical reason to do so.

    Once a session expires, the URL still resolves, but Stripe shows an error. If you’ve built a custom success or cancel flow, the customer may land on a generic Stripe page instead of your site.

    When to shorten the expiration window

    Flash sales, early-bird pricing, and limited-inventory drops benefit from shorter session lifetimes. If your offer ends at midnight, set expires_at to match that deadline. This prevents customers from bookmarking a checkout link with old pricing and completing payment after the window closes.

    Example: you’re selling 50 seats to a workshop. You open registration at 9:00 AM and close at 5:00 PM the same day. Set session expiration to 5:00 PM. Any link generated during the day dies at the cutoff, and you avoid the edge case where someone checks out at 6:00 PM with a stale session.

    Shorter expiration also reduces the risk of price or inventory desync. If you update a product price or mark it out of stock, existing sessions may still reference the old state until they expire or you manually invalidate them.

    The trade-off: customer friction

    Short expiration windows introduce friction. A customer who adds your link to a tab and returns three hours later may find it dead. They’ll need to start over—navigate back to your site, click through to checkout again, and re-enter payment details if autofill doesn’t catch them.

    For evergreen products or recurring subscriptions, the default 24-hour window usually works. Customers rarely sit on a payment link for more than a few hours, and the risk of stale pricing is low if your product catalog is stable.

    If you’re running a high-touch sales process—say, sending a custom quote via email—consider the 24-hour limit carefully. A prospect who receives your link Monday afternoon may not review it until Tuesday evening. If the session expires, they’ll email you for a new link, and you’ve added a round-trip to the sales cycle.

    One non-obvious detail: session expiration and webhooks

    Stripe does not fire a checkout.session.expired event by default. If you’re tracking session state in your own database, you’ll need to poll or handle expiration client-side. Stripe’s dashboard shows session status, but you won’t get a webhook notification when a session times out unless you’ve built custom logic to listen for the absence of a checkout.session.completed event within your expected window.

    This matters if you’re pre-reserving inventory or seats. If you decrement stock when a session is created and rely on expiration to release it, you’ll need a background job that checks session age and restores inventory for sessions that expired without completion. Stripe won’t do that for you.

    If you’re using Stripe for one-time payments, course sales, or limited-run products, audit your session expiration settings. The default 24 hours is reasonable for most cases, but it’s not universal. Shortening expiration tightens control over pricing and inventory; extending it—within the 24-hour cap—reduces friction for slower-moving prospects.

    Set expiration deliberately. Don’t leave it to default and assume it matches your offer’s lifecycle.

    Have a question about payment flows or checkout quirks? Reply to this email—we read every one and fold operator questions into future issues.

  • Monetisation platform webhooks: when they fire and where they fail

    Monetisation platform webhooks: when they fire and where they fail

    Monetisation platform webhooks: when they fire and where they fail
    Photo by David Pupăză on Unsplash

    Most online operators rely on webhooks to automate post-purchase workflows: add a buyer to your newsletter, grant course access, send a receipt, or trigger fulfillment. Payment and subscription platforms—Stripe, Gumroad, Lemon Squeezy, Paddle—all offer them, but they don’t behave the same way.

    Webhooks are HTTP POST requests the platform sends to your server when an event occurs: a charge succeeds, a subscription renews, a refund is issued. Your endpoint receives a JSON payload, verifies it, and takes action. Simple in theory. In practice, timing windows, retry policies, and failure modes create gaps that can break your automation—and leave customers waiting.

    When webhooks actually fire

    Most platforms send a webhook immediately after an event completes on their side. Stripe fires charge.succeeded within seconds of card capture (Stripe webhooks documentation, checked November 2026). Gumroad queues its sale notification shortly after payment clears. Lemon Squeezy and Paddle follow similar patterns.

    But “immediately” isn’t instant. Network latency, platform load, and internal queueing can introduce delays. Stripe’s documentation notes that webhooks may arrive out of order if multiple events fire in quick succession—so a customer.subscription.updated event can reach your server before the customer.subscription.created that preceded it.

    For high-volume operators, this creates a design constraint: your webhook handler must be idempotent (safe to run more than once on the same event) and tolerant of out-of-order delivery. Store event IDs and check for duplicates before processing.

    Retry logic and failure windows

    When your endpoint is unreachable—server restart, DNS hiccup, deploy in progress—the platform retries. Retry schedules differ.

    Stripe retries failed webhooks for up to three days, with exponential backoff: the first retry happens after a few seconds, subsequent attempts spread over hours (Stripe retry best practices, checked November 2026). If all retries fail, the event is marked as failed in your dashboard. You can manually resend it, but there’s no automatic recovery after the window closes.

    Gumroad retries for 72 hours. Lemon Squeezy follows a similar three-day window. Paddle’s retry schedule is shorter—24 hours—and its documentation warns that events older than that cannot be replayed (Paddle webhooks overview, checked November 2026).

    This matters if you’re migrating servers, changing endpoints, or experiencing downtime. A 48-hour outage on Paddle means lost events. On Stripe, you have a narrow recovery window—but only if you notice the failure and resend manually.

    Where webhooks break silently

    The most common failure mode isn’t a hard error—it’s a silent drop. Your server returns HTTP 200 (success) too early, before the database write completes. The platform marks the webhook as delivered. Your workflow never runs.

    Always acknowledge the webhook after you’ve committed the critical action—writing the order to your database, adding the email to your list, or queueing the follow-up job. Return 200 only when the work is durable. If your server crashes mid-process, return a 5xx status so the platform retries.

    Another silent failure: signature verification bugs. Every platform signs its webhook payloads so you can confirm they’re authentic. Stripe uses HMAC-SHA256 with a signing secret; Gumroad appends a hash parameter. If your verification logic is wrong—comparing the raw body instead of the canonical form, or using the wrong secret after a key rotation—you’ll reject legitimate webhooks and never know why.

    Test your handler with the platform’s CLI tool (Stripe offers stripe listen) and confirm that replayed events trigger the same outcomes as live ones.

    Designing around webhook unreliability

    Webhooks are notifications, not the source of truth. Treat them as a prompt to check the platform’s API, not as the definitive record of what happened. When a charge.succeeded arrives, query the Stripe API for the charge object and verify its status before granting access.

    For mission-critical workflows—access provisioning, high-value purchases—add a fallback: poll the platform’s API periodically for recent transactions and reconcile against your database. If a webhook was dropped or delayed beyond the retry window, your polling job catches it within minutes or hours instead of leaving the customer stuck.

    Store the raw webhook payload in a separate table before processing it. If your automation logic changes or you discover a bug weeks later, you can replay old events from your archive without asking the platform for help.

    Webhooks are the fastest path from payment to fulfillment, but they’re not guaranteed delivery. Build your automation to survive the gaps, and you’ll spend less time manually fixing stuck orders.

    One Two Three Send covers tools, workflows, and infrastructure for online operators. Subscribe to get one focused article every morning.

  • Payment link branding: which processors let you hide their logo

    Payment link branding: which processors let you hide their logo

    Payment link branding: which processors let you hide their logo
    Photo: Donald Trung Quoc Don (Chữ Hán: 徵國單) – Wikimedia Commons – © CC BY-SA 4.0 International.(Want to use this image?)Original publication 📤: –Donald Trung 『徵國單』 (No Fake News 💬) (WikiProject Numismatics 💴) (Articles 📚) 15:26, 1 March 2023 (UTC) via Wikimedia Commons (CC BY-SA 4.0)

    When you send a customer to a payment page, every logo, badge and footer message shapes whether they trust you or the processor. Some platforms let you strip their branding entirely; others lock it in place unless you’re on enterprise plans that cost more than most solo operators will ever pay.

    Here’s what you control—and what you don’t—on the checkout pages you link to from emails, social posts and landing pages.

    Stripe Checkout and Payment Links

    Stripe offers two hosted options: Checkout (embedded or redirect) and Payment Links (standalone URLs you share directly).

    On both, the Stripe wordmark appears in the footer by default. You can remove it—but only if you’re on a paid Stripe plan (Standard starts at 2.9% + $0.30 per transaction; no monthly fee, checked November 2026). The branding toggle lives under Settings → Branding → Checkout appearance. Once disabled, your checkout shows only your own logo and product details.

    If you stay on the free tier, the “Powered by Stripe” footer stays. It’s small, but it’s there on every page.

    Stripe also shows trust badges (card-network logos, security icons) near the payment form. You can’t remove those individually; they’re part of the checkout template. If you use Stripe’s embedded Checkout (checked November 2026) on your own domain, you control everything above and below the iframe, so the perceived branding shrinks further.

    PayPal Standard Checkout

    PayPal’s hosted checkout—what most solo operators use when they paste a button or link—always shows the PayPal logo in the header and footer. There’s no setting to remove it, even on business or premier accounts.

    If you want a fully white-labeled experience, you need Braintree (PayPal’s separate payments platform, checked November 2026), which requires custom integration and approval. Braintree lets you hide PayPal branding entirely, but it’s not a plug-and-play link you can email—it’s an API you wire into your own checkout flow.

    For most operators sending Payment Links, the PayPal logo is permanent.

    Gumroad

    Gumroad checkout pages show the Gumroad logo in the top-left corner and a “Powered by Gumroad” badge in the footer. You can’t remove either on the free tier (10% transaction fee) or the Gumroad Pro plan ($10/month, checked November 2026).

    There’s no enterprise or white-label option. If you use Gumroad, your buyers see Gumroad branding on every page.

    The trade-off: Gumroad’s checkout converts well because buyers recognise the Gumroad interface. The branding isn’t a bug—it’s a trust signal in niches where Gumroad is ubiquitous (indie SaaS, digital products, courses).

    Lemon Squeezy

    Lemon Squeezy’s hosted checkout always includes a “Secured by Lemon Squeezy” badge in the footer. Like Gumroad, there’s no plan tier or setting that removes it.

    You can customize colours, fonts and your own logo in the checkout appearance settings (checked November 2026), but the Lemon Squeezy name stays.

    If you use Lemon Squeezy’s API (checked November 2026) to build your own checkout on your domain, you control the branding entirely—but you’re also responsible for the UI, validation and payment-form plumbing. Most solo operators don’t go that route.

    When branding matters—and when it doesn’t

    If you’re selling to an audience that already knows you, processor branding matters less. A footer logo won’t kill a $29 ebook sale when the buyer clicked from your newsletter.

    It matters more when:

    • You’re running paid traffic to a cold audience, and trust is thin
    • You’re positioning as a premium service, and a third-party checkout dilutes that
    • You’re embedding checkout in a branded funnel, and visual inconsistency creates friction

    In those cases, the extra cost or integration work to strip branding can be worth it. In most other scenarios—especially early on—it’s noise.

    The non-obvious choice

    If you want checkout pages you fully control without API wiring, and you’re already paying for something, Stripe on a paid plan is the cleanest path. The per-transaction cost is the same as the free tier; you’re just unlocking branding removal and a few other appearance toggles.

    If you’re not paying anything yet and don’t want to start, accept that the processor logo will appear. Focus on the copy, the offer and the load speed instead—those move conversion more than a footer badge does.

    Want more breakdowns like this? Subscribe to One Two Three Send—we explain how online-business tools actually work, with no fluff and no affiliate pressure.

  • Subscription landing pages: what converts and what bounces

    Subscription landing pages: what converts and what bounces

    Subscription landing pages: what converts and what bounces
    Photo: SUNILSONI335523 via Wikimedia Commons (CC BY-SA 4.0)

    Most subscription landing pages fail the same way: too many fields, unclear value, buried price. The operator builds the page once, tests nothing, and wonders why traffic converts at 1–2% when the category average sits closer to 6–8%.

    Landing-page conversion isn’t mysterious. It follows predictable patterns, and small structural changes produce measurable lift. The challenge is knowing which five decisions matter most—and testing them methodically instead of guessing.

    Headline and first-screen clarity

    Your headline needs to answer one question in under ten words: what do I get? Not your mission. Not your story. What the subscriber receives, how often, and why it’s worth their attention.

    Bad: “Join thousands of readers who love our content.”
    Better: “Weekly SEO breakdowns. No fluff. Unsubscribe anytime.”

    The first screen—everything visible before scrolling—should contain your headline, one-sentence description, email field, and subscribe button. Nothing else. No testimonials, no feature grid, no founder bio. Those belong further down for visitors who need more convincing.

    Every element above the fold competes for attention. If you add a secondary CTA, a social proof callout, or a “learn more” link, you dilute focus and lower conversion. One action per screen.

    Form friction and field count

    Every additional form field costs you conversions. Email-only forms convert higher than email-plus-name. Email-plus-name converts higher than email-name-company. The pattern holds across platforms.

    Beehiiv and MailerLite both default to email-only signup forms, and most operators never change that. It’s the right default. You can ask for a first name later—after the subscriber has received two or three emails and decided you’re worth keeping.

    If you’re running a B2B newsletter and need company data for sponsorship targeting, collect it in a post-subscribe survey, not on the landing page. Conversion rate matters more than segmentation data you won’t use for three months.

    One exception: if your monetisation model depends on instant segmentation (say, you sell different products to agencies vs. freelancers), a single dropdown is acceptable. But test it. Compare your current conversion rate against a no-dropdown variant for two weeks. Most operators discover they were wrong about needing that field.

    Pricing and expectation-setting

    If your newsletter is free, say so. If it’s free now but will be paid later, say that too. If you’re launching a paid tier soon, show placeholder pricing.

    Conversion psychology favours clarity over surprise. Operators worry that mentioning future paid tiers will scare away free subscribers, but the opposite happens: you filter out people who will churn the moment you announce pricing, and you attract subscribers who expect to pay and are pre-qualified.

    For paid newsletters, show the price on the landing page. Not buried in FAQ copy—in the headline or subhead. “Weekly market research. $15/month or $120/year.” Visitors who bounce on price would have churned after the first paywall email anyway. You want conversions from people who’ve already decided your price is fair.

    Stripe and most subscription platforms report that landing pages with visible pricing convert qualified leads at higher rates than “sign up to learn more” pages, even though total conversions may be lower. Quality over volume.

    Social proof: where and how much

    Testimonials work, but only in the right location. Don’t lead with them. Put subscriber count, logos, or a single pull quote halfway down the page—after the first CTA, before the FAQ section.

    One testimonial is enough. Three is acceptable if they’re short and address different objections (value, frequency, relevance). Ten testimonials signal insecurity and slow page load.

    Subscriber counts work if they’re credible. “Join 247 operators” is honest and feels real. “Join thousands” is vague. “Join 83,000 readers” works if you’re actually that large, but inflate the number and visitors will smell it.

    If you’re just starting and have twelve subscribers, skip the count. Use a single strong testimonial or a one-sentence “as seen in” credential if you have one. No social proof is better than weak social proof.

    One clear ask

    Your landing page should have one goal: collect an email. Not “subscribe or follow on X” or “subscribe or read the archive.” Every alternative you offer splits attention and lowers your primary conversion rate.

    If you want to offer archive access, put it in the footer or on a separate /archive page. If you want to grow social followers, do that after the email confirmation. The landing page is not a homepage. It’s a conversion tool.

    Most operators add links because they’re nervous about appearing pushy. The result is a page that asks for nothing clearly and converts nobody effectively. Pick the one action that matters most to your business—usually an email signup—and design the entire page around that.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on online-business tools, traffic, and monetisation. One email, no fluff, unsubscribe anytime.

    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.

  • Payment link expiration: when Stripe, PayPal and Gumroad URLs die

    Payment link expiration: when Stripe, PayPal and Gumroad URLs die

    Payment link expiration: when Stripe, PayPal and Gumroad URLs die
    Photo: Politikaner via Wikimedia Commons (CC BY-SA 3.0)

    You publish a payment link in a newsletter, a blog post, or a social bio. Three months later, someone clicks it—and nothing happens. The link is dead, the checkout broken, or the product archived.

    Payment link expiration isn’t always obvious. Some platforms time out after inactivity, others when you edit a product, and a few never expire at all. Understanding the rules for each processor helps you decide where to host links that need to last.

    Stripe payment links don’t expire—but products can be archived

    Stripe payment links remain active indefinitely. Once created, the URL works as long as the underlying product and price remain active in your account (Stripe payment links documentation, checked October 2026).

    The failure mode: if you archive the product or deactivate the price attached to the link, the checkout page returns an error. Stripe doesn’t automatically archive products when you stop selling them—you have to do it manually. That means old payment links usually keep working unless you intervene.

    If you need to change pricing or product details, create a new payment link rather than editing the existing product. Editing can break the link for anyone who bookmarked or embedded the old URL.

    PayPal links expire after three years of inactivity

    PayPal payment buttons and hosted checkout links expire if they receive no transactions for three years (PayPal Checkout documentation, checked October 2026). The link remains live as long as someone completes a purchase within that window—each transaction resets the clock.

    For solo operators, this matters most for evergreen content. A blog post from 2023 with an embedded PayPal button will stop working in 2026 if nobody bought through it. You won’t receive a warning; the link just stops resolving to a checkout page.

    PayPal also auto-expires links when you close the connected business account or remove the linked funding source. If you switch banks or sunset a brand, audit which payment links are tied to that account.

    Gumroad links stay live unless you pause or delete the product

    Gumroad product links don’t have a fixed expiration. The URL persists as long as the product remains published in your library (Gumroad product settings help, checked October 2026).

    You can pause sales without breaking the link—the product page still loads, but the buy button is replaced with a “not currently available” message. Deleting the product makes the URL 404.

    One edge case: if you rename the product, Gumroad generates a new slug. The old URL redirects to the new one, but only if the product ID stays the same. If you duplicate a product instead of renaming it, the old link points to an archived copy unless you manually delete it.

    What breaks payment links faster than expiration

    Time limits aren’t the only failure mode. Here’s what kills links before they age out:

    • Currency mismatches. If you change your default currency in Stripe or PayPal, old links may fail for buyers in the original currency region.
    • Tax settings. Enabling tax collection retroactively can break links created before you configured rates, especially in the EU.
    • Account migrations. Moving from PayPal Business to a different account type orphans all existing links—they resolve but can’t process payments.
    • Platform bans. Gumroad suspends accounts for policy violations. All product links return a suspension notice, and there’s no grace period.

    The safest strategy: host payment links on a page you control, not directly in external content. A landing page on your own domain lets you swap the processor or product without updating dozens of embeds.

    How to audit which links are still live

    Most payment platforms don’t offer a bulk link-check tool. You’ll need to manually test links older than six months, especially if they appear in archived newsletters or old blog posts.

    For Stripe, export your product list from the dashboard and filter by creation date. Any product created more than a year ago that you no longer sell is a candidate for archiving—which will break its associated payment links.

    For PayPal, log in to your business account and navigate to payment buttons under Account Settings. The interface shows creation dates but not last-click timestamps, so you’re guessing on activity. If you haven’t sold through a button in over two years, test it.

    Gumroad displays product stats including last sale date. Sort your library by “oldest first” and check whether products with zero sales in the past year are still linked anywhere public.

    If you find dead links embedded in high-traffic pages, replace them immediately. A broken checkout costs more than the time to update the URL.

    Want more breakdowns of how online-business tools actually work? Subscribe to One Two Three Send for weekly explainers on the infrastructure behind newsletters, payments, and content publishing.

  • Payment processor currency conversion fees: where they show up

    Payment processor currency conversion fees: where they show up

    Payment processor currency conversion fees
    Photo by Ibrahim Boran on Unsplash

    If you sell subscriptions, courses, or sponsorships to an international audience, you may be paying a currency conversion charge on every non-USD transaction—and many operators don’t notice until they export a full year of data.

    Payment processors advertise their headline transaction fees (listed on each processor’s pricing page), but the conversion markup sits in a separate line item, often labeled “international card fee” or buried in the settlement report. It’s not illegal. It’s not hidden in the legal sense. It’s just easy to miss until it costs you hundreds of dollars a month.

    What conversion fees look like

    Processors list their conversion charges on their own pricing pages, and the rates differ by country, card type and currency pair. Check them for your own account: Stripe pricing, PayPal merchant fees and Paddle pricing. Checked October 2026.

    The pattern to look for is the same everywhere: the headline processing fee is one line, and a currency conversion or international card charge is a separate line on top.

    When presentment currency matters

    Stripe lets you charge customers in their local currency (called “presentment currency”) if you enable multi-currency support. A customer in Australia sees the price in AUD, pays in AUD, and Stripe settles to you in USD. The conversion charge still applies, but checkout conversion rates often improve when customers see a familiar currency—enough to offset the fee in many cases.

    The non-obvious cost: you now need to manage price rounding. A $49 USD product converts to roughly $76 AUD at current rates. Do you round to $75 or $79? Rounding down improves conversion but cuts margin further. Rounding up can look arbitrary. Most operators pick a psychologically clean number ($77 or $79) and accept the margin variance.

    PayPal offers similar multi-currency presentation but doesn’t let you hold balances in all currencies without a business account upgrade. If you’re on a standard account, everything converts to your primary currency on settlement, and you pay the conversion fee twice if you later need to move money back into a foreign currency for refunds or expenses.

    The decision, in outline

    If a large share of your revenue comes from outside your home currency, showing local prices usually helps checkout, and you should measure whether the lift covers the conversion charge. If only a small share is international, the charge matters more and a single currency may be simpler. Either way, work it out from your own export, not a rule of thumb.

    Where the fees hide in your dashboard

    Stripe’s default dashboard shows gross volume and net payouts. The conversion fee appears in the detailed transaction view under “fees,” but it’s not broken out separately unless you export a full balance report. Go to Balance > Reports > Generate and pull a month’s worth of data. Column J (or thereabouts) will show “currency conversion” as a line item. Sum it. Compare it to your net revenue. If it’s more than 0.5%, you’re handling meaningful international volume.

    PayPal buries it under Statements > All Transactions, then filter by “currency conversion.” The line item shows as a separate deduction, but it’s not aggregated in the monthly summary email. You have to pull a CSV and sum the column manually.

    Paddle bundles tax handling and payments into one fee, so compare the all-in cost on a real payout report rather than the headline rate.

    If you’re running a content business with thin margins—newsletters, paid communities, low-ticket courses—that 1–2% conversion spread is the difference between sustainability and slow burnout. Track it monthly. If it’s growing faster than revenue, your international mix is shifting and your pricing might need adjustment.

    Want more operator-to-operator breakdowns of the costs nobody warns you about? Subscribe to One Two Three Send and get the next one in your inbox.

  • Course platforms charge you twice: hosting fee plus transaction cut

    Course platforms charge you twice: hosting fee plus transaction cut

    Course platforms charge you twice: hosting fee plus transaction cut
    Photo by Jono Hirst on Unsplash

    If you’re selling a course, cohort, or paid community, you’re probably paying for it twice: once as a monthly platform fee, and again as a percentage of every transaction that clears.

    That’s not hidden. Most platforms advertise both. But the cumulative cost surprises operators who hit their first $5,000 month and realize they just handed over $150 in transaction fees on top of the $79 they paid to access the platform in the first place.

    Here’s how the pricing actually works, when the double charge makes sense, and when you should rebuild on infrastructure you control.

    How course platform pricing breaks down

    Most hosted course platforms use a tiered model with two components:

    • Monthly or annual subscription: $29–$299/month depending on feature access, student cap, or number of courses.
    • Transaction fee: 0–5% of gross revenue per sale, sometimes with a per-transaction ceiling.

    Teachable charges 0% on its $159/month Pro plan but takes 5% on the $39/month Basic tier. Kajabi bundles everything at $149/month with no transaction fees. Podia sits at $89/month with zero transaction cut. Thinkific’s free plan exists, but you pay 10% per sale until you upgrade.

    The trade-off is predictable: pay more upfront to keep transaction fees low, or start cheap and give up margin as you grow.

    Where it gets expensive is the middle ground—$2,000 to $15,000 in monthly course revenue. You’re paying a platform fee that assumes scale, and losing 2–5% on every sale because you haven’t hit the tier that waives the transaction cut.

    When the double charge makes sense

    If you’re launching your first course or testing a new offer, a hosted platform with both fees is still the right call. You get:

    • Payment processing built in (no Stripe integration required)
    • Student login, drip scheduling, and certificate generation without custom dev
    • Email sequences tied to course progress
    • Mobile apps on some platforms

    The transaction fee funds the infrastructure you’d otherwise build yourself. For a $500 launch, paying $25 in transaction fees plus a $39 platform subscription is cheaper and faster than standing up a membership site on WordPress, wiring Stripe webhooks, and writing conditional access logic.

    The model also works if your course revenue is unpredictable. A 5% variable cost beats a $300/month fixed cost when you’re selling $1,200 some months and $200 others.

    When to move off double-fee platforms

    Once you clear $10,000/month in course sales, the transaction fees start to hurt. At $10,000/month and a 3% transaction fee, you’re paying $300/month in cuts plus your base subscription. That’s $3,600/year in transaction drag.

    At that point, you have three exits:

    Option one: Upgrade to a plan that waives transaction fees. Kajabi and Podia don’t charge per sale. You pay more upfront, but your margin per student stays consistent.

    Option two: Move to a WordPress membership plugin (MemberPress, Restrict Content Pro, LearnDash) and connect your own Stripe account. You’ll pay Stripe’s standard 2.9% + 30¢, but nothing additional to the course platform. Hosting costs $30–$100/month depending on your provider and traffic load.

    Option three: Use a headless setup—sell access via Gumroad or your own Stripe checkout, then grant course access via Memberful, Circle, or a custom-built student portal. You control the payment flow and only pay Stripe’s processing fee.

    What most operators miss

    Transaction fees compound with payment-processor fees. If your course platform takes 3% and Stripe takes 2.9%, you’re losing nearly 6% of every sale before taxes, refunds, or chargebacks. On a $500 course, that’s $30 gone before you see a dollar.

    Some platforms (Thinkific, Teachable) let you bring your own Stripe account, which means you see the full sale minus Stripe’s cut—but you still owe the platform its transaction percentage. Others (Kajabi) process payments on your behalf and remit net revenue to you. Read the fine print. If the platform holds funds for 24–72 hours, that affects your cash flow during launch weeks.

    The breakeven math

    Here’s a rough model. Assume:

    • Platform A: $79/month + 3% transaction fee
    • Platform B: $149/month + 0% transaction fee

    You break even when $79 + (0.03 × revenue) = $149, which happens at $2,333 in monthly course sales. Above that number, Platform B is cheaper. Below it, Platform A wins.

    Run this calculation for your own numbers. If you’re selling $8,000/month on a platform charging $50/month + 5%, you’re paying $450/month total. A zero-transaction-fee platform at $150/month saves you $300 every month.

    One thing to do this week

    Pull your last 90 days of course revenue and calculate what you paid in platform fees vs. transaction fees. If transaction fees are larger than your base subscription, model what you’d pay on a higher tier or a different platform.

    If you’re clearing $5,000/month or more, the savings are real. And if you’re just launching, don’t overthink it—pick the platform that gets you live fastest, even if it charges twice. You can always migrate once the revenue justifies it.

    Got a question about course platforms, pricing models, or migration logistics? Reply to this email—we read everything and pull the best questions for future editions.

  • Affiliate link attribution windows: when credit expires

    You send someone to a product through your affiliate link in January. They bookmark the page, think about it, and buy in March. Do you get paid?

    Usually not. Most affiliate programs use a fixed attribution window—a clock that starts ticking the moment someone clicks your link. If the purchase happens after that window closes, the commission disappears. No pro-rating, no partial credit, no notification.

    If you’re running a content site, newsletter, or course with affiliate revenue, you need to know how long your windows are and what happens when they expire. Here’s what actually determines whether you get paid.

    How attribution windows work

    When someone clicks your affiliate link, the merchant (or network) drops a cookie or session identifier in their browser. That token tracks two things: which affiliate sent the traffic, and when the click happened.

    If the user completes a purchase before the window closes, you get credited. If they return after the window expires—even if they use the same browser—the system treats them as a direct visitor. The sale goes unattributed, or worse, it gets attributed to the last affiliate link they clicked.

    Most SaaS and digital-product programs use one of three standard windows:

    • 30 days: Common for low-ticket or high-volume products. Examples include MailerLite, Brevo, and many WordPress plugin marketplaces.
    • 60 days: Mid-range. Used by tools with longer consideration cycles, like project management or analytics platforms.
    • 90 days: Rare, but not unheard of. Some enterprise SaaS and high-ticket course platforms extend this far.

    A few programs—usually those with recurring subscriptions—use a hybrid model: a 30-day window for the first purchase, then lifetime commission as long as the customer stays subscribed. Beehiiv and some hosting affiliate programs work this way.

    What resets the clock and what doesn’t

    Here’s where it gets messy. Attribution windows don’t always behave the way you’d expect.

    Clicking your link again resets the timer. If someone clicked your link in January, then clicked it again in February, the window starts over from February. This is why retargeting the same audience—through follow-up emails, retargeting ads, or repeated social posts—can extend your effective window.

    Visiting the site directly does not reset it. If they click your link once, then return via bookmark or organic search, the original clock keeps running. The merchant’s system doesn’t know they came back unless they click another tracked link.

    Clearing cookies kills the attribution immediately. Most affiliate tracking relies on browser cookies. If the user switches devices, uses incognito mode, or runs a cookie cleaner, the link between your referral and their session disappears. This is more common than most affiliates realize—especially among privacy-conscious audiences.

    Why long consideration cycles hurt affiliate revenue

    If you’re promoting a $500/year tool or a $2,000 course, your audience isn’t buying on impulse. They’re comparing options, reading reviews, waiting for budget approval, or just procrastinating.

    The problem: a 30-day attribution window assumes a fast buying cycle. If your content attracts researchers who take 60 or 90 days to decide, you’ll send plenty of traffic and see weak conversion numbers—not because your audience isn’t buying, but because they’re buying outside your window.

    I’ve seen this play out with hosting referrals. Someone reads a performance comparison in October, sets a calendar reminder to migrate in January when their current plan renews, and buys direct. The affiliate who did the research gets nothing.

    What you can do about it

    You can’t change the attribution window, but you can work around it.

    Track your own click timestamps. Use a link shortener or UTM parameters that log to your analytics. Compare your click dates against conversion dates reported by the affiliate network. If you see a pattern—lots of clicks in month one, conversions spiking in month three—you know your window is too short for your audience.

    Retarget clickers before the window closes. If you’re promoting a product with a 30-day window, send a follow-up email at day 20. Frame it as a reminder, a case study, or a bonus resource. The goal is to get them to click again and reset the timer.

    Focus on products with longer windows or lifetime cookies. If your content naturally attracts slow decision-makers, prioritize affiliate programs that offer 60- or 90-day windows, or those that credit you for the lifetime of the subscription. Postmark and some WordPress hosting programs lean this way.

    Build an email list and nurture before promoting. If someone joins your list and you send them an affiliate link six weeks later, the 30-day clock starts fresh. You’re not racing against a window that started when they first discovered you.

    One more thing: last-click attribution

    Even if your window is still open, you can lose credit if the customer clicks another affiliate’s link before buying. Most programs use last-click attribution, meaning the most recent referrer wins.

    This is why you see affiliates aggressively retargeting the same audience, running comparison posts that link to competitors, and sending discount reminders. They’re not just trying to convert—they’re trying to be the last click.

    If you want a larger share of your affiliate revenue to stick, treat your links like a checkout flow: keep the path short, reduce the time between click and purchase, and don’t assume a single mention will carry you through a 60-day consideration cycle.

    Want more breakdowns of how online-business infrastructure actually works? Subscribe to One Two Three Send and get one operator-focused article like this every day.

    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’s payment intent lifecycle: where charges wait and why

    Stripe’s payment intent lifecycle: where charges wait and why

    Stripe's payment intent lifecycle: where charges wait and why
    Photo: Zina Deretsky, National Science Foundation via Wikimedia Commons (Public domain)

    Most solo operators think Stripe charges happen instantly. Click the button, money moves, done. But behind every payment sits a state machine with six distinct phases—and knowing where your charge actually is can save you hours of customer-support confusion and lost revenue.

    Payment intents are Stripe’s core transaction object. They track a single charge from creation to completion, and they don’t always move in straight lines. Here’s how the lifecycle actually works, what delays the flow, and one non-obvious trick that prevents duplicate charges.

    The six states every payment intent moves through

    When a customer submits payment, Stripe creates a PaymentIntent object. It starts in one of these states:

    • requires_payment_method – Intent created, but no card attached yet. Happens when you create the intent server-side before the customer sees the form.
    • requires_confirmation – Card attached, waiting for you to confirm the charge. Manual confirmation mode only.
    • requires_action – 3D Secure or bank authentication needed. This is where most “the payment didn’t go through” support emails come from.
    • processing – Stripe is talking to the bank. Usually lasts 1–3 seconds, but can hang for minutes on certain card networks.
    • requires_capture – Charge authorized, waiting for you to capture it. Only applies if you’ve enabled manual capture.
    • succeeded – Money secured. You can fulfill the order.

    Failed charges land in canceled or move back to requires_payment_method if you want to let the customer retry with a different card.

    Where charges stall—and what to check

    The most common hangup is requires_action. Stripe redirects the customer to their bank for 3D Secure authentication, but if the popup gets blocked, the redirect fails silently, or the customer closes the window, the intent never progresses. The charge stays pending indefinitely.

    Stripe’s webhook fires a payment_intent.requires_action event. If you’re not listening for it, you’ll never know the customer is stuck. Set up a webhook listener that emails the customer a direct authentication link when this fires—Stripe includes it in the next_action.redirect_to_url field.

    Processing delays happen more often than Stripe’s docs suggest. Visa and Mastercard usually respond in under two seconds, but Discover, certain co-branded cards, and international issuers can take 15–30 seconds. If your checkout flow redirects to a confirmation page immediately after submission, customers see a blank order and panic. Wait for the payment_intent.succeeded webhook before showing success.

    Manual capture mode (requires_capture) is useful for high-value orders where you want to authorize the charge but delay settlement until you ship. But Stripe auto-cancels uncaptured intents after seven days. If you’re running a pre-order or made-to-order business, you need to either capture within a week or switch to a different payment flow entirely—like invoices with NET terms.

    The idempotency key trick

    Here’s the non-obvious tip: Stripe’s API accepts an idempotency_key parameter on every PaymentIntent creation request. If your customer double-clicks the submit button, or your server retries a failed request, Stripe checks the key. If it matches an existing intent created in the last 24 hours, Stripe returns the original object instead of creating a duplicate charge.

    Most client libraries don’t set this automatically. You need to generate a unique key per transaction—usually a hash of the user ID, cart total, and timestamp—and pass it explicitly:

    stripe.paymentIntents.create({ amount: 5000, currency: 'usd' }, { idempotencyKey: 'user123_1697654400_5000' });

    Without this, double-click bugs charge customers twice. Stripe won’t refund both automatically—you’ll eat the dispute fee and the support time.

    When to use automatic vs. manual confirmation

    Stripe defaults to automatic confirmation: as soon as the card is attached, the charge fires. This works for most solo operators. But if you’re running a multi-step checkout—cart → shipping → payment—and you want to confirm inventory or apply fraud checks before charging, switch to manual confirmation mode.

    Set confirmation_method: 'manual' when creating the intent. The intent will pause at requires_confirmation until you call stripe.paymentIntents.confirm(). This gives you a hook to run your own validation logic server-side before money moves.

    Manual confirmation adds complexity—you need to handle the confirmation call in your webhook flow or backend—but it prevents scenarios where Stripe charges a customer for an out-of-stock item because your inventory check ran after payment.

    What to monitor in your dashboard

    Stripe’s dashboard shows payment intent states in real time, but it doesn’t alert you when intents get stuck. Set up a daily filter for intents in requires_action or processing that are older than 30 minutes. Those are your lost conversions—customers who started checkout, hit a snag, and never came back.

    For automated monitoring, pull the payment_intent.processing and payment_intent.requires_action webhook events into your analytics tool and track time-to-resolution. If your median processing time jumps above five seconds, you’re either seeing more international cards or your webhook handler is slow.

    One more thing: Stripe’s test mode doesn’t simulate processing delays. Test cards move instantly from requires_confirmation to succeeded. If you want to test your timeout logic, you need to use a live-mode charge with a real card in a staging environment, then immediately refund it.

    Got a payment-flow question? Reply to this email—I’ll cover it in a future breakdown. And if you found this useful, forward it to another operator who’s wiring up Stripe for the first time.