Category: Monetisation

  • Sponsored content briefs: what brands actually send you

    Sponsored content briefs: what brands actually send you

    Sponsored content briefs: what brands actually send you
    Photo by Annie Spratt on Unsplash

    The first time a brand sends you a sponsorship brief, it doesn’t look like the simple “mention us in your next post” pitch you expected. It’s a PDF with sections titled Messaging Guidelines, Exclusivity Window, and Usage Rights—and half of it contradicts what the sales rep told you over email.

    Here’s what you’ll actually see when a brand commits to sponsoring your content, and which parts you need to read twice before signing.

    The deliverables grid

    Most briefs open with a table: one column for asset type, one for quantity, one for due date. A typical $2,000 sponsorship for a newsletter operator might list:

    • One dedicated email send (minimum 500 words)
    • Two social posts (one Instagram, one Twitter/X)
    • One permanent blog post with dofollow link
    • Performance report due seven days post-send

    Brands almost always want more than the email. If your initial pitch was “sponsored newsletter slot,” expect the brief to bundle in at least one social amplification requirement. Budget accordingly—those extra deliverables take time, and the fee rarely adjusts upward to match.

    The due dates are usually staggered. The email might be due August 28, but the social posts often have a “within 72 hours of email send” clause. That means you’re not done on send day.

    Messaging guidelines and the red-pen test

    This section tells you what to say—and what you can’t. You’ll see:

    • Required talking points (“emphasize ease of setup”)
    • Prohibited comparisons (“do not mention [Competitor A] or [Competitor B] by name”)
    • Mandatory disclosures (FTC compliance language, sometimes pre-written)
    • Tone guidance (“conversational, not salesy”—ironic, given the constraints)

    The tighter the guidelines, the less the content will sound like you. If a brand sends you three full paragraphs of pre-written copy and asks you to “adapt it to your voice,” you’re ghostwriting their ad, not creating sponsored content. That’s fine if the price reflects it, but a $1,500 fee for what amounts to light editing is low.

    Some operators push back here. If the brief leaves you fewer than 200 words of original writing in a 600-word piece, ask for either a higher fee or more creative latitude. Brands used to working with larger creators are often flexible; performance marketing teams less so.

    Exclusivity windows and category blocks

    Buried mid-brief, you’ll find the exclusivity clause. It typically reads: “Creator agrees not to promote competing products in the [category] for [30/60/90] days before or after this campaign.”

    If you run a newsletter about productivity tools and you sign a 60-day exclusivity window for a task manager sponsor, you’ve just locked yourself out of promoting any other task manager—including affiliate links—for four months. That’s fine if this sponsor pays enough to replace that affiliate revenue. It’s not fine if you didn’t notice the clause until after you signed.

    Watch for category definitions. A “project management tool” exclusivity clause might be interpreted by the brand to include time trackers, note apps, or even calendar tools. Get the category scope in writing. If the brand says “we mean direct competitors only,” ask them to list those competitors by name in the brief.

    Usage rights and reshare permissions

    The final section covers what the brand can do with your content after you publish it. Common clauses:

    • Perpetual right to reshare the content on brand-owned channels
    • Permission to edit for length (social clips, pull quotes)
    • Inclusion in paid media (your face in their Facebook ads)
    • White-label rights (republishing with attribution removed)

    Most operators accept resharing and light editing. Paid media inclusion should come with a separate fee—your likeness in their ad campaign is worth more than a single sponsored post rate. White-label clauses are rare, but they exist; push back hard unless the fee is 3–5× your normal rate.

    If the brief is silent on usage rights, clarify in writing before you publish. Default assumptions vary by industry. SaaS brands usually assume they can reshare excerpts; agencies sometimes assume they own the entire asset.

    What to do before you countersign

    Read the brief twice. Once for deliverables and price, once for constraints and rights. If any section is vague—especially exclusivity, usage rights, or revision limits—reply with clarifying questions before you agree. Brands expect this. The ones that don’t aren’t worth working with.

    Keep a simple checklist: Does the scope match what we discussed? Is the exclusivity window acceptable given my other revenue streams? Are the due dates realistic? Do I retain enough creative control that this will still sound like my work?

    If the answer to any of those is no, send a redline. Most brands would rather negotiate than start over with another creator.

    Got a sponsorship question that isn’t covered here? Reply to this email—we’re collecting operator questions for an upcoming Q&A piece.

  • Productized service revenue: forecasting retainer churn vs. new bookings

    Productized service revenue: forecasting retainer churn vs. new bookings

    Productized service revenue: forecasting retainer churn vs. new bookings
    Photo by Invest Europe on Unsplash

    If you run a productized service—content writing packages, design retainers, SEO audits sold monthly—you’ve probably built a revenue forecast that looked great in January and fell apart by March.

    The culprit: most operators model new bookings but treat churn as an afterthought. You add projected monthly recurring revenue from new clients, assume everyone renews, and wonder why actual cash is 20% lower than the spreadsheet promised.

    Retainer businesses don’t grow linearly. They grow in steps, then lose a piece, then step again. Forecasting both movements—accurately—requires separating the two flows and tracking them with different assumptions.

    Why churn breaks simple revenue models

    A typical productized service forecast starts with current MRR, adds expected new clients at your average package price, multiplies by twelve months, and calls it done.

    But retainer churn isn’t binary. Clients don’t all leave at once—they trickle out. A $2,000/month design retainer might churn in month four. A $500 content package might renew for eight months, then pause for two, then restart at $300.

    If you’re forecasting new bookings at $10,000 MRR per month and losing $3,000 to churn every month, your net growth is $7,000—but most forecasts show $10,000 because churn is invisible until it happens.

    The fix: track gross new MRR and gross churn MRR separately, then calculate net monthly change. This gives you three numbers instead of one, and it exposes whether you’re growing because you’re selling well or just because churn hasn’t caught up yet.

    Model churn as a monthly percentage, not a yearly average

    Annual churn rate—say, 25%—sounds manageable. But if you apply it evenly across twelve months, you’re assuming the same clients leave every period. That’s not how retainers work.

    Clients churn in clusters: budget resets in January, mid-year strategy shifts in June, end-of-contract renewals in December. If you sell a six-month retainer, churn spikes in month seven. If you sell annual packages, churn concentrates around renewal month.

    Instead of spreading 25% annually, model churn month-by-month based on contract length. If 40% of your clients are on six-month retainers, expect churn to spike every six months. If 30% are month-to-month, expect steady 5–8% monthly churn from that cohort.

    Build a simple table: cohort start month, contract length, expected churn month. Then sum churn by month. It’s more work than a single percentage, but it prevents the surprise of losing $8,000 MRR in one week because five contracts ended simultaneously.

    Forecast new bookings with a confidence tier

    New bookings aren’t certain until the invoice is paid. But most revenue forecasts treat pipeline conversations the same as signed contracts.

    Separate your bookings forecast into three tiers: signed and started (100% confidence), contract sent and verbally agreed (60–70%), active proposal or discovery call scheduled (20–30%). Multiply expected MRR by the confidence weight, then sum across tiers.

    This gives you a weighted pipeline value instead of a binary “we’re closing five clients this month” guess. If you have $15,000 in signed MRR, $8,000 in sent contracts, and $12,000 in proposals, your weighted new MRR is $15,000 + ($8,000 × 0.65) + ($12,000 × 0.25) = $23,200, not $35,000.

    Update the weights weekly. If your “sent contract” close rate is actually 80%, raise the multiplier. If proposals convert at 15%, lower it. The model gets more accurate the longer you run it.

    Track the gap between bookings and cash received

    Retainer invoices don’t always pay on time. A $3,000/month client might sign in August, start work in September, and pay the first invoice in October. Your MRR went up in August, but cash flow didn’t move until October.

    Separate your forecast into two views: MRR booked (when the contract starts) and cash received (when payment clears). The gap between them is your working capital need.

    If you’re booking $10,000 new MRR per month but cash lags 30 days behind, you need $10,000 in the bank to cover the gap. If half your clients pay net-30 and the other half pay upfront, the gap shrinks to $5,000—but it’s still there.

    Most productized service operators don’t track this until they can’t make payroll. Build it into the forecast from the start: MRR booked this month, expected cash next month, any overdue invoices dragging into month three.

    One spreadsheet, three tabs

    You don’t need expensive forecasting software. A Google Sheet with three tabs works: one for new bookings (weighted pipeline), one for churn by cohort and contract length, one for net MRR and cash flow.

    Update bookings weekly. Update churn monthly when contracts renew or cancel. Compare forecast vs. actual every month and adjust your confidence multipliers and churn rates based on what actually happened.

    The forecast won’t be perfect. But it’ll be close enough to catch a cash crunch two months out instead of two weeks out—and that’s the difference between scaling smoothly and scrambling to replace a lost retainer overnight.

    Want more operator-focused breakdowns like this? Subscribe to One Two Three Send—we publish daily guides on tools, workflows, and monetisation for people running online businesses.

  • Newsletter sponsorship pricing: flat rate vs. CPM vs. performance

    Newsletter sponsorship pricing: flat rate vs. CPM vs. performance

    Newsletter sponsorship pricing: flat rate vs. CPM vs. performance
    Photo by Woliul Hasan on Unsplash

    Most newsletter operators pick a sponsorship pricing model based on what they’ve seen other people charge. That works until a sponsor pushes back, or you realize you left money on the table because your open rate spiked after you locked in a flat fee.

    The three common models—flat rate, CPM (cost per thousand impressions), and performance-based—aren’t interchangeable. Each one shifts financial risk between you and the sponsor, and the right choice depends on your list size, niche stability, and how predictable your engagement is.

    Flat rate: predictable revenue, capped upside

    A flat rate means you charge the same amount regardless of opens, clicks, or conversions. A sponsor pays $500 for a mention in next Tuesday’s issue, period.

    When it works: Flat rates make sense when your list is under 5,000 subscribers and fluctuates week to week, or when sponsors care more about brand association than measurable performance. If you write about a tight niche—like SaaS financial planning or Webflow development—sponsors often pay for access to a specific audience, not raw impressions.

    The risk you carry: If your open rate drops from 45% to 32% because you changed your subject line format or your ESP flagged a spam issue, you still owe the sponsor the same exposure. You absorb that variance.

    One non-obvious move: If you sell flat-rate sponsorships, specify a minimum list size or a floor open rate in your media kit. That way, if your list shrinks unexpectedly, you can renegotiate or pause the deal without breaching the agreement.

    CPM: scales with engagement, requires volume

    CPM pricing charges per thousand opens (or sends, depending on how you define “impression”). If you charge $40 CPM and 6,000 people open the email, the sponsor pays $240.

    When it works: CPM makes sense once your list exceeds 10,000 subscribers and your open rate is stable. Sponsors who buy CPM deals usually run them across multiple newsletters simultaneously and care about cost efficiency at scale. They’re comparing your $40 CPM to someone else’s $55.

    The risk the sponsor carries: If your open rate climbs from 38% to 50% because you tightened your subject lines, the sponsor pays more for the same ad slot. That’s why CPM buyers almost always ask for historical open rate data before committing.

    Pricing benchmark: As of mid-2026, B2B newsletter CPMs range from $30 to $80 depending on niche. Developer tools and finance newsletters command the high end; general business content sits closer to $35–$45.

    Performance-based: aligned incentives, delayed payment

    Performance deals tie payment to outcomes: cost per click (CPC), cost per signup, or cost per sale. The sponsor pays $2 for every click to their landing page, or 20% of revenue from customers who convert within 30 days.

    When it works: Performance pricing works when the sponsor has a tight attribution model and you’re confident your audience acts on recommendations. Affiliate programs and course launches almost always use performance terms. SaaS trials sometimes do, too.

    The risk you carry: You can send to 15,000 people, write a strong callout, and still earn nothing if the sponsor’s landing page loads slowly or their offer doesn’t resonate. You’ve spent the inventory; they’ve paid $0.

    What to negotiate: If you agree to performance pricing, ask for a small flat fee as a baseline—say, $200 guaranteed plus $1.50 per click above 100 clicks. That way, you’re compensated for the list access even if conversion falls short.

    Hybrid models: combining upfront + performance

    Some operators charge a modest flat fee ($300) plus a performance kicker (10% of attributed revenue, or $0.75 per click). This splits risk more evenly and works well when both parties are testing fit for the first time.

    Hybrid deals also make renewals easier. If the performance component delivers, the sponsor comes back and often agrees to raise the flat-rate floor. If it underperforms, you’ve still covered your baseline cost.

    Which model to lead with

    If your list is under 5,000 and growing inconsistently, start with flat rates. Lock in predictable revenue while you stabilize open rates and refine your pitch.

    Once you cross 10,000 subscribers and your monthly open rate variance drops below 5 percentage points, switch to CPM. You’ll earn more as your list grows, and sponsors will find your pricing easier to compare.

    Save performance-based deals for sponsors who already know your audience converts—typically after you’ve run one flat-rate or CPM test with them and the click-through rate exceeded 3%.

    One last note: whichever model you pick, write it into a short sponsorship agreement before you send the invoice. Specify the pricing model, the measurement window, and what happens if you need to reschedule the send. It’s a two-paragraph PDF, and it prevents confusion when the sponsor’s finance team asks why the invoice doesn’t match their internal estimate.

    Want more on running a content business without guessing? Subscribe to One Two Three Send and get one operator-focused article like this in your inbox weekly.

  • Lemon Squeezy’s webhook signature verification: how it works

    Lemon Squeezy’s webhook signature verification: how it works

    Lemon Squeezy's webhook signature verification: how it works
    Photo: Iamovichowdhury via Wikimedia Commons (CC BY-SA 4.0)

    If you’re running a paid newsletter, course platform, or membership site on Lemon Squeezy, you’re probably listening for webhooks to provision access, update subscriber status, or log revenue events. But every webhook Lemon Squeezy sends includes a signature header that most operators ignore—and that’s a problem.

    Webhook signature verification isn’t optional security theater. It’s the only way to confirm that the POST request hitting your server actually came from Lemon Squeezy, not a malicious actor replaying old payloads or inventing fake subscription events.

    Here’s how Lemon Squeezy’s signature system works, how to validate it in your code, and one non-obvious edge case that breaks verification even when you’ve done everything right.

    How Lemon Squeezy generates the signature

    Every webhook Lemon Squeezy sends includes an X-Signature header. This is an HMAC-SHA256 hash of the raw request body, signed with your webhook signing secret.

    You’ll find your signing secret in the Lemon Squeezy dashboard under Settings → Webhooks. It looks like a long alphanumeric string starting with whsec_. Each webhook endpoint you create gets its own secret—if you rotate or delete an endpoint, the secret changes.

    The signature process is straightforward: Lemon Squeezy takes the entire JSON payload, hashes it using HMAC-SHA256 with your secret as the key, then sends the resulting hash in the header. Your server’s job is to recreate that hash and compare it to what was sent.

    Validating the signature in your code

    Here’s a minimal Node.js example using Express and the built-in crypto module:

    const crypto = require('crypto');
    const express = require('express');
    const app = express();
    
    const WEBHOOK_SECRET = process.env.LEMON_SQUEEZY_SECRET;
    
    app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
      const signature = req.headers['x-signature'];
      const payload = req.body;
    
      const hash = crypto
        .createHmac('sha256', WEBHOOK_SECRET)
        .update(payload)
        .digest('hex');
    
      if (hash !== signature) {
        console.error('Invalid signature');
        return res.status(401).send('Unauthorized');
      }
    
      // Signature valid—process the webhook
      const event = JSON.parse(payload);
      console.log('Event type:', event.meta.event_name);
    
      res.status(200).send('OK');
    });
    

    Two things to note: you must use express.raw() to preserve the raw request body. If you parse the JSON first with express.json(), the signature won’t match—whitespace, key order, and encoding all matter. You also need to compare the hash as a hex string, not a buffer.

    If you’re using PHP, the process is similar with hash_hmac(). Python uses hmac.new() from the standard library. The algorithm is the same across languages.

    The edge case: timestamp drift and replay attacks

    Lemon Squeezy doesn’t include a timestamp in the signature itself, which means a valid webhook payload can be replayed indefinitely. If an attacker intercepts a legitimate webhook—say, a subscription cancellation event—they can resend it to your endpoint days or weeks later, and your signature check will pass.

    The mitigation is to track processed webhook IDs. Every Lemon Squeezy webhook includes a unique meta.webhook_id field in the payload. Before processing the event, check whether you’ve already seen that ID. If you have, return a 200 status but skip the business logic.

    Store processed IDs in a database table with a TTL—30 days is reasonable. This prevents replay attacks without requiring you to implement a sliding timestamp window.

    Here’s the addition to the earlier example:

    const event = JSON.parse(payload);
    const webhookId = event.meta.webhook_id;
    
    // Check if already processed (pseudo-code)
    if (await db.webhookExists(webhookId)) {
      console.log('Duplicate webhook, ignoring');
      return res.status(200).send('OK');
    }
    
    await db.saveWebhookId(webhookId);
    // Continue processing...
    

    When verification fails even though it shouldn’t

    If your signature check is failing consistently and you’re confident the secret is correct, check your server’s request body size limit. Some frameworks—Express included—default to a 100kb limit. Lemon Squeezy’s order_created webhooks can exceed that if the order includes multiple line items or custom data fields.

    Increase the limit in your middleware config: express.raw({ type: 'application/json', limit: '1mb' }).

    The other common culprit is proxies or load balancers that rewrite the request body. If you’re behind Cloudflare, Nginx, or AWS ALB, confirm that the raw body is being forwarded unmodified. A single trailing newline or whitespace change will break the hash.

    Lemon Squeezy doesn’t currently offer a signature verification test mode or sample payloads with pre-signed signatures, so the easiest way to debug is to log both the computed hash and the received signature, then compare them character by character.

    If you’re handling payments or provisioning access via webhooks, signature verification isn’t optional. It’s the only way to distinguish legitimate events from forged requests. Set it up once, test it with a live webhook, and add replay protection if your product handles high-value transactions.

    Got a question about webhook security or payment automation? Reply to this email—we cover this stuff every week.

  • Stop refreshing Stripe—affiliate networks delay payouts by design

    Stop refreshing Stripe—affiliate networks delay payouts by design

    Stop refreshing Stripe—affiliate networks delay payouts by design
    Photo by Fahim Junaid on Unsplash

    You check your affiliate dashboard. The clicks are there. The conversions are confirmed. The revenue number updates in real time. But the money doesn’t hit your account for another 60 days.

    This isn’t a bug. It’s how affiliate networks are built—and understanding the gap between “earned” and “paid” changes how you budget, forecast, and pick which programs to join.

    Why affiliate networks hold payments

    Most affiliate programs operate on net-30, net-60, or net-90 payment terms. That means if you generate a sale on August 1, the network pays you 30, 60, or 90 days after the end of the month in which the sale occurred—so September 30, October 30, or November 1 at the earliest.

    The delay isn’t arbitrary. Networks wait because:

    • Refund windows: Many products allow 14-, 30-, or 60-day returns. Networks withhold payment until the refund window closes to avoid clawing back commissions later.
    • Fraud detection: Payment processors and affiliate platforms use the delay to identify patterns—chargebacks, coupon abuse, cookie-stuffing—that invalidate commissions.
    • Cash flow smoothing: The merchant doesn’t pay the network immediately either. The delay synchronizes inbound and outbound cash.

    For SaaS affiliate programs, the lag can stretch even further. Annual subscriptions sometimes hold first-month commissions until the customer passes 60 or 90 days active, ensuring the sale wasn’t fraudulent or immediately refunded.

    How payment timing varies by program type

    Not all affiliate programs use the same clock. Here’s what to expect:

    Self-hosted platforms: Tools like Easy Affiliate (WordPress) and Rewardful (Stripe-native) let merchants set their own terms. Default is often net-30, but some operators push to net-60 to pad working capital.

    Marketplace networks: Amazon Associates pays roughly 60 days after month-end. Impact and ShareASale default to net-30 but vary by merchant. PartnerStack is often net-60 for SaaS.

    Direct partnerships: If you negotiate a private affiliate deal, payment terms are negotiable—but expect net-30 as the starting point unless you have leverage or volume.

    The fastest-paying programs are usually membership platforms or newsletters using Stripe-native tools like Rewardful, where the merchant can configure near-real-time payouts. But even then, most leave a 14-day buffer to catch refunds.

    How to forecast when you’ll actually get paid

    The mistake most operators make: treating dashboard revenue as cash in hand. It’s not. It’s a promise to pay, subject to refunds, fraud checks, and the network’s payment schedule.

    Here’s how to model it:

    Track three dates per sale: Conversion date, commission confirmation date, and scheduled payout date. Most dashboards show the first two; you have to calculate the third yourself.

    Build a rolling 90-day cash forecast: Use a spreadsheet with columns for each week. Drop expected payouts into the week they’ll actually arrive, not the week you earned them.

    Flag minimum payout thresholds: Many networks (Amazon, Impact, CJ) only pay when you hit $50–$100 in commissions. If you’re earning $40/month from a program, your first payment might take three months—even on a net-30 schedule.

    Watch for holds on new accounts: Some networks extend the payment window for your first 1–3 payouts. ShareASale, for example, holds first payments longer to establish trust.

    When to drop a program over payout terms

    A high commission rate matters less if cash flow timing breaks your budget. Here’s when to walk:

    Net-90 with a high refund rate: If the product has a 30-day trial and the network waits 90 days post-month-end, you’re looking at 120+ days to cash. That’s a loan you’re giving the merchant.

    Rolling holds without disclosure: Some programs add “additional review” holds without warning. If payouts are routinely late beyond stated terms, leave.

    Threshold + long terms: A $100 minimum payout on net-60 terms means slow earners might wait six months for their first check. That’s fine for side income, but not if affiliate revenue pays your hosting bill.

    Conversely, if you’re choosing between two similar programs, payout speed can be the tiebreaker. A 10% commission paid net-30 beats 12% paid net-90 if you need cash flow predictability.

    Want to compare payout structures across platforms before you commit? Subscribe to One Two Three Send—we track terms, thresholds, and timing for the tools online operators actually use.

    The affiliate dashboard is not your bank account. Treat it like accounts receivable: earned, but not yet liquid. Build your budget around payment dates, not conversion dates, and you’ll never be surprised when the money’s late.

  • Monetisation dashboard refresh intervals: how often revenue updates

    You refresh your Stripe dashboard at 9am and see $247 in new revenue. You check again at 9:15am and the number hasn’t moved—but you know three customers just checked out because you got the order confirmation emails. So where’s the money?

    Revenue dashboards don’t update in real time, and each platform operates on a different delay. If you’re tracking daily revenue, reconciling payouts, or just trying to understand what’s actually happening with your business, knowing these intervals matters.

    Payment processor dashboard delays

    Stripe’s main dashboard updates every few minutes for successful charges, but refunds, disputes, and failed payment retries can lag by 15–30 minutes. The timeline view shows transactions almost immediately, but the balance graph—the one most operators check first—refreshes every 10 minutes and caches aggressively.

    PayPal’s dashboard has a reputation for slower updates. Standard transactions appear within 5–10 minutes, but subscription renewals and recurring payments sometimes take 30+ minutes to surface in the main balance view. The “Recent Activity” feed is faster, but it doesn’t always match the top-line numbers until the hourly rollup runs.

    Gumroad updates sales in near-real-time on the main dashboard, but the earnings graph—the one that shows net after fees—recalculates every hour. If you’re tracking margin, don’t trust the first number you see after a big launch.

    Membership and subscription platforms

    Platforms that sit on top of payment processors inherit their delays, then add their own.

    Memberful processes payments through Stripe, so completed charges appear almost immediately in Stripe—but Memberful’s own analytics dashboard updates every 15 minutes. The member count and MRR charts refresh overnight, so if you’re watching churn or upgrade velocity intraday, you’re looking at stale data.

    Patreon’s earnings dashboard updates twice daily: once around 8am Pacific and again around 8pm. If a patron pledges at 9am, you won’t see it reflected in your dashboard total until evening. The notification feed is real-time, but the dollar figure at the top isn’t.

    Substack shows new paid subscriptions within a few minutes, but the subscriber breakdown by tier—and the projected annual revenue number—updates every few hours. If you’re making pricing decisions based on tier distribution, pull the CSV export instead; the raw data is always current.

    Ad networks and affiliate dashboards

    Ad network dashboards are the slowest of all, because they’re waiting on third-party reporting.

    Beehiiv‘s ad network dashboard updates earnings once daily, around 6am Eastern. If you ran a sponsored placement yesterday, you won’t see attributed revenue until the next morning—and final numbers won’t settle for 48–72 hours as the network reconciles click-through conversions.

    Google AdSense updates estimated earnings every few hours, but the numbers aren’t final until the next day. The real-time reporting view shows impressions and clicks with a 10-minute lag, but the revenue estimate attached to them recalculates on a slower cycle. If you’re troubleshooting a sudden RPM drop, wait until tomorrow before panicking.

    Affiliate dashboards vary wildly by network. Amazon Associates updates every 2–3 hours, but conversions can take 24 hours to appear if the customer clicked late at night. Impact and ShareASale update conversions within the hour, but commission amounts don’t finalize until the advertiser approves the sale—sometimes days later.

    What to do about it

    First, stop refreshing. Pick one time each day to check revenue—preferably after your slowest platform has updated. If Patreon only refreshes twice daily, checking Stripe every ten minutes just creates anxiety and bad decisions.

    Second, reconcile weekly, not daily. Payment processor dashboards show gross revenue; your bank account shows net after fees, refunds, and holds. The two will never match on the same day, and trying to force them into alignment wastes time.

    Third, use webhook notifications for anything time-sensitive. If you need to know the instant a high-value customer subscribes, set up a Slack or email alert via your payment processor’s webhook system. Don’t rely on dashboard-refresh habits for operational awareness.

    Finally, export raw data when you need precision. Every monetisation platform offers CSV downloads with transaction timestamps and final amounts. If you’re building a financial model or reconciling taxes, the dashboard is a preview—the export is the source of truth.

    Want more breakdowns of how online-business tools actually work? Subscribe to One Two Three Send for weekly deep-dives into the features, delays, and design decisions that shape how you operate.

    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 processor webhook retry logic: how long they wait before giving up

    Payment processor webhook retry logic: how long they wait before giving up

    Payment processor webhook retry logic: how long they wait before giving up

    When your server misses a payment webhook—because your hosting provider had a blip, your endpoint timed out, or you deployed code at the wrong moment—you’re relying on the processor’s retry logic to deliver it again. But each platform handles retries differently, and the windows are shorter than most operators assume.

    Miss the retry window entirely, and you’ll never know that subscription was canceled, that payment failed, or that refund was issued. Here’s what actually happens behind the scenes.

    Stripe: exponential backoff over three days

    Stripe retries failed webhooks with exponential backoff. The first retry happens within minutes. Subsequent attempts spread out over roughly three days, with the final attempt landing around 72 hours after the initial event.

    If your endpoint returns anything other than a 2xx status code—or times out after 30 seconds—Stripe marks it as failed and queues a retry. The dashboard shows each attempt, including response codes and timing.

    The three-day window sounds generous, but if your server is down for a long weekend or you’re troubleshooting a bug that takes four days to identify, you’ve lost the event. Stripe doesn’t retry indefinitely.

    Non-obvious detail: Stripe disables your webhook endpoint automatically after multiple consecutive failures across different event types. You’ll get an email, but if you’re not monitoring closely, subscription updates can go silent for days before you notice.

    Paddle: 72-hour retry, then manual replay required

    Paddle’s retry behavior mirrors Stripe’s three-day window but with a stricter cutoff. After 72 hours, failed webhooks stop retrying. To recover them, you need to manually request a replay through the dashboard or API.

    The replay feature is helpful if you know what you’re looking for—filter by event type and date range, then trigger a resend. But it requires you to notice the gap first. If a handful of subscription.updated events went missing during a deploy and you don’t audit logs regularly, you might not realize users were downgraded or upgraded until they complain.

    Paddle also enforces the same 30-second timeout as Stripe. If your webhook handler queries a slow database or chains multiple API calls, you’ll hit that ceiling faster than expected.

    Lemon Squeezy: five retries over 24 hours, then it’s gone

    Lemon Squeezy retries webhooks five times over approximately 24 hours. The schedule isn’t publicly documented down to the minute, but the final attempt lands within a day of the original event.

    This tighter window means less room for error. If you deploy a breaking change Friday afternoon and don’t catch it until Monday, you’ve missed every webhook that fired over the weekend. Unlike Stripe and Paddle, Lemon Squeezy doesn’t surface retry history in the dashboard with the same granularity—you’ll see that an event was sent, but forensic details are limited.

    The shorter retry window makes Lemon Squeezy less forgiving for solo operators who don’t monitor uptime 24/7. It’s workable if your stack is stable, but the margin is thin.

    What to do when retries aren’t enough

    Webhook retries are a safety net, not a guarantee. If you’re running a subscription business, you need a second layer: periodic reconciliation.

    Once a day—or once a week, depending on volume—query your payment processor’s API for subscription and payment statuses, then compare them against your database. Look for mismatches: active subscriptions in Stripe that your app thinks are canceled, payments marked pending that actually settled, refunds that never updated your records.

    This reconciliation step catches what retries miss. It’s not real-time, but it prevents the worst-case scenario where a customer’s access is wrong for weeks because a single webhook disappeared.

    Set up logging that writes every incoming webhook to a separate table before processing it. If your handler crashes mid-execution, you’ll still have the raw payload to replay manually. Most processors let you trigger test webhooks from the dashboard—use those to validate your endpoint handles retries and errors correctly before real money flows through.

    Want more architecture breakdowns like this? Subscribe to One Two Three Send—every article is written for operators running the business, not just the content.

    Set up alerts, not just logs

    Failed webhooks usually show up in your payment processor’s dashboard, but dashboards require you to look. Set up an alert—Slack notification, email, SMS, whatever you’ll actually see—when your endpoint returns a non-2xx status or when the processor reports multiple failures in a row.

    If you’re on a platform like Stripe, enable the option to email you when an endpoint is disabled. That email might be the only signal you get before revenue events start disappearing.

    Webhook retries buy you time to fix an outage, but they don’t extend indefinitely. Understand your processor’s retry schedule, build reconciliation into your workflow, and monitor failures in real time. The three-day window Stripe offers feels comfortable until you realize you didn’t check the dashboard for four.

  • Sponsored post disclosure templates: what regulators actually require

    Sponsored post disclosure templates: what regulators actually require

    Sponsored post disclosure templates: what regulators actually require
    Photo by Team Nocoloco on Unsplash

    Most solo operators running sponsored content use boilerplate disclosure language they copied from someone else. That works until a brand’s legal team pushes back, a platform flags your post, or you realize the rules vary by country, platform, and even content format.

    The disclosure frameworks aren’t consistent. What satisfies the U.S. Federal Trade Commission doesn’t necessarily meet UK Advertising Standards Authority requirements. Instagram’s branded content tool has different mechanics than a newsletter sponsorship disclosure. And affiliate links sit in a separate category from paid placements, even though many operators lump them together.

    Here’s what the major frameworks actually require, and how to write disclosures that cover you without sounding like a legal disclaimer.

    FTC requirements: clear, conspicuous, and early

    The FTC’s core rule is simple: disclose material connections before someone engages with your recommendation. That means the disclosure has to appear before the call-to-action, not buried at the bottom of a 2,000-word post.

    “Clear and conspicuous” has specific meaning. The disclosure needs to be:

    • In plain language—”This post is sponsored by [Brand]” works; “In partnership with” is ambiguous
    • Unavoidable—not hidden behind a “read more” fold or a link labeled “legal”
    • In the same format as the content—if your post is a video, the disclosure needs to be spoken and on-screen, not just in the description

    For newsletters, that usually means a line at the top: “Today’s issue is sponsored by [Brand].” Some operators put it in the subject line using brackets or prefixes; that satisfies the “before engagement” rule because the subject is visible before the open.

    Affiliate links need disclosure too, but the language can be lighter: “This post contains affiliate links. I earn a commission if you purchase.” The FTC cares that readers know you have a financial incentive—not the exact commission structure.

    ASA and UK-specific rules

    The UK’s Advertising Standards Authority is stricter about labeling. The word “ad” needs to appear prominently. “Sponsored,” “partner,” and “collab” don’t meet the standard on their own.

    If you’re running sponsored content and have UK readers, use “Ad:” or “Advertisement:” as a prefix in the subject line or headline. The ASA has flagged Instagram posts where “#ad” appeared several hashtags deep—the rule is that it needs to be upfront, not mixed into a list.

    For newsletters with international audiences, the safest approach is to satisfy the stricter standard. Leading with “Ad:” in the subject and “This issue is an advertisement for [Brand]” in the body covers both FTC and ASA requirements.

    Platform-specific branded content tools

    Instagram, Facebook, YouTube, and TikTok all have built-in branded content toggles. When you enable them, the platform adds its own “Paid partnership with [Brand]” label.

    Using the platform tool doesn’t eliminate your obligation to disclose in your own words—it’s additive. The FTC and ASA expect you to make the disclosure, not rely on a platform label that could change or disappear in a layout update.

    The platform tools do serve a separate purpose: they let brands access performance data through Meta’s Brand Collabs Manager or YouTube’s brand analytics. If a sponsor requires that data access, you need to use the platform toggle. Just don’t treat it as your only disclosure.

    Writing disclosures that don’t kill your voice

    Legal-sounding language makes readers skip the content entirely. You can stay compliant without sounding like a Terms of Service page.

    Instead of: “The following content has been underwritten by a third-party commercial entity in exchange for monetary or other consideration.”

    Use: “This issue is sponsored by [Brand]. They’re paying me to tell you about [Product].”

    The second version is clearer, more honest, and meets every regulatory standard. Readers appreciate directness. The sponsors who push back on plain-language disclosures are usually the ones trying to obscure the commercial relationship—which is exactly what regulators are trying to prevent.

    For affiliate links, the same principle applies. “I earn a commission if you buy” is clearer than “This post may contain affiliate links to products and services, for which the author may receive compensation.”

    Where operators actually get flagged

    Most enforcement isn’t about missing disclosures—it’s about disclosures that appear too late or use ambiguous language.

    Common mistakes:

    • Placing “Sponsored by [Brand]” only in the footer of a newsletter
    • Using “Thanks to [Brand] for supporting this post” without clarifying it’s a paid relationship
    • Disclosing on your website’s generic “Disclaimers” page instead of in the content itself
    • Using platform hashtags like #partner or #collab, which don’t explicitly state a paid relationship

    If you’re running a newsletter with recurring sponsors, disclosing once in your welcome email or about page doesn’t cover individual sponsored issues. Each piece of sponsored content needs its own disclosure.

    One template that works everywhere

    If you want a single disclosure format that satisfies FTC, ASA, and platform norms across newsletters, blog posts, and social media:

    Subject line or headline: “Ad: [Your usual title]”

    Opening line: “This [post/issue/video] is a paid advertisement for [Brand]. They compensated me to [describe what you’re doing: reviewing, recommending, featuring].”

    That structure is unambiguous, front-loaded, and uses plain language. It works for newsletters sent via Beehiiv, MailerLite, or Postmark. It works for blog posts. It works for Instagram captions and YouTube descriptions.

    You can adjust tone—”[Brand] paid me to write this” vs. “This issue is sponsored by [Brand]”—but the core elements stay the same: who paid, what the relationship is, and disclosure before the pitch.

    One Two Three Send covers the operational side of running content businesses—including the legal and platform mechanics most guides skip. Subscribe to get one focused piece like this each 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.

  • Affiliate link management: when spreadsheets cost you money

    Affiliate link management: when spreadsheets cost you money

    Affiliate link management: when spreadsheets cost you money
    Photo by Gorilla ROI Data Connector on Unsplash

    If you run affiliate links across your content—newsletter, blog, social—you probably started with a spreadsheet. Product name, affiliate URL, commission rate, maybe a notes column. It works until it doesn’t.

    The breaking point isn’t volume. It’s versioning. Affiliate programs change their URLs, update terms, expire cookies faster, or shut down entirely. Your spreadsheet doesn’t tell you when a link dies. You find out three months later when a reader replies asking why your checkout link 404s.

    What breaks first

    Spreadsheets fail at three things: link rot detection, historical performance, and propagation speed.

    Link rot is silent. An affiliate program migrates to a new domain, updates their tracking parameter structure, or sunsets a product SKU. Your old link still resolves—it just doesn’t credit you. Unless you’re manually testing every link monthly, you won’t know.

    Historical performance matters when you’re deciding what to promote next quarter. A spreadsheet can log clicks if you’re using a link shortener with analytics, but matching clicks to actual conversions requires stitching together your shortener dashboard, the affiliate network backend, and your own notes. Most operators give up and optimize for vanity metrics instead.

    Propagation speed is the operational bottleneck. You update a link in your spreadsheet, then you have to manually find and replace it across every past article, email archive page, and pinned social post. If the link appears in 40 places, you’re burning an hour. If you skip the older posts, you’re leaving dead links live.

    When a link manager pays for itself

    Dedicated affiliate link management tools—Pretty Links, ThirstyAffiliates, Lasso—charge $10 to $30/month. The ROI threshold is straightforward: if one broken link costs you more than one month’s subscription in lost commissions, the tool pays for itself.

    For a solo operator earning $500/month in affiliate revenue, a single high-value conversion is worth $50 to $200 depending on the program. One missed sale covers six months of tooling.

    The feature that matters most isn’t the link cloaking or the pretty dashboard. It’s automatic redirect updating. You edit the destination URL once in the tool’s backend; every instance of that short link across your entire site updates instantly. No find-and-replace. No archaeology through old posts.

    Link health monitoring is the second-order benefit. Tools like Lasso ping your affiliate URLs weekly and flag 404s or redirects that don’t resolve to the expected domain. You get an alert, fix it, move on. The alternative is discovering the problem when a reader emails you or when you notice commission drops in your next payout statement.

    The spreadsheet-plus-shortener hybrid

    If you’re not ready to pay monthly, the middle path is a spreadsheet plus a custom domain short link service. Rebrandly’s free tier gives you 500 branded links and click tracking. You store the short link in your spreadsheet, paste that short link everywhere, and update the destination URL in Rebrandly when the affiliate program changes.

    This works if you have fewer than 50 active affiliate relationships and you’re disciplined about logging every new link. It breaks when you forget to add a link to the sheet, or when you need to bulk-edit links by category (“update all Amazon links to the new Associate ID”).

    The hidden cost is context switching. Every time you create a new affiliate link, you’re opening three tabs: the affiliate dashboard to generate the URL, Rebrandly to shorten it, and your spreadsheet to log it. That’s 90 seconds per link. If you’re adding 10 links a week, that’s 15 minutes weekly—13 hours a year—on administrative overhead.

    What to do Monday

    Audit your last 90 days of affiliate links. Open your spreadsheet, click every URL, and verify it resolves to the correct product page with your tracking parameter intact. If more than 10% are broken or redirect incorrectly, you have a link rot problem worth solving.

    If you’re earning less than $200/month in affiliate revenue, stay with the spreadsheet but set a calendar reminder to re-check links quarterly. If you’re above $500/month or managing more than 30 active programs, trial a link manager for one month and measure time saved on link updates.

    The goal isn’t perfect tracking. It’s reducing the lag between when a link breaks and when you notice. Every day a broken link stays live is a day you’re sending traffic you can’t monetize.

    One Two Three Send covers the tools and tactics solo operators actually use to run content businesses. Subscribe to get one focused article daily—no filler, no fluff.

  • Stripe tax calculation sync delays: when checkout totals don’t match

    Stripe tax calculation sync delays: when checkout totals don’t match

    Stripe tax calculation sync delays: when checkout totals don't match
    Photo by FIN on Unsplash

    If you’re running subscriptions or one-off product sales through Stripe and you’ve turned on automated tax calculation, you’ve probably assumed the displayed total at checkout matches what Stripe will actually charge. Most of the time it does. But there’s a timing issue that breaks this assumption, and it shows up more often than Stripe’s documentation admits.

    The problem: Stripe’s Tax Calculation API is called asynchronously when a customer reaches checkout. If your checkout page renders faster than the tax calculation response returns—common on fast hosting or CDN-cached pages—the displayed price can lag behind by a second or two. When that happens, the customer sees one total, then it flickers to another, or worse, the charge goes through before the tax rate applies.

    How Stripe’s tax calculation actually fires

    Stripe’s tax engine doesn’t pre-calculate tax for every possible customer location. Instead, it waits until checkout to call POST /v1/tax/calculations with the customer’s IP-derived location, the line items, and your tax settings. The response includes the tax amount, which your frontend then adds to the subtotal.

    This works fine when checkout is slow—legacy WordPress installs, heavy JavaScript bundles, or multi-step forms give the API enough time to respond before the total renders. But if your checkout loads in under 800ms and you’re calling the API client-side, you’ll see the mismatch.

    Stripe recommends server-side calculation for this reason, but many solo operators use client-side Stripe.js integrations or no-code tools like MemberStack, Outseta, or Carrd payment embeds, which default to client-side tax calls.

    When the lag causes real problems

    The flicker alone erodes trust. A customer sees $49, then $53.67 a moment later. If they screenshot the first number or bail before the update, you’ve lost the sale or opened a dispute.

    Worse: if your payment button becomes active before the tax calculation completes, Stripe will process the charge without tax. You’re liable for the shortfall. This happens most often when operators use custom checkout forms that don’t wait for Stripe’s PaymentIntent status to confirm tax has been applied.

    Third issue: webhook events. If you’re listening for checkout.session.completed to trigger fulfillment, and the tax calculation hasn’t finished, your webhook payload might show an incomplete amount_total. Fulfillment scripts that check totals against expected pricing will fail or flag fraud.

    How to fix it

    Move tax calculation server-side if you control your checkout stack. Create the PaymentIntent on your backend, call /v1/tax/calculations there, and return the final total to the frontend. This ensures tax is baked in before the customer sees any number.

    If you’re locked into a client-side tool, add a loading state to your checkout button. Disable it until Stripe confirms automatic_tax.status returns complete. Most no-code platforms let you add a custom attribute or visibility rule tied to a calculation flag.

    For webhook reliability, always validate amount_total in your handler. If it’s lower than expected and automatic_tax.status is requires_location or failed, log it and retry the calculation manually via the API before fulfilling.

    One non-obvious fix: cache customer location in a session cookie after their first page load, then pre-calculate tax before they hit checkout. This won’t work for first-time visitors, but it smooths repeat traffic. You can use Stripe’s customer_details.address field to store validated location data from a prior purchase.

    Pricing and support notes

    Stripe Tax costs 0.5% of the transaction amount plus any tax collected, with a $10/month minimum once you process your first taxable sale. The API itself has no rate limit for tax calculations, but each call adds ~200–400ms latency depending on region.

    If you’re processing under 100 transactions a month, the $10 minimum might not justify automation—manual tax rates via Stripe’s dashboard are free and load instantly. For higher volume or multi-region sales, automated tax is worth it, but only if you handle the sync timing correctly.

    Stripe’s support documentation assumes you’re using Checkout or Payment Links, both of which handle tax calculation timing internally. If you’ve built a custom integration, you’re on your own to catch these edge cases.

    Have a checkout or payment flow question? Reply to this email—operator questions shape what we cover next.