Author: onetwothreeadmin

  • Newsletter referral programs reward shares, not subscribers—here’s why

    Newsletter referral programs reward shares, not subscribers—here’s why

    Newsletter referral programs reward shares, not subscribers—here's why
    Photo by Team Nocoloco on Unsplash

    Newsletter referral programs look simple: existing subscriber shares your newsletter, someone new signs up through their link, original subscriber gets credit. But the mechanics under the hood reveal a design choice that changes how you should think about rewards, milestones, and fraud prevention.

    Most platforms—including Beehiiv, Sparkloop, and UpViral—credit the referrer at the moment of the share action or initial click, not when the new subscriber confirms their email or becomes active. That’s not an oversight. It’s a deliberate trade-off between attribution accuracy and user experience.

    Why platforms credit the share, not the conversion

    If a platform waits to credit the referrer until the new subscriber confirms their email, you introduce a 24-to-48-hour delay before the referrer sees any progress toward their reward. That delay kills momentum. People share once, see no movement on their dashboard, and assume the system isn’t working.

    Crediting the share immediately gives the referrer instant feedback. They see their count tick up within seconds. That dopamine hit encourages them to share again.

    The downside: you’re counting referrals that never convert. If someone shares your newsletter and ten people click but only three confirm their email addresses, the referrer gets credit for ten. Your dashboard shows ten referred subscribers, but your email list only grows by three.

    Beehiiv‘s referral system, for example, increments the referrer’s count when someone lands on the signup page via their unique link and submits an email address—before double opt-in confirmation. If that person never clicks the confirmation email, Beehiiv doesn’t automatically deduct the referral credit. You’re left with inflated referral counts and a smaller list than your referral leaderboard suggests.

    What this means for milestone design

    If you’re running a referral program with tiered rewards—get five referrals, unlock a PDF; get 25, get a one-on-one call—you need to account for the gap between credited referrals and confirmed subscribers.

    A conservative multiplier: assume 60-70% of credited referrals will actually confirm and stay active. If you want someone to genuinely deliver 25 new subscribers to your list, set the milestone at 35-40 credited referrals. That’s not padding—it’s compensating for the way the system counts.

    Some operators do the opposite. They set lower thresholds and accept that referral credits overstate real growth. The logic: referral programs are about engagement and word-of-mouth momentum, not precise list-building math. If someone shares your work enough to rack up 40 credited referrals, they’ve done the work even if only 25 people actually joined.

    Both approaches work. The mistake is setting a milestone at, say, ten referrals, expecting ten confirmed subscribers, and then feeling cheated when your list only grows by six.

    Fraud and gaming the system

    Because platforms credit the share action, referral programs are vulnerable to bulk fake signups. Someone creates a dozen disposable email addresses, uses their own referral link, submits all twelve emails, and immediately gets credit for twelve referrals—even though none of those addresses will ever open an email.

    Most platforms have basic fraud detection: they flag referrals from the same IP address, block known disposable email domains, and penalize accounts that rack up referrals with zero engagement. But enforcement is reactive, not preventive. If someone wants to game your referral leaderboard, they can do it for at least a few days before the system catches up.

    The operator-side fix: build engagement thresholds into your rewards. Don’t just offer a reward at ten referrals—require that at least seven of those ten people open an email in the first 30 days. Sparkloop and some custom-built systems let you set that kind of conditional unlock. Beehiiv doesn’t natively support engagement-based milestones, so you’d need to manually audit your leaderboard before delivering high-value rewards like coaching calls or physical products.

    When conversion-based crediting makes sense

    A few platforms—mostly custom-built referral systems using tools like Rewardful or ReferralCandy—let you choose when to credit the referrer. You can configure the system to wait until the new subscriber confirms their email, opens their first email, or even makes a purchase (if you’re running a paid newsletter).

    That approach eliminates inflated counts, but it introduces the delay problem. If your audience is sophisticated enough to understand that referral credit takes 24-48 hours to appear, it works. If your audience skews toward casual readers who expect instant feedback, the delay will depress sharing behavior.

    One middle path: credit the share immediately, but display two numbers on the referrer’s dashboard—”total shares” and “confirmed subscribers.” Transparency costs you nothing, and it sets expectations. If someone sees they’ve sent 15 people to your signup page but only 9 confirmed, they understand the gap without feeling penalized.

    Most newsletter platforms don’t offer that dual display by default. You’d need to build it yourself or accept that your referral dashboard is a directional indicator, not a precise accounting tool.

    What to do now

    If you’re running a referral program, audit your current milestone structure. Check the gap between credited referrals and actual confirmed subscribers over the last 30 days. If the gap is more than 20%, adjust your milestones upward or add engagement requirements before delivering rewards.

    If you’re designing a new referral program, decide whether you’re optimizing for momentum (credit the share) or accuracy (credit the conversion). Most solo operators should optimize for momentum. Referral programs live or die on early enthusiasm, and nothing kills enthusiasm faster than a dashboard that doesn’t move.

    Got a referral program question? Reply to this email—I read every response.

    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.

  • Zapier filters fail silently when field types mismatch

    Zapier filters fail silently when field types mismatch

    Zapier filters fail silently when field types mismatch
    Photo by Annie Spratt on Unsplash

    Zapier filters are supposed to stop workflows when conditions aren’t met. But when the data type coming from your trigger doesn’t match the filter’s expected type, the filter step often passes data through instead of stopping it—and you won’t see a warning.

    This happens most often when API responses return numbers as strings, or when form fields send boolean values as text. Your filter logic looks correct in the Zapier editor, but the workflow keeps running when it shouldn’t.

    Why type mismatches break filter logic

    Zapier’s filter conditions use different comparison rules depending on the data type. When you set a filter to check if a number is “greater than 100,” Zapier expects an integer or float. If the incoming field is a string—even if it contains the characters “150”—the comparison often evaluates as true regardless of the actual value.

    The most common culprits:

    • Webhook payloads that wrap numbers in quotes
    • Airtable formula fields returning text instead of numbers
    • Google Sheets cells formatted as text
    • Form builders that send checkbox values as “true” or “false” strings instead of booleans

    Zapier doesn’t flag these mismatches in the test step. The filter appears to work, because the test data happens to pass. But in production, edge cases slip through.

    How to test for type problems

    The fastest way to confirm a type issue: add a temporary Formatter step immediately before your filter. Use Numbers > Format Number or Text > Default Value to force the field into the type you expect. If your filter suddenly starts behaving correctly, you’ve found the mismatch.

    You can also check the raw data in Zapier’s task history. Open a completed task, expand the trigger step, and look at the field in question. If you see quote marks around a number—"42" instead of 42—it’s a string. Zapier won’t coerce it during comparison.

    For boolean checks, the problem is worse. A field containing the string “false” evaluates as true in existence checks, because non-empty strings are truthy. Your filter checking “if subscription_active exists” will pass even when the value is explicitly “false.”

    Three fixes that actually work

    Option one: Add a Formatter step before every filter that touches numbers or booleans. Use Numbers > Spreadsheet-Style Formula with a formula like VALUE(input) to convert strings to numbers, or Text > Length combined with a secondary filter to check boolean strings explicitly.

    Option two: Fix the data at the source. If you control the webhook or API, return proper JSON types. If you’re using Airtable, switch formula fields to rollup or lookup fields that preserve number types. In Google Sheets, use TO_PURE_NUMBER() in a hidden helper column.

    Option three: Use Zapier’s “Text Contains” or “Text Exactly Matches” conditions instead of numeric comparisons—but only if you’re comparing against a small set of known values. This works for status fields (“active,” “paused,” “cancelled”) but breaks down for ranges.

    The Formatter approach costs an extra task per workflow run. At $0.01–0.03 per task depending on your plan, that adds up—but it’s cheaper than the support emails from users who slipped through a broken filter.

    When to rewrite the workflow entirely

    If you’re chaining three or more filter steps to work around type issues, you’re better off moving the logic upstream. Platforms like Make (formerly Integromat) handle type coercion more gracefully, and their routers let you branch on complex conditions without stacking fragile filters.

    For high-volume workflows—anything over 10,000 tasks per month—the cumulative cost of workaround Formatter steps often exceeds the price difference between Zapier and a code-optional alternative. Make’s operations are roughly 30% cheaper per unit, and n8n self-hosted is effectively free at scale if you’re comfortable with Docker.

    Zapier’s filter UX is clean and approachable, but it’s built for the 80% case. When your data sources don’t play along, you’re either adding duct-tape steps or migrating.

    Have a workflow automation question? Reply to this email—we’re building a library of operator-tested fixes for the automation gaps platforms don’t document.

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

    Subscription churn dashboards: what they hide about your real retention

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

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

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

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

    Voluntary vs. involuntary churn

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

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

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

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

    Paused subscriptions that don’t resume

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

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

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

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

    Downgrades to free tiers

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

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

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

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

    Cohort decay vs. headline churn

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

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

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

    What to do with this

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

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

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

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

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

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

  • AI transcription tools: when per-minute pricing beats subscription

    AI transcription tools: when per-minute pricing beats subscription

    AI transcription tools: when per-minute pricing beats subscription
    Photo by Sasun Bughdaryan on Unsplash

    Most solo operators pick a transcription tool the same way they pick a newsletter platform: they sign up for a monthly subscription and hope they use it enough to justify the cost. But transcription pricing works differently—and if you’re not processing hours of audio every week, you’re probably overpaying.

    The breakeven point between pay-per-minute and subscription models sits around 300 minutes per month for most tools. Below that threshold, usage-based pricing almost always costs less. Above it, subscriptions start to make sense. Here’s how to figure out which model fits your workflow.

    How per-minute pricing actually works

    Services like AssemblyAI, Deepgram, and Gladia charge between $0.00025 and $0.0015 per second of audio—roughly $0.015 to $0.09 per minute. You upload a file, get charged for the exact runtime, and walk away. No monthly commitment, no unused quota rolling over.

    If you’re transcribing two podcast episodes a month at 45 minutes each, that’s 90 minutes total. At $0.05 per minute (a typical API rate), you’re spending $4.50. Compare that to Descript’s $12/month starter plan or Otter.ai’s $16.99/month Pro tier, and the math is straightforward.

    The catch: per-minute tools are almost always API-first. You’re not logging into a dashboard and dragging files into a browser window. You’re either sending HTTP requests directly or using a lightweight wrapper tool. That’s fine if you’re comfortable with Postman or a basic Python script, but it’s friction if you just want to upload and download.

    When subscriptions stop being a waste

    Monthly plans make sense when you’re consistently crossing 300–400 minutes. Descript’s $24/month Creator plan includes 10 hours of transcription (600 minutes). If you’re using 500+ minutes, you’re paying $0.048 per minute—cheaper than most pay-as-you-go rates.

    But subscription value isn’t just about volume. You’re also paying for the interface, collaboration features, and integrated editing. Descript lets you edit transcripts like a text document and exports video with cuts applied. Otter.ai syncs with Zoom and auto-titles meeting transcripts. Those features have value if you use them. If you don’t, you’re subsidising someone else’s workflow.

    The real waste happens when you pay for a subscription tier you don’t fully use. Otter.ai’s Business plan is $30/user/month and includes 6,000 minutes per user per month. Unless you’re transcribing 100 hours of audio, you’re paying for capacity you’ll never touch.

    Hybrid setups that actually work

    Most operators don’t need to pick one model forever. If you’re running a podcast, you might process 200 minutes a month during regular seasons and 800 minutes during a launch sprint. Paying per-minute during off-months and subscribing for two months during launches saves more than either model alone.

    Another option: use a pay-per-minute API for bulk transcription and a free-tier tool for ad hoc work. Otter.ai’s free plan includes 300 minutes per month. If you’re transcribing client calls or quick voice memos, that’s enough to avoid paying anything. Save the API budget for long-form content.

    One non-obvious trick: batch your transcription requests if you’re using a per-minute service. Most APIs charge the same rate whether you send one 60-minute file or twelve 5-minute files, but some tools (like Deepgram) offer volume discounts that kick in at 100+ hours per month. If you’re close to that threshold, consolidating requests in a single billing cycle can drop your per-minute rate by 20–30%.

    What to check before you switch

    Pricing models aren’t the only variable. Accuracy, turnaround time, and language support all matter—and they vary widely even among tools charging similar rates.

    AssemblyAI’s word error rate is around 5% for clean English audio, but climbs to 12–15% with heavy accents or background noise. Deepgram handles noisy audio better but costs slightly more. If you’re transcribing Zoom calls with multiple speakers and mediocre microphones, paying an extra $0.02 per minute for better accuracy saves you more time than the cost difference.

    Turnaround time also fluctuates. Most API-based tools process audio at 10–15x real-time speed (a 30-minute file takes 2–3 minutes). Subscription tools with built-in editors can be slower, especially during peak hours. If you need transcripts immediately after recording, per-minute APIs usually win.

    Finally, check how each tool handles speaker identification and formatting. Some charge extra for diarisation (labelling who said what). Others include it by default but cap the number of speakers. If you’re transcribing panel discussions or group calls, that feature isn’t optional—and the upcharge can flip the breakeven math.

    If you’re transcribing under 300 minutes a month, start with a pay-per-minute API and a free-tier tool for overflow. Track your usage for two months. If you’re consistently crossing 400 minutes, switch to a subscription. If you’re hovering around 200, stay on usage-based pricing and pocket the difference.

    Have a transcription workflow that doesn’t fit these models? Reply and let us know—we’ll cover edge cases in a future piece.

  • Sponsored content disclosure placement: where platforms require it

    Sponsored content disclosure placement: where platforms require it

    Sponsored content disclosure placement: where platforms require it
    Photo by Szabo Viktor on Unsplash

    If you run sponsored posts, you already know you need to disclose the relationship. What most operators don’t realize is that each platform has its own technical requirements for where that disclosure appears—and some of them override what you write.

    Instagram and Facebook: the built-in toggle wins

    Meta’s platforms require you to use the “Paid partnership with” label when posting branded content through a business or creator account. You enable it in the advanced settings before publishing.

    If you add #ad or #sponsored in the caption, that’s fine—but it doesn’t replace the toggle. Meta’s terms treat the built-in label as the compliant disclosure. The hashtag is supplementary.

    The label appears at the top of the post, above the image and caption. It’s styled in Meta’s UI and can’t be customized. If you’re working with a brand that wants specific language, send them Meta’s official branded content guidelines—they’re locked into this format.

    YouTube: the first five seconds, or the description box

    YouTube’s policy requires disclosure “in the video itself” or “in the description.” If you choose the description route, it needs to appear above the fold—before the “Show more” link.

    For video content, the safest approach is a verbal mention in the first five seconds, paired with on-screen text that stays visible for at least three seconds. The FTC has cited creators for burying disclosures at the end of a video or in collapsed description text.

    YouTube also has a “Includes paid promotion” checkbox in the upload flow. Checking it adds a small disclaimer to the lower-left corner of the video player. That checkbox is required for certain ad categories (political, prescription drugs), but for standard sponsorships, it’s considered supplementary—not a replacement for in-video or description disclosure.

    TikTok: the branded content toggle is mandatory

    TikTok requires the “Branded Content” toggle for any post that promotes a third-party product or service. You’ll find it in the post settings under “Advanced settings” → “Content disclosure.”

    Enabling it adds a “Paid partnership” label to the top of the video. Like Meta, TikTok treats this as the primary disclosure mechanism. Adding #ad in the caption is recommended but not sufficient on its own.

    One catch: TikTok’s branded content toggle is only available to accounts in the Creator Marketplace or those that meet specific eligibility thresholds (10,000+ followers and 100,000+ video views in the last 30 days as of mid-2026). If you don’t have access yet, you’re stuck with caption-based disclosure—and the platform may limit your reach or remove the post if it’s flagged as undisclosed advertising.

    LinkedIn: text-based disclosure still rules

    LinkedIn doesn’t have a built-in sponsored-content label for individual posts (its “Sponsored Content” product is for paid ads run through Campaign Manager, not organic posts).

    For organic posts that include a paid partnership, you need to disclose it in the text itself. The FTC’s guidance applies: the disclosure should appear before the call to action and be clear without requiring users to click “see more.”

    Common phrasing: “Sponsored by [Brand],” “Paid partnership with [Brand],” or “This post is sponsored by [Brand].” Put it in the first two lines of the post. Burying it after three paragraphs or in a comment doesn’t meet the standard.

    What the FTC actually enforces

    Platform-specific tools help, but the FTC’s core rule is simple: disclosures must be “clear and conspicuous.” That means:

    • Visible without scrolling, clicking, or hovering
    • In plain language—no ambiguous hashtags like #partner or #collab
    • Close to the claim being made, not buried at the end

    In practice, the FTC has gone after creators and brands for disclosures that appeared only in collapsed text, in light-colored fonts against light backgrounds, or in strings of hashtags where #ad was the eighth tag.

    If a platform’s built-in tool exists and you don’t use it, that’s a red flag during an audit. If you use it and add text disclosure, you’re in the clear.

    One disclosure format that works everywhere

    If you’re cross-posting the same sponsored content to multiple platforms, lead with a text-based disclosure in the first sentence and enable any platform-specific toggles where available.

    Example: “Sponsored by [Brand]. Here’s why I’ve been using [product]…”

    That satisfies LinkedIn and Twitter (which has no built-in tool). Then layer on Meta’s partnership toggle, TikTok’s branded content flag, and YouTube’s in-video mention. It’s redundant, but redundancy is the point—regulators and platforms both want the relationship to be unmissable.

    Got a question about disclosure rules for a specific platform or sponsor agreement? Reply to this email—we’ll cover it in a future Q&A.

  • WordPress plugin update rollbacks: how automatic reversions work

    WordPress plugin update rollbacks: how automatic reversions work

    WordPress plugin update rollbacks: how automatic reversions work
    Photo: Simpson, Thomas via Wikimedia Commons (Public domain)

    WordPress 6.3 shipped a feature most operators don’t know exists until it saves them: automatic plugin rollback after a fatal error. If a plugin update crashes your site, WordPress will—under specific conditions—revert to the previous version without you touching anything.

    That safety net isn’t as wide as it sounds. Understanding when it fires, what it catches, and what it misses will save you from assuming your site is protected when it isn’t.

    What triggers an automatic rollback

    WordPress monitors plugin updates for fatal PHP errors during a brief window immediately after activation. If a newly updated plugin throws a fatal error that would break your site, WordPress detects it during the next loopback request—a self-ping the system uses to verify the site is still responding.

    If that loopback fails, WordPress rolls the plugin back to its previous version and sends an email to the site admin address on file. The entire process happens within seconds to minutes, depending on how quickly the loopback request completes.

    Three conditions must be true for rollback to fire:

    • The plugin was updated through the WordPress admin dashboard or WP-CLI with the --defer-site-health flag
    • The fatal error occurs during plugin load or initialization—not later during a page request
    • The loopback request detects the failure before the request timeout (default: 10 seconds)

    If you update via SFTP, the rollback system never sees the change. If the plugin loads fine but crashes when a visitor hits a specific page, rollback won’t catch it. If your server is slow and the loopback times out before detecting the error, you’re on your own.

    What gets reversed, what doesn’t

    Rollback restores the plugin’s PHP files to the previous version. That’s it. Any database changes the new version made—schema migrations, new rows, updated option values—stay in place.

    This creates a mismatch problem. If version 2.0 of a plugin adds a database column and version 1.9 expects it not to exist, rolling back the code doesn’t undo the schema change. You’re now running old code against a new database structure.

    Most well-coded plugins handle this gracefully by checking for the existence of columns or tables before querying them. Poorly coded plugins assume the database structure matches the code version and break in new ways after rollback.

    Settings changes are similarly sticky. If the new version migrated your settings array to a new format, rollback won’t revert that migration. You’ll need to manually restore settings from a backup or reconfigure the plugin.

    When rollback fails silently

    Rollback depends on the loopback request succeeding. If your server blocks loopback requests—common on shared hosts with aggressive firewall rules or when using localhost SSL certificates—WordPress can’t verify the site is broken, so it won’t roll back.

    You can test whether loopbacks work by visiting Tools > Site Health in the WordPress admin. If the “Loopback request” test fails, automatic rollback won’t work either. Fixing it usually requires whitelisting your own domain in your firewall or adjusting WP_HTTP_BLOCK_EXTERNAL settings.

    Rollback also won’t fire if the fatal error occurs outside the plugin’s initialization phase. If a plugin loads successfully but crashes when you try to access its settings page, that’s a runtime error, not an initialization failure. WordPress considers the update successful because the site didn’t break immediately.

    Manual rollback as fallback

    Even when automatic rollback works, it’s worth knowing how to roll back manually. WordPress doesn’t keep old plugin versions on your server—it deletes them after update. To manually revert, you’ll need to download the previous version from the WordPress.org plugin repository.

    Visit wordpress.org/plugins/[plugin-slug]/advanced/ to access the developer view, which lists all previous versions. Download the version you need, delete the current plugin folder via SFTP or your host’s file manager, and upload the old version. Reactivate if necessary.

    If you’re on a managed WordPress host, check whether they offer automatic snapshots before updates. Kinsta, WP Engine, and similar hosts take filesystem snapshots before applying updates, letting you restore the entire plugin folder—and sometimes the database state—from before the update.

    For operators managing multiple sites, a staging environment is the better insurance. Test plugin updates on staging first. If they break, your production site never sees the bad code. If automatic rollback is your only safety net, you’re relying on a system that only catches a subset of failures.

    One Two Three Send covers WordPress operations, hosting, and the tools solo operators use to keep sites running. Subscribe for one operator-focused article every day.

  • SEO title tags: why Google rewrites 33% of them automatically

    SEO title tags: why Google rewrites 33% of them automatically

    SEO title tags: why Google rewrites 33% of them automatically
    Photo by Mitchell Luo on Unsplash

    You spend twenty minutes crafting the perfect title tag. You test it in the preview tool. You publish. Two days later, you check Google Search Console and discover Google’s rewritten it entirely—pulling text from your H1, your brand name, or some fragment of body copy you never intended as a title.

    This isn’t a bug. It’s how Google’s been operating since August 2021, and internal studies suggest it now rewrites roughly 33% of all title tags that appear in search results. Understanding when and why this happens gives you more control over what searchers actually see.

    When Google rewrites your title tag

    Google replaces your title tag when its algorithm decides the original doesn’t accurately describe the page content, is too long, stuffs keywords, or doesn’t match the query intent. The rewrite pulls from:

    • Your H1 heading
    • Visible text near the top of the page
    • Anchor text from internal or external links pointing to the page
    • Structured data markup, especially for products or articles

    The most common trigger is a mismatch between the title tag and the H1. If your title says “Best Email Marketing Tools” but your H1 says “9 Email Platforms We Tested in 2026,” Google often uses the H1 verbatim. The second most common trigger is length: titles over 60 characters get truncated or rewritten entirely, especially on mobile.

    Keyword stuffing still triggers rewrites. If your title is “Email Marketing Software | Email Tools | Best Email Platforms | Email Services,” Google will almost certainly replace it with something shorter pulled from your page.

    What gets rewritten most often

    Homepage titles get rewritten more than any other page type—close to 50% of the time. Google typically replaces them with the brand name, sometimes appended with a tagline or category descriptor pulled from the page. If your homepage title is “Welcome to Acme Newsletter Tools,” Google might show “Acme | Newsletter Platform for Solo Operators” if that phrase appears prominently on the page.

    Product and landing pages get rewritten when the title is too sales-heavy. “Buy the #1 Newsletter Tool Today!” becomes “Acme Newsletter Tool” in search results. Google strips superlatives, urgency language, and calls-to-action that don’t describe the page.

    Blog post titles survive more often, but only if they’re descriptive and under 60 characters. Opinion pieces, how-tos, and case studies have the highest survival rate because the title and H1 usually match and clearly describe the content.

    How to write titles that stick

    Keep your title tag and H1 identical or nearly identical. Google’s algorithm treats divergence as a signal that one of them is inaccurate. If you need a different H1 for design reasons, make sure it’s semantically similar to the title.

    Stay under 60 characters, including spaces. Google’s display limit fluctuates based on pixel width, but 60 characters is the safe zone for desktop and mobile. If your title is longer, Google will either truncate it with an ellipsis or replace it entirely.

    Front-load the topic, not the brand. “ConvertKit vs. MailerLite comparison | Acme Blog” becomes “ConvertKit vs. MailerLite comparison” in search results far more often than “Acme Blog | ConvertKit vs. MailerLite.” Put the descriptor first, brand last.

    Avoid keyword repetition. One mention per keyword is enough. Google’s algorithm interprets repetition as manipulation and replaces the title with a cleaner version.

    When a rewrite is better than your original

    Not every rewrite is bad. If Google pulls a clearer, more specific phrase from your H1 or body copy, your click-through rate might improve. Check Google Search Console’s performance report: compare impressions, clicks, and CTR before and after the rewrite. If CTR increases, leave it alone.

    If CTR drops or the rewritten title misrepresents the page, you have two options: rewrite the title tag to better match the H1 and body content, or rewrite the H1 to align with the title tag. Either way, alignment is what stops the rewrite.

    One non-obvious fix: add structured data. Google’s algorithm gives more weight to titles in Article or Product schema markup. If your title appears in structured data and matches the visible title, Google’s less likely to replace it.

    Want more operator-level breakdowns of how platforms actually work? Subscribe to One Two Three Send—one article every morning, no fluff, no affiliate listicles.

  • Analytics event deduplication: when double-counting inflates conversions

    Analytics event deduplication: when double-counting inflates conversions

    Analytics event deduplication: when double-counting inflates conversions
    Photo: Nemo bis via Wikimedia Commons (CC BY-SA 3.0)

    You’re tracking conversions across multiple tools—Google Analytics, your email platform, maybe a CRM—and the numbers don’t match. One dashboard says you had 47 signups yesterday. Another says 52. A third claims 61.

    The culprit is often event deduplication, or more precisely, the lack of it. When the same user action triggers multiple tracking events without a shared identifier to merge them, you end up counting the same conversion two, three, or more times.

    This isn’t just a reporting nuisance. Inflated conversion counts make your funnel look healthier than it is, lead you to overspend on acquisition channels that aren’t actually performing, and break attribution when you’re trying to figure out what’s working.

    How duplicate events happen

    The most common scenario: you fire a tracking pixel on page load and via a JavaScript event listener. A user completes a signup form. The page reloads to a thank-you URL. Your analytics script fires once on form submission, once on the new page load, and if you’ve got server-side tracking hooked into your backend, possibly a third time when the database write completes.

    Each event looks legitimate in isolation. None of your dashboards know the others exist. You see three conversions. Reality: one person signed up.

    Another pattern: tracking the same conversion in both client-side and server-side systems without a deduplication key. Google Analytics records the event when the browser sends it. Your email platform records it when the API call creates the subscriber. Your payment processor records it when the webhook fires. Same user, same action, three separate counts.

    Single-page apps make this worse. If your React or Vue app doesn’t manage history state carefully, navigation events can fire duplicate pageviews. Add a tag manager that reinitializes on every route change, and you’re stacking events every time someone clicks a link.

    What actually deduplicates events

    Most analytics platforms offer deduplication, but it’s not automatic. Google Analytics 4 uses a combination of client ID, session ID, and timestamp to merge events that fire within a narrow window—usually a few seconds. If your duplicate fires outside that window, or if the client ID changes between events (common in cross-device scenarios), GA4 treats them as separate.

    Facebook Pixel and other ad-platform tracking use event IDs. If you pass the same eventID parameter with both a browser pixel and a server-side Conversion API call, the platform deduplicates them. But you have to implement it. The default setup doesn’t generate or pass event IDs automatically.

    Email platforms like MailerLite and Beehiiv deduplicate by email address when you’re tracking list growth, but if you’re sending conversion events via API and tracking form submissions via their embed code, you’ll still double-count unless you add a check in your own code to prevent firing both.

    How to catch and fix it

    Start by auditing where your conversions get tracked. Open your browser’s network inspector, complete a test conversion, and watch how many tracking requests fire. Look for:

    • Multiple requests to the same analytics endpoint within a few seconds
    • Duplicate event names with identical or near-identical timestamps
    • The same conversion being sent to different platforms without a shared transaction or session ID

    If you’re running server-side tracking, check your logs. Grep for the event name and see if the same user ID or session appears multiple times for a single action.

    Once you’ve identified duplicates, the fix depends on your stack. If you’re firing events both on form submit and page load, pick one and remove the other. If you’re using both client-side and server-side tracking, implement event IDs or transaction hashes so platforms can merge them. If you’re tracking across multiple tools, designate one as the source of truth for each conversion type and use it to reconcile the others.

    For Google Analytics, enable User-ID tracking and pass a consistent identifier across sessions and devices. For Facebook, generate a unique event ID server-side, store it in the user’s session, and pass it with both pixel and API calls. For email platforms, check whether a subscriber already exists before firing a secondary conversion event.

    When deduplication breaks

    Deduplication fails silently when identifiers don’t match. A user clears cookies between events. A session expires. A server-side call uses a hashed email while the client-side call uses a raw one. A mobile app and a web browser use different device IDs.

    Cross-domain tracking makes this worse. If your checkout lives on a different domain than your marketing site, and you haven’t configured cross-domain measurement correctly, every conversion looks like a new session with a new client ID. No deduplication happens because the platform doesn’t recognize them as the same user.

    The best defense: log your conversion events somewhere you control—a database table, a Google Sheet via API, a Slack channel—and compare counts across platforms weekly. When your internal log shows 50 conversions and your analytics dashboard shows 73, you know you have a deduplication problem.

    One Two Three Send covers the tools and workflows solo operators actually use. If you want sharp, specific takes on analytics, email platforms, and everything else in the online-business stack, subscribe below.

    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.

  • Social media cross-posting tools treat replies inconsistently

    Social media cross-posting tools treat replies inconsistently

    Social media cross-posting tools treat replies inconsistently
    Photo by Alexander Shatov on Unsplash

    Cross-posting saves time. You write once, and your scheduler pushes the same content to Twitter, LinkedIn, Mastodon, and Threads. But while the original post goes everywhere, the responses don’t come back the same way—and that breaks conversations.

    Most cross-posting tools treat replies as read-only artifacts or don’t pull them at all. If someone comments on LinkedIn, you won’t see it in the dashboard unless the tool explicitly built LinkedIn comment ingestion. If someone replies on Twitter, it might appear in-app but won’t thread back to the Mastodon copy. You end up checking four inboxes anyway, which defeats half the point.

    What cross-posting tools actually sync

    Publer pushes your post to every connected account and pulls back basic engagement counts—likes, shares, retweets. But replies and comments stay on each platform. You can see that someone replied, but reading or responding requires clicking through to the native platform. There’s no unified inbox.

    Buffer works the same way: it shows reply counts in the dashboard, but you open Twitter or LinkedIn in a separate tab to read them. Buffer’s Analyze plan includes a basic reply view for Twitter, but it’s read-only. You still compose responses in the platform’s native interface.

    Hootsuite is the exception. Its inbox aggregates replies and mentions from Twitter, Facebook, Instagram, and LinkedIn into one feed. You can reply directly from Hootsuite, and the response posts back to the original platform. But it doesn’t support Mastodon, Threads, or Bluesky yet, so if you’re cross-posting to those, you’re back to checking them separately.

    Postpone, which is popular with solo operators, doesn’t pull replies at all. It’s purely a publisher. The analytics tab shows clicks and impressions via URL shorteners, but no social engagement data. If you want to see who replied, you open each platform manually.

    Why replies don’t unify

    APIs are the bottleneck. Twitter’s API lets apps read replies to your posts, but only if the reply mentions your username or is a direct thread descendant. Quoted tweets don’t always appear. LinkedIn’s API returns comments on your posts, but only for posts you published—comments on shares or reposts of your content are invisible to third-party tools.

    Mastodon technically allows full reply threading via ActivityPub, but most scheduling tools don’t support it yet because Mastodon instances rate-limit API calls differently. A tool built for Twitter’s global rate limits can’t assume Mastodon behaves the same way across hundreds of independent servers.

    Threads doesn’t have a public API yet. Tools that “support” Threads are using Instagram’s API as a proxy, which means reply ingestion is either unavailable or unreliable.

    How to design around it

    If you’re cross-posting to more than two platforms, accept that replies will scatter. Don’t promise to respond everywhere—pick one or two platforms where you’ll actually engage, and say so in your bio or pinned post. “I reply on Twitter and LinkedIn” sets expectations and consolidates where you spend attention.

    Use native notifications, not dashboard alerts. Turn on push or email notifications for replies on the platforms where you want to respond. Let the tool handle publishing, but let the platform handle reply alerts. Aggregated dashboards lag by minutes or hours, and you’ll miss time-sensitive conversations.

    If you’re running a team account, assign one platform per person. Cross-posting makes publishing faster, but reply management still requires humans. Split the work by platform, not by tool, so no one’s checking four inboxes trying to catch everything.

    When unified replies actually matter

    If you’re running a customer support account, use Hootsuite or Sprout Social—tools explicitly built for inbox unification. The extra cost is worth it when reply speed affects retention. For content-driven accounts, where replies are async conversations rather than service tickets, checking platforms individually is fine. You’re not losing money by waiting an hour.

    One exception: if you’re using social media as a lead channel and replies contain purchase intent or partnership inquiries, unified inboxes reduce response lag. But most solo operators and small teams don’t get enough inbound volume to justify the premium tier cost. You’ll know when you need it—your reply count will outpace your ability to check tabs.

    Want more tools and workflows that actually fit solo operators? Subscribe to One Two Three Send and get one operator-to-operator breakdown every morning.

    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.

  • ConvertKit vs. MailerLite: which one actually delivers better?

    ConvertKit and MailerLite both land on every “best newsletter platform” list. Both promise high deliverability. Both offer free tiers, automation builders, and landing pages. So which one actually gets your emails into inboxes more reliably?

    The short answer: it’s closer than you think, and deliverability alone probably shouldn’t decide this.

    Deliverability reputation and shared IP pools

    Both platforms use shared IP pools for most senders. That means your emails go out alongside thousands of other newsletters. If you’re on the Creator plan at ConvertKit (starts at $25/month for 1,000 subscribers) or any paid MailerLite tier (starts at $9/month for the same size), you’re sharing infrastructure with everyone else at your tier.

    ConvertKit’s advantage: they segment pools by sender reputation. High-engagement senders get routed through better-performing IPs. MailerLite uses a flatter pool structure, though they do isolate problematic senders.

    In practice, third-party inbox placement studies from mid-2025 through early 2026 show both platforms landing 92–96% of emails in primary inboxes for senders with clean lists and consistent engagement. The difference is statistically narrow—often within 2 percentage points depending on the test cohort.

    What matters more: your own list hygiene. A 40% open rate on MailerLite will outperform a 15% open rate on ConvertKit every time.

    Deliverability tooling: where they differ

    ConvertKit includes SPF and DKIM setup in onboarding, but custom domain sending (the “from” address uses your domain, not convertkit.com) requires a paid plan. MailerLite offers custom domain sending on all paid plans, including the $9 tier.

    Both platforms enforce list verification and double opt-in by default. ConvertKit is stricter about imported lists—they’ll flag high bounce rates faster and throttle sending if you upload a stale list. MailerLite gives you slightly more rope, which can be a liability if you’re not careful.

    Neither platform offers dedicated IPs on standard plans. ConvertKit Creator Pro (starts at $50/month) includes that option. MailerLite requires you to contact sales for dedicated IP pricing, typically starting around $80/month for higher-volume senders.

    Where ConvertKit pulls ahead

    Automation sophistication. ConvertKit’s visual builder lets you branch on link clicks, tag additions, custom field values, and purchase behavior. If you’re running a funnel with lead magnets, trip-wire offers, and product launches, ConvertKit’s logic handles complexity better.

    Subscriber tagging is more flexible. You can apply multiple tags per action, segment by tag combinations, and trigger sequences based on tag presence or absence. MailerLite has groups and segments, but the tagging system feels more rigid once you’re past 3,000 subscribers.

    Paid newsletter integration is native. ConvertKit Commerce lets you sell subscriptions and digital products without connecting Stripe separately. Revenue share is 3.5% + transaction fees. MailerLite requires third-party integrations for paid memberships.

    Where MailerLite wins

    Price. For the same 5,000 subscribers, ConvertKit charges $66/month. MailerLite charges $30/month. That’s $432/year in savings, which matters when you’re bootstrapped.

    Drag-and-drop email builder. ConvertKit’s editor is intentionally simple—plain text with minimal formatting. MailerLite gives you a visual editor with image blocks, buttons, columns, and templates. If your newsletter includes product showcases or event promotions, MailerLite’s design flexibility shows.

    Included features at lower tiers. Landing pages, pop-up forms, and A/B testing are available on MailerLite’s $9 plan. ConvertKit gates landing pages behind the $25 tier and limits forms on the free plan.

    Built-in website builder. MailerLite added a simple site builder in late 2025. It’s not WordPress, but if you need a landing page hub without spinning up hosting, it’s included.

    Who should pick which

    Choose ConvertKit if you’re running a creator business with multiple offers, a segmented audience, and automation sequences that branch based on behavior. The extra cost pays for itself if you’re monetizing through courses, coaching, or premium subscriptions.

    Choose MailerLite if you’re launching, your list is under 10,000, and you need a full-featured platform without spending $500+/year. The design flexibility and lower price make it easier to experiment before you’ve nailed product-market fit.

    Switch between them? Both platforms let you export your list as CSV. Automation sequences don’t transfer cleanly—you’ll rebuild those by hand. Expect half a day of work to migrate 3,000+ subscribers.

    Want more tool breakdowns like this? Subscribe to One Two Three Send and get operator-focused comparisons every week—no affiliate fluff, just what actually works.