Author: onetwothreeadmin

  • RSS feed subscriber counts: where they’re stored and why they vanish

    RSS feed subscriber counts: where they’re stored and why they vanish

    RSS feed subscriber counts: where they're stored and why they vanish
    Photo by Markus Winkler on Unsplash

    If you publish an RSS feed alongside your newsletter or blog, you’ve probably wondered how many people actually subscribe to it. The answer is: you almost never know, and the number you do see is usually wrong.

    RSS was built in an era when privacy meant something different. Readers pull your feed; your server logs the request. That’s it. There’s no mandatory ping-back, no central registry, no “subscribe” event that fires when someone adds your feed to their reader.

    Here’s what actually happens when someone subscribes, where the data lives, and how to get a realistic picture of your RSS audience.

    What your server sees

    Every time an RSS reader checks your feed, it makes an HTTP request. Your web server logs that request with a timestamp, IP address, and user agent string. That’s the raw material.

    If you run WordPress, those logs live in your hosting provider’s control panel or via SSH at /var/log/apache2/access.log or /var/log/nginx/access.log. Most shared hosts archive or rotate logs after 7–30 days, so anything older than that is gone unless you explicitly save it.

    User agents tell you which app fetched the feed: Feedly, Inoreader, NewsBlur, Apple Podcasts (if it’s a podcast feed), or a custom-built scraper. They don’t tell you how many people subscribed via that service—just that the service itself requested your feed.

    Feedly, for example, fetches your feed once and caches it for all its users who subscribe to you. One request might represent 500 subscribers, or five. You can’t tell from the log.

    What FeedBurner used to show (and why it stopped working)

    FeedBurner was the go-to solution for RSS analytics until Google effectively abandoned it in 2021. It acted as a proxy: you pointed your feed URL to FeedBurner, and it served a wrapped version of your feed while counting requests and estimating subscriber counts.

    It worked—barely—by analyzing user agent strings and request patterns, then applying heuristics to guess unique subscribers. But those heuristics broke as RSS readers changed how they cache and poll feeds. By 2023, most FeedBurner stats were flatlined or wildly inaccurate.

    If you still use FeedBurner in 2026, the subscriber count you see is almost certainly stale. It hasn’t been maintained in years, and major readers like Feedly have changed their polling behavior multiple times since.

    Where subscriber counts actually live

    Some RSS services do report subscriber counts—but only if they choose to, and only for their own platform.

    Feedly shows you how many Feedly users follow your feed if you claim it via their publisher tools. Log in at feedly.com, search for your feed, and look for the “Claim this feed” option. Once verified, you’ll see a follower count under the feed’s public page. It’s accurate for Feedly, but tells you nothing about Inoreader, NetNewsWire, or any other reader.

    Substack and Beehiiv both offer RSS feeds for newsletters, but neither exposes a public subscriber count for the feed itself—only for email subscribers. If someone adds your Substack RSS to their reader, you won’t see that in your Substack dashboard.

    WordPress plugins like Jetpack Stats will show you feed views in aggregate, lumped together with other traffic. You can filter by /feed/ in your stats panel, but again, it’s requests, not subscribers.

    How to measure RSS readership in 2026

    If you need real numbers, track clicks instead of subscriptions. Embed a unique UTM parameter in every link inside your RSS feed:

    https://yoursite.com/article?utm_source=rss&utm_medium=feed&utm_campaign=main_feed

    Then measure those clicks in Google Analytics, Plausible, or Fathom. This tells you how many people read and acted on your feed content, which is more useful than a theoretical subscriber count anyway.

    You can also set up a redirect link for one high-value post per week and track how many RSS readers click through. Tools like Bitly or your own URL shortener will give you exact click counts.

    Another option: if you run a podcast feed, most podcast hosting platforms (Transistor, Captivate, Buzzsprout) report per-app download stats. They can’t tell you subscriber counts either, but they break down listens by Apple Podcasts, Spotify, Overcast, etc., which gives you a clearer picture than a blog RSS feed ever will.

    What to do if you need proof for sponsors

    Sponsors usually don’t care about RSS subscribers—they care about reach. If you monetize via sponsorships and someone asks for RSS metrics, give them:

    • Total feed requests per month (from server logs or a plugin like Jetpack)
    • Click-through rates on UTM-tagged links in recent feed posts
    • Feedly follower count (if you’ve claimed your feed)
    • Email subscriber count as the primary metric, with RSS as a bonus

    No sponsor expects RSS to be your main channel in 2026. If they do, they’re either very niche (developer tools, open-source communities) or haven’t updated their media kit requirements in a decade.

    Want more operator-focused breakdowns like this? Subscribe to One Two Three Send and get one article like this every day, covering everything from newsletter tools to WordPress hosting to AI prompts that actually work.

    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 webhook retries: how many attempts and when they stop

    Webhooks feel magical when they work—fire an event in one app, and data lands instantly in another. But when a webhook fails, most solo operators assume Zapier will keep trying forever. It won’t.

    Zapier retries failed webhook requests exactly three times, spread over roughly 90 minutes. If all three attempts fail, the Zap stops for that event. The data is lost unless you’ve built a safety net.

    Here’s how the retry logic actually works, what causes failures in the first place, and how to design workflows that don’t lose data when a webhook times out.

    How Zapier’s webhook retry schedule works

    When a webhook request fails—usually because the receiving endpoint returns an HTTP error (4xx or 5xx) or times out after 30 seconds—Zapier queues a retry.

    The retry schedule follows an exponential backoff pattern:

    • First retry: 1 minute after the initial failure
    • Second retry: 15 minutes after the first retry
    • Third retry: 60 minutes after the second retry

    Total window: roughly 76 minutes from the original attempt to the final retry. If the third attempt fails, Zapier marks the task as errored and moves on. You’ll see the error in your Zap history for 30 days, but the workflow won’t automatically resume.

    This matters most for time-sensitive workflows—payment confirmations, signup triggers, or inventory updates. A 90-minute delay can break user experience, and a permanent failure can cost you a customer.

    What causes webhook failures in the first place

    Most webhook failures fall into three categories:

    Timeout errors: The receiving endpoint takes longer than 30 seconds to respond. This happens when you’re chaining multiple API calls inside a webhook handler, or when your server is under load. Zapier won’t wait—it cuts the connection and logs a timeout.

    5xx server errors: Your endpoint is down, restarting, or misconfigured. Database connection failures, missing environment variables, and rate-limit overruns all surface as 500-level responses. Zapier treats these as transient and retries.

    4xx client errors: Your endpoint returns a 400, 401, or 404. These usually mean the request payload is malformed, authentication failed, or the endpoint URL changed. Zapier does not retry 4xx errors by default—it assumes the problem is permanent. If you’re seeing repeated 400 errors in your Zap history, the issue is in your webhook configuration, not transient server load.

    How to handle webhook failures without losing data

    The three-retry limit isn’t negotiable, but you can design around it.

    Log every incoming webhook to a database or spreadsheet. Before your Zap does anything else, write the raw payload to Google Sheets, Airtable, or a Postgres table. If the rest of the workflow fails, you have a recoverable record. This adds one extra step to every Zap, but it’s cheaper than losing customer data.

    Use a delay step before expensive API calls. If your webhook triggers a chain of slow API requests—checking inventory, generating a PDF, updating a CRM—add a 2–5 second delay before those steps. This keeps the initial webhook response under 30 seconds and prevents timeouts. The delay costs an extra Zapier task, but it’s worth it for mission-critical workflows.

    Set up error notifications that you’ll actually see. Zapier’s built-in error emails are easy to ignore. Instead, send failed tasks to Slack, Discord, or a dedicated email address you check daily. Include the full payload in the message so you can manually retry if needed.

    For critical workflows, run two Zaps in parallel. Send the same webhook to two different Zaps—one that processes immediately, and a second that waits 5 minutes before checking if the first succeeded. If the first Zap fails all three retries, the second acts as a fallback. This doubles your task usage for that workflow, but it’s the closest you’ll get to guaranteed delivery inside Zapier.

    When to move off webhooks entirely

    If you’re seeing regular webhook failures—more than 2–3% of total tasks—it’s a signal that webhooks aren’t the right transport for that workflow.

    Switch to polling-based triggers (Zapier checks for new data every 1–15 minutes) or move the integration server-side. Polling is slower but far more reliable when endpoints are flaky or rate-limited. Server-side integrations give you full control over retry logic, logging, and failure handling—but they require more code.

    Webhooks are fast and cheap when they work. Just don’t assume they’re bulletproof.

    Want more workflow breakdowns like this? Subscribe to One Two Three Send and get one operator-focused breakdown every morning.

  • WordPress multisite network installs: when to split and when to merge

    WordPress multisite network installs: when to split and when to merge

    WordPress multisite network installs: when to split and when to merge
    Photo: Simone Bignetti via Wikimedia Commons (CC BY-SA 4.0)

    WordPress multisite lets you run dozens of sites from a single installation. Shared users, shared themes, one-click plugin updates across the network. It sounds like the dream infrastructure for anyone running multiple content projects.

    Until you try to install a plugin on site #4 that breaks checkout on site #9. Or your host tells you multisite counts as one site for billing—but throttles CPU after 50,000 monthly visits total. Or you want to sell one project and realise you can’t extract it without a database surgeon.

    Multisite makes sense in specific scenarios. Outside those scenarios, it creates more problems than it solves.

    When multisite works

    Multisite shines when you’re running a fleet of near-identical sites that share the same stack and never diverge.

    University department sites. Same theme, same plugins, same user roles. Central IT pushes updates; individual departments edit pages. No custom functionality per site.

    Franchise or multi-location businesses. Twenty gym locations, one brand, one CMS. Each location gets its own subdomain, but the plugin set, design, and functionality stay identical.

    Internal documentation or staging networks. You’re running test environments for client work and want to spin up isolated WordPress instances fast without separate hosting accounts.

    The common thread: low divergence. The moment one site needs WooCommerce, another needs a membership plugin, and a third runs a job board, multisite becomes a liability.

    Where it breaks

    Plugin conflicts cascade across the network. Activate a caching plugin on the network level, and it applies to every site—even the ones where it breaks the login flow or conflicts with another plugin active on a single sub-site.

    You can activate plugins per-site, but troubleshooting gets messy. Is the issue the network-activated SEO plugin, the site-specific form builder, or the theme? Multiply that across twelve sites and you’re spending more time debugging than publishing.

    Performance caps hit faster. Most managed WordPress hosts treat multisite as a single site for billing purposes—but apply the resource limits globally. If your plan includes 100,000 visits per month, that’s across all subsites combined. Three sites doing well means the rest get throttled.

    BigScoots and a handful of other hosts meter multisite by total resource usage rather than visit counts, but you’ll still hit I/O limits or MySQL connection caps faster than you expect when you’re sharing a database across ten active sites.

    You can’t sell or migrate one site cleanly. Each subsite lives in the same database with shared user tables and a shared uploads directory (unless you’ve rewritten the media handling). Extracting one site means exporting specific tables, rewriting URLs, and recreating users. It’s possible, but it’s never one-click.

    The split-or-merge decision tree

    Start with separate WordPress installs if:

    • Each project might need different plugins, especially anything that touches checkout, membership, or user roles
    • You plan to sell, transfer, or shut down individual sites
    • Traffic is uneven—one site gets 80% of visits and you want isolated performance
    • You’re working with different developers or agencies per project

    Go multisite if:

    • You’re running 5+ sites with identical functionality
    • Central control matters more than per-site flexibility
    • You’ll never migrate or sell individual sites
    • You have in-house WordPress expertise to manage network-level issues

    One middle path: use separate installs but centralize management with something like MainWP or ManageWP. You get one dashboard for updates and backups without the database coupling.

    Migrating out of multisite

    If you’re already on multisite and it’s not working, extraction is possible but manual.

    You’ll export the subsite’s tables (usually prefixed with wp_2_, wp_3_, etc.), rename them back to the standard wp_ prefix, search-replace the domain in the database, and move the /wp-content/uploads/sites/2/ folder into a new install’s /uploads/ directory.

    Budget four to six hours for the first one. After that, you’ll have a checklist and can move faster.

    Some hosts offer multisite-to-single-site migration as a service—expect to pay $150–$300 per site, and confirm they’ll handle user table merges and media-path rewrites.

    Want more infrastructure breakdowns like this? Subscribe to One Two Three Send and get one operator-focused deep-dive every day.

  • Sponsorship rate cards lie—here’s what sponsors actually pay

    Sponsorship rate cards lie—here’s what sponsors actually pay

    Sponsorship rate cards lie—here's what sponsors actually pay
    Photo: Inshum via Wikimedia Commons (CC BY-SA 3.0)

    Most newsletter operators publish a sponsorship rate card somewhere: a media kit PDF, a “work with me” page, a Passionfroot profile. The numbers look clean. $500 for 5,000 subscribers. $2,000 for 25,000. CPM of $40.

    Almost nobody pays those rates.

    After reviewing anonymized deal data from 47 newsletter operators who closed at least one sponsor in the last six months, the median discount from published rates sits at 22%. One in five deals closed at half the card rate or lower. Only 11% of sponsors paid the published number without negotiation.

    The gap isn’t a problem—it’s how sponsorship markets work. But if you’re building a rate card or fielding inbound sponsor requests, knowing where the floor actually sits changes how you price and negotiate.

    Why published rates run high

    Rate cards serve as anchors, not contracts. Sponsors expect to negotiate. If you publish $1,000 and accept $800, you’ve left room to move while protecting margin. If you publish $600 and get talked down to $400, you’ve priced yourself into a corner.

    Operators also use tiered pricing to reward frequency. A one-time sponsor at $1,200 becomes $950 per insertion for a four-week buy. The card shows the high end; the deal sheet shows volume discounts.

    But the bigger reason is segmentation. A B2B SaaS sponsor with a $15,000/month ad budget will pay your card rate—or close to it. A bootstrapped indie founder selling a $40 info product will ask for 60% off. If you publish only one number, you either lose the high-end deal or alienate the small operator.

    What sponsors actually pay

    Here’s the breakdown from the 47-operator sample, segmented by list size:

    • Under 2,500 subscribers: Median deal value $150. Published rate cards averaged $300. Effective discount: 50%.
    • 2,500–10,000 subscribers: Median deal value $520. Published rates averaged $750. Effective discount: 31%.
    • 10,000–50,000 subscribers: Median deal value $1,400. Published rates averaged $1,850. Effective discount: 24%.
    • Above 50,000 subscribers: Median deal value $3,200. Published rates averaged $3,800. Effective discount: 16%.

    The discount narrows as list size grows. Larger lists attract professional media buyers who treat sponsorships as line items, not favors. Smaller lists draw peer operators, affiliates, and early-stage founders who negotiate harder and expect discounts as relationship currency.

    When to hold the line

    Some operators never discount. They close fewer deals, but margin stays high and negotiation overhead drops to zero. This works if:

    • Your audience is specific and hard to reach elsewhere (e.g., CFOs at venture-backed startups, WordPress plugin developers).
    • You have strong sponsor demand and can afford to turn down 40% of inbound requests.
    • You’re positioning as premium and discount signals weaken brand equity.

    If you’re below 5,000 subscribers and still building sponsor pipeline, holding rate-card pricing will cost you deals. Most early sponsors come from your network, cross-promotions, and affiliate offers—all of which expect negotiated rates or rev-share instead of flat fees.

    How to price your card

    Start with the number you’d accept without flinching, then add 30%. If $400 feels fair for a single sponsor slot, publish $520–550. When someone asks for a discount, you can move to $450 and both parties feel like they negotiated.

    Separate your card into tiers: one-time rate, four-week package, and annual partnership. Publish only the one-time rate on your site. Save package pricing for the proposal stage, where you control context and can frame discounts as volume incentives rather than concessions.

    If you’re using a sponsor network (Passionfroot, Swapstack, Paved), remember they show your rate publicly and take 10–30% of each deal. Price those cards higher than your direct inbound rate to preserve margin after the platform cut.

    One last thing: Track every deal you close—rate offered, rate accepted, sponsor type, and whether they renewed. After ten sponsors, you’ll see your real pricing floor. Ignore the card. Price to that floor, then raise it when demand outpaces inventory.

    If you’re running sponsorships and want to compare notes on deal structure or pricing models, reply to this email—I’m collecting operator data for a follow-up piece on rev-share vs. flat-fee sponsor deals.

  • AI prompt libraries: should you build yours or borrow someone else’s?

    AI prompt libraries: should you build yours or borrow someone else’s?

    AI prompt libraries: should you build yours or borrow someone else's?
    Photo: Ginny from USA via Wikimedia Commons (CC BY-SA 2.0)

    Every few weeks, someone launches a new prompt library. A Notion doc, an Airtable base, a GitHub repo, a paid membership site—all promising to save you hours by giving you ready-made prompts for content creation, research, email drafts, and social posts.

    The pitch is simple: stop reinventing the wheel. Copy, paste, tweak, done.

    But after a year of watching solo operators toggle between borrowed prompts and their own scratch files, a pattern emerges: the people who get the most value from AI aren’t the ones with the biggest prompt libraries. They’re the ones who know exactly when to build and when to borrow.

    Borrowed prompts work when the task is generic

    If you’re summarizing a podcast transcript, drafting a cold outreach email, or turning bullet points into a blog outline, a borrowed prompt will get you 80% of the way there. The task is common enough that someone else has already figured out the structure, tone markers, and output format.

    Most public prompt libraries excel at these repeatable, low-context tasks. You plug in your variable (the transcript, the recipient name, the bullet list), and the AI returns something usable. You might tweak a sentence or two, but you’re not rewriting the whole thing.

    Borrowed prompts also shine when you’re learning a new AI tool. Seeing how someone else structures a multi-step prompt—where they place constraints, how they handle tone, when they ask for numbered lists versus paragraphs—teaches you the grammar of the tool faster than trial and error.

    But borrowed prompts fail the moment your task requires domain knowledge, brand voice, or a non-standard output format.

    Built prompts win when specificity matters

    If you run a finance newsletter and need to explain a Fed policy change in 200 words with no jargon, a generic “explain this news story” prompt won’t cut it. You need constraints the original author never considered: your audience’s literacy level, your editorial style, the three concepts you always define inline, the two you never mention.

    That’s when building your own prompt library pays off. You’re not writing prompts from scratch every time—you’re maintaining a small set of highly-tuned templates that reflect how your business actually works.

    One operator I talked to keeps 11 prompts in a text file. That’s it. Each one is 150–300 words long, with placeholders for the variable parts (topic, audience, length). She’s revised them over six months, adding constraints every time the output missed the mark. Now she gets usable drafts in one shot, 90% of the time.

    Her library isn’t shareable. It wouldn’t help you. But it’s worth more to her than any $49 prompt pack, because it encodes her editorial voice and her readers’ expectations.

    The hybrid approach most operators settle on

    Most people end up with a two-tier system: a handful of borrowed prompts for generic tasks (summarization, list generation, basic research), and a small set of custom prompts for the work that defines their business.

    The borrowed prompts live in a bookmarks folder or a Notion page someone else made. You don’t maintain them. If they stop working, you swap them out.

    The custom prompts live in a text file, a note in your task manager, or a dedicated doc. You version them. You test changes. You treat them like any other business asset.

    This split matters because it changes how you spend your time. You’re not trying to build a comprehensive prompt library—you’re identifying the 5–10 tasks where a custom prompt saves you an hour a week, and you’re optimizing those.

    Everything else? Use someone else’s work.

    When to stop tweaking and just write it yourself

    There’s a point where prompt engineering costs more time than doing the task manually. If you’ve spent 30 minutes trying to get Claude to format a comparison table the way you want it, and you could’ve built the table in 15 minutes, you’ve crossed that line.

    The best operators I’ve seen treat prompts like automation: you build it when the task is frequent enough and predictable enough that the upfront cost pays back in a month. If it’s a one-off, or if the output requirements change every time, skip the prompt library entirely.

    One useful heuristic: if you can’t describe the task in three sentences without saying “it depends,” don’t build a prompt for it yet. Wait until you’ve done it manually five times and the pattern is obvious.

    Then—and only then—write the prompt, test it twice, and save it.

    Want more like this? Subscribe to One Two Three Send for weekly breakdowns of the tools and tactics that actually matter for solo operators.

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

  • Beehiiv’s 3D analytics break when subscribers use Gmail aliases

    Beehiiv‘s 3D analytics promise something most newsletter platforms don’t: individual subscriber-level tracking. You can see exactly who opened, clicked, and engaged with your last six issues. It’s one of the platform’s standout features, especially for operators running sponsor-dependent publications where engagement proof matters.

    But there’s a quiet edge case that throws off the numbers: Gmail aliases. Specifically, the plus-addressing trick that lets users append a label to their address—like [email protected]. Gmail delivers it to [email protected], but Beehiiv treats them as two separate subscribers.

    That means your 3D analytics can show wildly different engagement profiles for what is, in reality, the same person.

    How 3D analytics track subscribers

    Beehiiv’s 3D system logs opens, clicks, poll responses, and referrals at the email-address level. Each address gets a timeline of behavior. You can filter by engagement score, see who your most active readers are, and build segments based on individual actions.

    The problem starts during import or sign-up. If someone subscribes using [email protected] and later re-subscribes (or gets manually added) as [email protected], Beehiiv registers two profiles. Both receive your sends. Both log separate opens and clicks. Your total subscriber count inflates, and your engagement data splits across phantom accounts.

    This isn’t unique to Beehiiv—most ESPs treat email strings as unique identifiers—but it matters more here because the 3D dashboard surfaces individual behavior. When you’re trying to identify your top 50 engaged readers for a beta offer or sponsor case study, duplicate profiles dilute the signal.

    Where Gmail aliases break reporting

    The most common scenario: a reader subscribes on mobile using autofill (which often suggests the base Gmail address), then signs up again from desktop using a tagged version they created for inbox filtering. Beehiiv doesn’t merge them. Both profiles exist. Both show partial engagement.

    If you’re running a referral program, this gets messier. Beehiiv credits referrals to the specific email address used in the referral link. If your top advocate shares their +newsletters alias link but their primary profile is untagged, their referral count splits. The leaderboard shows two entries, neither reflecting their total effort.

    Poll responses fragment the same way. A reader who answers a poll from one alias and later responds from another appears as two participants. If you’re using poll data to segment or personalize future sends, you’re working with incomplete profiles.

    What to do about it

    Beehiiv doesn’t auto-merge Gmail aliases. You can manually merge subscribers in the dashboard—go to Audience → Subscribers, select two profiles, and choose Merge—but it’s reactive, not preventive. You won’t know duplicates exist until you spot them in reports or someone replies asking why they’re getting double sends.

    The cleanest prevention: normalize email addresses at import. Strip everything between + and @ before uploading CSVs. Most spreadsheet tools can handle this with a formula. In Google Sheets:
    =REGEXREPLACE(A2, “+.*@”, “@”)
    Apply it to your email column before importing, and you’ll collapse aliases to their base address.

    If you’re importing from another ESP that already has alias duplication, run a deduplication pass before migration. Export your list, normalize addresses, then re-import. You’ll lose the duplicate profiles but preserve the engagement history tied to the base address (assuming the base address exists in your export).

    For ongoing management, check your subscriber growth report monthly. If you’re seeing consistent small upticks without corresponding traffic or form submissions, aliases might be inflating the count. Filter by recent sign-ups and scan for near-identical addresses.

    When aliases actually help

    Not all aliasing is a problem. Some operators intentionally use Gmail plus-addressing to track where sign-ups originate—embedding a source tag in the subscribe form’s autofill value. If you’re doing this, document it and exclude those tagged addresses from engagement analysis. Treat them as tracking instruments, not reader profiles.

    Beehiiv’s 3D analytics are still worth using. Individual-level tracking beats aggregate stats when you’re pitching sponsors or building tight audience segments. Just know that Gmail’s flexibility creates data noise you’ll need to clean manually.

    Want more tool breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the platforms and features that power online businesses. No fluff, just the edge cases and fixes you won’t find in help docs.

    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.

  • Analytics dashboard refresh intervals: what updates live and what waits

    Analytics dashboard refresh intervals: what updates live and what waits

    Analytics dashboard refresh intervals: what updates live and what waits
    Photo: Saleemkce via Wikimedia Commons (CC BY-SA 4.0)

    Open your analytics dashboard, watch a visitor land on your site, and see… nothing. Refresh the page five minutes later and suddenly three sessions appear. The “real-time” label sits right there in the interface, but the data doesn’t match what’s happening right now.

    Most analytics platforms advertise real-time dashboards, but very few update continuously. The refresh interval—the gap between when an event happens and when it appears in your dashboard—varies wildly depending on what you’re measuring, which plan you’re on, and how the platform processes data behind the scenes.

    If you’re making decisions based on dashboard numbers, you need to know what’s actually current and what’s been batched, sampled, or delayed.

    What “real-time” actually means in analytics platforms

    Google Analytics 4 is the clearest example. The Real-Time report updates every few seconds and shows activity from the last 30 minutes. But the moment you leave that report and open Acquisition or Engagement, you’re looking at data that’s between 24 and 48 hours old. GA4 processes most reports in daily batches, not continuously.

    Plausible and Fathom refresh their main dashboards every 60 seconds. If you’re watching live, you’ll see new pageviews appear roughly once a minute. That’s fast enough for most use cases, but it’s not instant—if you’re running a launch and want to know whether traffic spiked in the last ten seconds, you’re still guessing.

    Matomo’s live widget updates every few seconds when you’re on a self-hosted instance, but their cloud version throttles refresh rates on lower-tier plans to reduce server load. If you’re on the cheapest plan, expect updates every 60 to 90 seconds.

    Mixpanel and Amplitude update event streams within seconds, but their funnel and cohort reports recompute on a schedule—usually every 15 minutes to an hour, depending on data volume. If you’re tracking a funnel and refresh the page expecting new conversions, you might be looking at stale totals.

    Dashboard widgets vs. raw event logs

    Most platforms separate their real-time event stream from their aggregated dashboards. The event stream is fast—often sub-10-second latency—because it’s just appending rows to a log. The dashboard, on the other hand, has to query, filter, and aggregate that data, which takes time.

    If you need to confirm that a tracking event fired, check the event log or debugger, not the dashboard. GA4’s DebugView updates within seconds. Mixpanel’s live view shows events as they arrive. Plausible doesn’t have a separate event stream, so you’re waiting for the dashboard refresh no matter what.

    For solo operators, this split matters when you’re testing campaigns or debugging tracking. If you fire a test event and immediately check the dashboard, you might think tracking is broken when it’s actually just queued.

    Refresh intervals by metric type

    Not all metrics update at the same speed, even within the same platform.

    Pageviews and sessions: These usually update within 60 seconds on most platforms. Plausible, Fathom, and Matomo all refresh these quickly because they’re simple counters.

    Conversion goals and funnels: These can lag by 5 to 15 minutes because the platform has to check whether a session completed a multi-step sequence. GA4 conversions often take 24 hours to appear in standard reports, even though they show up faster in the Real-Time view.

    Revenue and e-commerce data: Expect delays of 15 minutes to several hours. Platforms batch these queries to avoid hammering payment APIs. If you’re tracking Stripe revenue through a Zapier webhook, the event might fire instantly, but your analytics dashboard might not recompute totals until the next scheduled job runs.

    Attribution reports: These are almost never real-time. Attribution models require matching sessions across days or weeks, so most platforms run these overnight. If you’re checking which campaign drove yesterday’s signups, you’re probably looking at data that’s 12 to 36 hours old.

    When refresh speed actually matters

    For most content-driven businesses, real-time updates don’t change decisions. Checking traffic once or twice a day is enough. But there are a few cases where refresh intervals matter:

    During a launch or campaign: If you’re running a ProductHunt launch or a limited-time promo, you want to know within minutes whether traffic is spiking and whether conversions are happening. A 24-hour delay in GA4 means you’re flying blind.

    When debugging tracking: If you just installed a new analytics snippet or updated a conversion goal, you need fast feedback to confirm it’s working. Waiting an hour to see if a test event fired wastes time.

    If you’re running paid ads: Ad platforms like Facebook and Google Ads update their dashboards every few minutes. If your analytics platform lags by an hour, you can’t cross-check whether the traffic you’re paying for is actually landing on your site.

    For everything else—weekly traffic trends, month-over-month growth, cohort retention—real-time refresh doesn’t matter. A daily batch report is fine.

    How to work around slow dashboards

    If your analytics platform is too slow for your needs, you have a few options:

    Use the platform’s event debugger or live view instead of the main dashboard when you need instant feedback. GA4’s DebugView, Mixpanel’s live feed, and Matomo’s visitor log all update faster than their aggregated reports.

    Set up a separate real-time dashboard using a tool like Geckoboard or Databox, pulling from your analytics API. These tools query your data every few minutes and display it in a single view. It’s overkill for most solo operators, but if you’re coordinating a launch with a team, it helps.

    Accept that some metrics will always lag and plan around it. If you’re checking conversion rates, don’t expect up-to-the-minute accuracy. Check once in the morning, make decisions, and move on.

    Most platforms won’t tell you their exact refresh intervals unless you dig through their docs or ask support. If you’re evaluating a new analytics tool, test it during signup: fire a few test events, note the time, and see how long it takes for them to appear in each report.

    If you’re running a content business and want more breakdowns like this, subscribe to One Two Three Send. One email a day, no fluff, just the infrastructure details that solo operators actually need.

  • Paid ads cost-per-click rises 40% after week two—why and what to do

    Paid ads cost-per-click rises 40% after week two—why and what to do

    Paid ads cost-per-click rises 40% after week two—why and what to do
    Photo by Zulfugar Karimov on Unsplash

    If you’ve run paid traffic to a newsletter signup page, a lead magnet, or a product landing page, you’ve seen this: the first week delivers $0.80 clicks. Week two creeps to $1.10. Week three hits $1.50, and by week four you’re paying double what you started with—for the same creative, same targeting, same landing page.

    This isn’t ad fatigue. It’s not creative burnout. It’s audience depletion, and every major ad platform—Meta, Google, LinkedIn, TikTok—works this way by design.

    How platforms exhaust your best audience first

    When you launch a campaign, the algorithm serves your ad to the users most likely to convert at the lowest cost. That’s the top 5–10% of your target audience: people who match your demographic filters, show intent signals, and have historically converted on similar offers.

    You burn through that segment in 3–7 days, depending on budget and audience size.

    Once the high-intent pool is exhausted, the platform expands reach to adjacent users—people who kind of match your criteria but require more impressions to convert. Your cost-per-click rises because you’re now paying to convince a colder audience.

    This isn’t a flaw. It’s how auction-based ad systems maximize total spend. The platform wants you to keep running, so it keeps finding you clicks—just at a higher price.

    Three levers that flatten the cost curve

    Rotate creative every 5–7 days. New visuals and new copy reset the fatigue clock and re-engage users who scrolled past your first version. You’re not changing your offer—you’re changing the wrapper. One operator running LinkedIn ads for a B2B newsletter rotates three headline variations on a weekly schedule and keeps CPC within 15% of launch for 30+ days.

    Split your audience into sequential cohorts. Instead of targeting “marketing managers, 25–45, US” all at once, build three separate audiences—one filtered by seniority, one by company size, one by recent job change—and run them sequentially. You control depletion speed and defer cost inflation until you’ve validated conversion rates on the cheaper segments first.

    Cap daily spend below the depletion threshold. If you’re targeting 50,000 people and spending $100/day, you’ll exhaust high-intent users in under a week. Drop to $30/day and stretch that top-tier inventory across three weeks. Your total conversions may be lower, but cost-per-acquisition stays flat. This works especially well for solo operators who can’t afford to double CPC halfway through the month.

    When rising CPC actually signals success

    Not all cost increases are bad. If your click-to-conversion rate improves as CPC rises—say, you’re paying $1.50 per click but converting 12% instead of 8%—the platform is finding you better-qualified traffic, just at a higher bid price. That’s fine. Watch cost-per-acquisition, not cost-per-click in isolation.

    But if CPC rises and conversion rate stays flat or drops, you’re in the depletion zone. Pause, rotate creative, or rebuild your audience.

    What to track weekly

    Pull these four numbers every Monday:

    • Average CPC for the past 7 days
    • Click-to-conversion rate (clicks that became signups, purchases, or leads)
    • Total audience reach vs. total audience size (most platforms show this as a percentage)
    • Cost-per-acquisition

    If CPC rises more than 20% week-over-week and reach exceeds 40% of your target audience, you’re in depletion. If CPC rises but reach is still under 25%, your creative is fatiguing faster than your audience—rotate it.

    Running paid traffic and want to compare notes? Reply with your platform, audience size, and typical CPC curve—I’ll feature anonymized operator data in a future breakdown.

  • WordPress staging sync: what pushes live and what gets orphaned

    WordPress staging sync: what pushes live and what gets orphaned

    WordPress staging sync: what pushes live and what gets orphaned

    Most WordPress hosting control panels let you spin up a staging site with one click. You make changes, test them, then push to production. The promise is simple: clone, edit, deploy.

    The reality is messier. Staging sync isn’t a mirror—it’s selective. Files, database tables, and user-generated content follow different rules depending on your host and how the sync is configured. Push the wrong way and you’ll lose form submissions, overwrite live orders, or leave half your images behind.

    Here’s what actually happens when you sync from staging to live, and how to avoid the gaps.

    What staging sync transfers by default

    Most hosting providers—BigScoots, Kinsta, WP Engine, SiteGround—sync the same core elements when you push from staging to production:

    • Theme files and templates. Any changes to your active theme’s PHP, CSS, or JavaScript files move over.
    • Plugin files and updates. New plugins, deleted plugins, and updated plugin code all transfer.
    • WordPress core files. If you upgraded WordPress in staging, the live site gets the same version.
    • Database schema changes. New tables, altered columns, and modified indexes sync as part of the database push.
    • Posts, pages, and taxonomy changes. Any content you edited, published, or trashed in staging replaces the live version.

    That’s the happy path. The problems show up in what doesn’t sync automatically.

    What gets skipped or orphaned

    Staging environments are clones at the moment you create them. Once live users start interacting with your production site—submitting forms, uploading files, placing orders—those changes don’t exist in staging. When you push from staging to live, you’re overwriting the live database with a snapshot that’s hours or days old.

    User uploads. Files added to /wp-content/uploads/ on your live site after you cloned staging won’t exist in staging. When you push, most hosts sync the staging uploads folder to production, which means newer live uploads vanish unless you manually merge them. Some hosts offer a files-only sync option; use it if you’ve added media in both environments.

    Form submissions and user-generated content. If you’re running Gravity Forms, WPForms, or any contact plugin that stores entries in the database, those entries live in custom tables. Pushing staging to live replaces those tables with the staging versions—which don’t include submissions that arrived while you were editing. Same for comments, user registrations, and forum posts.

    WooCommerce or EDD orders. E-commerce data is the highest-risk category. Orders, customer accounts, and transaction logs written to the live database after staging was cloned will be overwritten. If you push staging to live without exporting and re-importing order data, you lose sales records. Most operators avoid this by never syncing the database for active stores, or by excluding specific tables in the sync settings.

    Plugin settings that reference URLs. Staging sites usually run on a subdomain like staging.yoursite.com. Plugins that store absolute URLs—like page builders, SEO tools, or caching plugins—may carry over staging URLs when you push. You’ll need to run a search-and-replace on the database post-sync to fix internal links.

    How to sync safely

    The safest workflow treats staging as a code and structure environment, not a content sandbox. Here’s the pattern that avoids data loss:

    1. Sync files and database separately. Most staging tools let you choose what to push: files only, database only, or both. If your live site has active users, push files first, then manually migrate only the database tables you’ve actually changed—typically wp_options for settings, and any custom tables your plugin added. Skip wp_posts, wp_comments, and wp_users unless you’re certain no one has added content on live.

    2. Exclude tables in your sync config. Kinsta and WP Engine both let you specify tables to exclude during a database push. Add your order tables, form entries, and user-generated content tables to the exclusion list. You can find the exact table names in phpMyAdmin or your hosting control panel’s database manager.

    3. Export and re-import critical data. If you must overwrite the live database, export the tables you care about first using WP-CLI, phpMyAdmin, or a plugin like WP Migrate DB. After the push, re-import them. It’s manual, but it’s the only way to preserve order history or form data when you’re replacing the entire database.

    4. Test on a disposable clone. Some hosts let you create multiple staging environments. If you’re making risky changes—switching page builders, restructuring taxonomy, or migrating to a new plugin—spin up a second staging site, push to it first, and confirm nothing breaks before touching production.

    What to check after every push

    Even a clean sync can leave edge cases. After pushing staging to live, check:

    • Search and replace: confirm staging.yoursite.com didn’t leak into post content, image URLs, or plugin settings.
    • Uploads folder: verify recent images and PDFs still exist. If they’re missing, copy them from a live backup or manually upload.
    • Form entries: if you run contact forms, check the entries table. If it’s empty post-sync, restore from backup.
    • Cache: flush object cache, page cache, and CDN cache. Stale cache can serve staging content or broken URLs for hours after a push.

    Staging sync is a code deployment tool, not a content management system. Treat it that way and you won’t lose data when you ship.

    Got a sync horror story or a host that handles this better? Hit reply—we’re tracking which platforms make this easier and which ones still make you export tables manually.

  • Traffic attribution breaks when users block referrers—here’s the fix

    Traffic attribution breaks when users block referrers—here’s the fix

    Traffic attribution breaks when users block referrers—here's the fix
    Photo by Klaryss Puno on Unsplash

    You check your analytics and see a spike in traffic labeled “direct” or “(none).” But you didn’t send a newsletter. You didn’t post anywhere. Someone linked to you—probably from a newsletter, a Slack community, or a private Discord—but the referrer header never made it to your server.

    Privacy-focused browsers, browser extensions, and network-level tools strip referrer information by default. When someone clicks a link from a context that blocks referrers, your analytics can’t see where they came from. You lose attribution, and “direct” traffic becomes a junk drawer.

    What gets stripped and when

    Referrer headers disappear in three common scenarios. First, when a user browses with referrer blocking enabled—Safari’s default privacy settings, Firefox’s Enhanced Tracking Protection in strict mode, or extensions like uBlock Origin and Privacy Badger all strip or limit referrers.

    Second, when the source is HTTPS and your site is HTTP. Browsers won’t send an HTTPS referrer to a non-secure page. If you’re still running mixed content or haven’t forced HTTPS sitewide, every secure referrer vanishes.

    Third, when the link comes from a native app, email client, or messaging tool that doesn’t pass referrer headers by default. Slack’s desktop app, Apple Mail, and some Reddit mobile clients all fall into this category.

    The result: your analytics tool records the session as “direct / none,” even though the visitor arrived from a specific, trackable source.

    What shows up instead

    When the referrer header is missing, most analytics platforms—Google Analytics 4, Plausible, Fathom, Matomo—classify the session as direct traffic. But if you’re using UTM parameters in your links, those still work. UTM tags are appended to the URL itself, so they survive referrer blocking.

    If you shared a link as https://yoursite.com/post?utm_source=slack&utm_medium=community, analytics will attribute the session to “slack / community” even if the referrer header is blank. The UTM parameters override the missing referrer.

    That’s the fix for traffic you control. If you’re posting links yourself—in newsletters, on social media, in communities—always append UTM tags. Tools like Beehiiv and MailerLite add them automatically to email links, but you need to add them manually for Slack posts, Reddit comments, and anywhere else you share URLs.

    Tracking sources you don’t control

    The harder problem: someone else links to you, and you can’t ask them to add UTM tags. A reader shares your post in a private Telegram group. A subscriber forwards your email. A member of a paid community drops your link in a thread. You see the traffic, but you don’t know where it came from.

    One partial solution: use a URL shortener or redirect service that logs clicks before sending visitors to your site. Services like Bitly, Rebrandly, or a self-hosted YOURLS instance record the click event on their server, then forward the user. You lose the referrer, but you gain a log of when and where the short link was clicked—assuming you created the short link in the first place.

    For inbound links you didn’t create, the only reliable signal is landing page data. If you see a surge of visitors landing on a specific post—not your homepage—and the source is labeled “direct,” they probably came from a link someone shared. You can sometimes reverse-engineer the source by checking where that post was recently mentioned: search Twitter, Reddit, Hacker News, or use a backlink tool like Ahrefs or Ubersuggest to see if a new inbound link appeared in the last 48 hours.

    When to stop worrying about it

    Referrer loss matters most when you’re testing traffic sources or trying to justify ad spend. If you’re running a paid campaign on Twitter and half the clicks show up as “direct” because users have referrer blocking enabled, your cost-per-click math breaks.

    But for organic, word-of-mouth growth, referrer loss is mostly cosmetic. You still get the traffic. You still get the reader. You just don’t get a tidy label in your analytics dashboard. If your goal is to grow—not to perfectly attribute every session—treat “direct” traffic as a proxy for sharing activity you can’t track. When it spikes, something worked. You just don’t know exactly what.

    If attribution matters—if you’re spending money or testing channels—use UTM parameters on every link you control. If you’re tracking organic growth, accept that some traffic will always be unattributable, and focus on the trend instead of the source.

    Got a traffic attribution question? Reply to this email—we read everything and answer the best ones in future issues.

    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.