Author: onetwothreeadmin

  • Reddit’s new Ads API opens self-serve targeting to solo operators

    Reddit’s new Ads API opens self-serve targeting to solo operators

    Reddit rolled out a full-featured Ads API in late May 2026, and most solo operators missed it. The platform had previously gated programmatic access behind agency partnerships and minimum monthly spends well into five figures. Now you can spin up campaigns, pull performance data, and automate bid adjustments with a free developer account and a credit card that clears the $5 daily minimum.

    If you’ve been running Reddit ads through the web dashboard or ignoring the platform entirely because the manual workflow didn’t scale, this changes the math.

    What the API actually unlocks

    The new endpoints cover campaign creation, audience targeting, creative upload, bid management, and reporting. You can now script campaign launches tied to content publish dates, auto-pause underperforming ad groups when cost-per-click crosses a threshold, or pull spend and conversion data into your own analytics stack without CSV exports.

    The targeting options mirror what’s available in the dashboard—subreddit lists, interest clusters, keyword targeting, and lookalike audiences based on pixel data—but you can now template and duplicate campaigns in bulk. If you’re testing ten subreddit combinations across three creative variants, that’s thirty manual setups in the UI versus a single script run.

    Rate limits sit at 600 requests per minute for most endpoints, which is generous for a solo operator or small team. Creative assets upload through a separate media endpoint that accepts PNG, JPG, and MP4 up to 200 MB. Video ads now support 16:9 and 4:5 aspect ratios, though square still outperforms in feed placement based on Reddit’s own case studies published in April.

    Where the workflow breaks down

    The API documentation assumes you’re comfortable with OAuth 2.0 flows and can parse JSON responses without a GUI. If you’ve never touched an API before, the learning curve is steeper than clicking through Ads Manager. Reddit provides Python and JavaScript SDKs, but they’re not as polished as Meta’s or Google’s—expect to write more error-handling logic yourself.

    Conversion tracking still requires Reddit’s pixel or the Conversions API, and setup is manual. You can’t provision pixels programmatically yet, so your first campaign still involves copying a JavaScript snippet into your site footer or wiring up server-side events. If you’re running a headless CMS or a static site, the server-side route is cleaner but requires endpoint configuration that isn’t trivial.

    The API also doesn’t surface some diagnostics that show up in the dashboard. If an ad gets rejected for policy violations, the error message in the API response is often a generic code without the specific flagged term. You’ll still need to log into the web UI to see what tripped the filter.

    Pricing and when this makes sense

    Reddit ads run on a second-price auction with a $5 daily minimum per campaign. CPCs vary wildly by subreddit—anywhere from $0.20 in broad interest groups to $4+ in finance or SaaS communities. The API doesn’t change the auction mechanics, but it does let you kill spend faster when a test flops.

    This is worth the setup time if you’re running more than two campaigns a month, testing multiple subreddit clusters, or pulling ad data into a consolidated dashboard alongside Google, Meta, or other channels. If you’re spending under $500/month total and running a single evergreen campaign, the manual workflow is still faster.

    For content-driven businesses publishing on a schedule—newsletters that promote each issue, course creators launching cohorts, or affiliates running seasonal pushes—the ability to automate campaign start dates and creative swaps cuts hours of repetitive work.

    One non-obvious trick

    Reddit’s audience expansion toggle is on by default when you create campaigns through the API, even if you specify exact subreddit targeting. This means Reddit will serve your ad outside your defined subreddit list if its algorithm thinks the user matches your intent. That’s fine for awareness plays, but it torches budgets if you’re targeting a niche community for a specific reason.

    The parameter is expansion_enabled in the campaign create request. Set it to false unless you’ve explicitly decided to let Reddit’s algorithm roam. The dashboard makes this a checkbox you have to actively enable; the API flips the default.

    If you want to test this without writing code, tools like Postman or Insomnia let you authenticate and send API requests through a GUI. Reddit’s OAuth flow is standard—register an app in your account settings, grab your client ID and secret, request a bearer token, and attach it to subsequent requests. The whole setup takes about fifteen minutes if you’ve done it with another platform before.

    Have you tried Reddit’s Ads API yet, or are you sticking with another platform for paid tests? Reply and let us know—we’re tracking which ad channels solo operators actually use in 2026, and we’ll share the numbers in a future issue. Subscribe here if you want that data when it drops.

  • WordPress plugin auto-updates: when to enable and when to wait

    WordPress plugin auto-updates: when to enable and when to wait

    WordPress added automatic plugin updates in version 5.5, and the feature has quietly become one of the most misunderstood levers in the admin dashboard. Enable it everywhere and you risk pushing a breaking change to production at 3 a.m. Disable it completely and you’re one unpatched vulnerability away from a compromised site.

    The decision isn’t binary. Most operators treat auto-updates as an all-or-nothing switch, but the smarter play is selective: some plugins earn the privilege, others don’t.

    What actually happens when you enable auto-updates

    When you toggle auto-updates for a plugin, WordPress adds it to a background job that runs twice daily. If a new version is available and passes a few basic checks—compatible WordPress version, no obvious conflicts—the update executes without asking.

    The update happens during a cron event, not in real time. If your site has low traffic or your server’s cron is misconfigured, the update may delay by hours. That’s not a bug; it’s how WordPress schedules background tasks.

    WordPress sends an email after each auto-update. If you’re not seeing those, check your transactional email setup—most hosts route wp_mail() through unreliable SMTP by default. If you’re using Postmark or another dedicated transactional service, the notifications land reliably.

    One detail most guides skip: auto-updates do not create database backups before running. If a plugin update breaks your schema or corrupts data, you’re restoring from your last manual or scheduled backup. That’s why staging environments matter.

    Which plugins to trust with auto-updates

    Not all plugins carry the same risk profile. Small, single-purpose utilities—contact forms, social share buttons, analytics connectors—rarely introduce breaking changes. They touch a narrow slice of your site and update infrequently.

    Security-focused plugins are the best candidates: Wordfence, Sucuri, iThemes Security. These update often, and delaying a security patch is riskier than the update itself. The vendors test obsessively because their reputation depends on it.

    Plugins maintained by large platforms—Jetpack, WooCommerce, Yoast SEO—also qualify. They have QA teams, beta cycles, and rollback mechanisms. Auto-updating these is less risky than manually updating at random intervals.

    Avoid auto-updates for plugins that:

    • Modify your database schema (membership plugins, custom post-type builders)
    • Interact with payment processors (WooCommerce extensions, Easy Digital Downloads add-ons)
    • Control caching or performance (WP Rocket, LiteSpeed Cache—these can break rendering)
    • Hook deeply into your theme (page builders, custom fields)

    For these, the cost of an unexpected break in production outweighs the convenience of hands-off updates.

    How to test updates before enabling auto-update

    If you’re running a staging environment, clone production, enable auto-updates there first, and wait two weeks. If nothing breaks, enable it on the live site. Staging environments catch 80% of update conflicts before they hit real traffic.

    If you don’t have staging, manual-update high-risk plugins during low-traffic windows. Check your analytics for the quietest two-hour block each week—usually early morning in your primary timezone—and batch updates then. Keep your browser open for ten minutes after updating and test key workflows: checkout, form submissions, member login.

    For plugins that update frequently—weekly or more—auto-updates make sense even if they’re high-risk, because the manual burden becomes unsustainable. You’ll spend more time clicking “Update” than you’ll lose to occasional rollbacks.

    The non-obvious tip: monitor update frequency before committing

    Before enabling auto-updates, check the plugin’s update history on WordPress.org. Click “Development” in the plugin’s listing and scan the changelog. If the vendor ships five updates a month with vague notes like “bug fixes” or “performance improvements,” that’s a red flag. Frequent, low-detail updates suggest poor testing or reactive development.

    Plugins that update every 60–90 days with detailed changelogs are safer bets. The vendor is batching changes, running QA, and treating releases as events rather than continuous patches.

    One more filter: check the “Active Installations” count. Plugins with 100,000+ installs get battle-tested by a large user base. If a breaking change ships, it’s caught and patched within hours. Plugins with fewer than 10,000 installs don’t have that safety net.

    Auto-updates work best when the plugin vendor has more to lose than you do. High-profile plugins with millions of users can’t afford to break sites at scale. Niche plugins with small audiences can.

    Want more deployment and workflow tips? Subscribe to One Two Three Send—every issue covers one specific decision point for operators running content businesses.

  • Newsletter subscriber surveys: what to ask and what to skip

    You want to know what your subscribers care about. A survey feels like the obvious solution. But most operators write surveys that produce either useless vanity metrics or mountains of data they don’t have time to parse.

    The problem isn’t surveying itself—it’s asking the wrong questions, at the wrong time, in the wrong format. Here’s how to build a subscriber survey that gives you actionable editorial direction without burning goodwill or drowning in responses you can’t use.

    Ask about future content, not past issues

    The most common survey mistake is asking subscribers to rate or rank your previous newsletters. “Which issue did you like best?” or “How would you rate our content?” These questions feel safe, but they’re backward-looking and subjective.

    Instead, ask what they want to read next. Frame questions around problems they’re trying to solve or topics they’re actively researching. For example:

    • “What’s the biggest challenge you’re facing with [your niche topic] right now?”
    • “Which of these topics would help you most in the next 30 days?”
    • “What question do you wish someone would answer about [topic]?”

    You’re not polling for popularity—you’re mining for editorial gaps. The answers tell you what to write, not whether people liked what you already sent.

    Keep it to three questions, maybe four

    Survey fatigue is real. If your form scrolls, response rates drop. If it takes more than 90 seconds, you lose half your respondents before they finish.

    Limit yourself to three core questions. If you absolutely need a fourth, make it optional. Use multiple-choice wherever possible—open-text fields are harder to analyze at scale, and most subscribers won’t fill them out anyway.

    Here’s a template structure that works:

    • Question 1: Multiple-choice topic preference (4–6 options)
    • Question 2: Open-text pain point or challenge (optional)
    • Question 3: Demographic or context question (e.g., “How long have you been running your business?”)

    That’s it. You’ll get a higher completion rate and cleaner data.

    Segment your ask—don’t survey everyone at once

    Not all subscribers need to answer the same questions. If you’re running a newsletter with both beginners and experienced operators, surveying them together will muddy your results.

    Instead, segment your survey by behavior or tenure. For example:

    • New subscribers (joined in the last 30 days) get a short onboarding survey focused on their current goals.
    • Engaged readers (opened 8+ of the last 10 emails) get a deeper content-direction survey.
    • Inactive subscribers (haven’t opened in 60+ days) get a simple re-engagement question: “What would make this newsletter more useful to you?”

    Most email platforms—MailerLite, Beehiiv, ConvertKit—let you tag or segment by open rate or signup date. Use that data to send the right survey to the right group.

    Don’t survey more than twice a year

    Survey burnout is worse than survey silence. If you ask for feedback every quarter, subscribers start ignoring you. Once or twice a year is plenty—unless you’re pivoting your editorial strategy or launching a new product.

    When you do survey, close the loop. Send a follow-up email a week later summarizing what you heard and what you’re changing. It doesn’t have to be long—three bullet points and a sentence about what’s coming next. This reinforces that their input mattered and primes them to respond next time.

    One operator I know sends a yearly survey in January and a mid-year check-in in June. Both are three questions, both close with a “here’s what I heard” email. Her response rate hovers around 22%, well above the typical 10–15% for cold surveys.

    Skip the NPS question

    Net Promoter Score—”How likely are you to recommend this newsletter?”—is a corporate metric that doesn’t translate well to solo operators. It’s designed for companies with large customer bases and multi-touch attribution. For a newsletter, it’s noise.

    You don’t need a numerical score. You need to know what to write next and whether you’re solving the right problems. Save the NPS question for SaaS dashboards.

    Use survey data to build a content queue, not a strategy document

    Once responses come in, resist the urge to over-analyze. You’re not running a focus group—you’re filling your editorial calendar.

    Pull the top three topics or pain points mentioned. Schedule one article or issue for each in the next 30 days. If a question came up repeatedly in open-text responses, turn it into a Q&A or tutorial. That’s the loop: ask, write, ship.

    Survey data goes stale fast. If you wait two months to act on feedback, the problems your subscribers cared about in March might be irrelevant by May. Treat survey results like perishable inventory.

    Want more tactical breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools, tactics, and trade-offs that matter for online operators.

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

  • Course completion rates hover around 15%—here’s what moves the needle

    Course completion rates hover around 15%—here’s what moves the needle

    The average online course completion rate sits between 10% and 20%. If you’re running a paid course as part of your content business, that number probably feels familiar—and frustrating.

    The usual advice—gamification, drip schedules, community access—sounds good in theory. But the data from operators actually running courses tells a different story about what moves completion rates and what’s mostly noise.

    What the numbers look like in practice

    Three operators shared their course metrics over the past 18 months. All three run evergreen courses priced between $149 and $497, sold primarily to their email lists.

    Operator A: A WordPress productivity course with 847 enrollments. Completion rate: 18%. Average time to finish: 6.3 weeks. Refund rate: 4.2%.

    Operator B: An SEO fundamentals course with 1,203 enrollments. Completion rate: 23%. Average time to finish: 9.1 weeks. Refund rate: 6.8%.

    Operator C: A newsletter monetization course with 614 enrollments. Completion rate: 14%. Average time to finish: 11.4 weeks. Refund rate: 3.1%.

    The spread is narrow. All three courses include video lessons, worksheets, and some form of community or Q&A access. Pricing and production quality didn’t predict completion—the $497 course had the lowest rate.

    Three changes that actually moved the needle

    Operator B added a single check-in email at the 72-hour mark. It’s not a drip sequence. It’s one manual email sent three days after purchase asking what section the student is working on and if anything’s blocking them. Response rate: 31%. Completion rate climbed from 19% to 23% over six months. The email takes four minutes to send per cohort of 20–30 buyers.

    Operator A cut the course from 22 lessons to 14. The original version tried to be comprehensive. The shorter version focused on three workflows and cut everything else. Completion rate went from 14% to 18%. Refund rate stayed flat. Students finished faster—5.1 weeks instead of 7.8—and left better reviews.

    Operator C introduced a 48-hour «finish line» challenge. Once a month, students who’ve completed 80% or more get an email with a 48-hour window to finish the last module and submit their final project. It’s not a hard deadline—the course stays open—but the nudge works. Completion among students who receive the email: 67%. Overall course completion rose from 11% to 14%.

    What didn’t work

    All three operators tried Facebook groups or Slack communities. Operator A’s group had 18% of enrollees join; 4% posted more than once. Operator B shut down their Slack after three months—too much moderation overhead for minimal engagement. Operator C kept a Circle community but stopped treating it as a completion lever.

    Gamification—badges, progress bars, leaderboards—showed no measurable impact on completion for any of the three. Operator B’s course platform (Teachable) includes progress tracking by default. Students who completed the course had the same interaction rate with progress indicators as students who dropped off after module two.

    Drip schedules were neutral to slightly negative. Operator A tested releasing one lesson per week versus full access on day one. Completion rates were statistically identical (17.8% vs. 18.1%), but students on the drip schedule were more likely to request refunds in week two, before the course was fully unlocked.

    The completion-rate mistake most operators make

    Chasing higher completion rates assumes completion is always the right goal. It’s not.

    Operator C’s course teaches newsletter monetization. Some students buy it, watch the sponsorship module, land their first sponsor, and never finish the rest. They got what they paid for. Refund rate is low. Testimonials are strong. Completion rate is 14%.

    The better metric: outcome rate. What percentage of students achieved the result the course promised? For Operator C, 41% of students reported landing a sponsor, affiliate deal, or paid subscription tier within 90 days. That’s nearly three times the completion rate—and the number that matters for retention and referrals.

    If you’re optimizing for completion, track it. But if you’re optimizing for business results, measure the outcome your course promises and work backward from there.

    Want more operator data like this? Reply and tell us what metrics you’re trying to move—we’ll find operators who’ve solved it and share what worked.

  • WordPress Staging Environments: What Actually Needs Testing

    WordPress Staging Environments: What Actually Needs Testing

    You spin up a staging site, clone production, test a plugin update, see it works, push live. Two days later something breaks. The staging test missed it.

    Staging environments promise safety. They deliver it only when you know what actually needs testing—and what’s theater.

    Most solo operators and small teams treat staging as a checkbox: “I tested it.” But staging sites differ from production in ways that make certain tests useless and certain risks invisible. Here’s what to focus on when you’ve got limited time and a site that can’t afford downtime.

    Test Database-Dependent Changes, Skip Static Ones

    Plugin updates that touch the database—anything involving custom post types, user roles, or schema changes—need staging. A membership plugin, an SEO tool that rewrites permalinks, a form builder that stores submissions: these can corrupt data or break queries if they fail mid-migration.

    Static changes—new CSS, a JavaScript library update, a theme tweak that doesn’t touch PHP logic—can often be tested locally or on a low-traffic page. Staging won’t tell you much more than your browser’s dev tools already do.

    The dividing line: if the change writes to wp_options, wp_posts, wp_users, or custom tables, stage it. If it’s front-end only and reversible with FTP, you can skip the full staging ritual.

    Replicate Traffic Patterns, Not Just Data

    A cloned database and codebase won’t show you how a change performs under load. Staging sites run on lighter server specs, handle zero concurrent users, and skip most caching layers. That makes them poor predictors of performance.

    If you’re testing a resource-heavy plugin—an analytics injector, a lazy-load script, a page builder—check server resource usage in staging, then simulate traffic with a tool like Query Monitor or a simple load test script. Watch for memory spikes, slow database queries, and HTTP request waterfalls.

    Don’t bother testing page-load speed in isolation. Staging won’t have your CDN, your object cache, or your production traffic patterns. The metric that matters is relative performance: does the change make queries slower or add significant overhead?

    Test Integration Points, Not Just Features

    The plugin works in staging. But does it work with your email delivery, your payment processor, your analytics, your CDN purge rules?

    Most staging environments disable or sandbox third-party API calls. That’s smart for safety, but it means your tests skip the failure modes that break production: a conflict between your caching plugin and your transactional email setup, a payment webhook that doesn’t fire after a checkout-flow redesign, a CDN that stops purging after you change permalink structure.

    Before you push live, test one full user flow that touches external services. Sign up, receive an email, complete a purchase, check that analytics fire. Use staging API keys where possible. If your staging site can’t connect to real services, document which integration points weren’t tested—and monitor them closely post-deploy.

    When Staging Wastes Time

    Staging is overkill for editorial changes, minor copy edits, and media uploads. It’s also overkill for plugin updates from trusted sources that don’t touch your database schema—security patches, minor version bumps with no migration scripts.

    If your staging workflow takes more than ten minutes to clone, test, and sync back, you’ll start skipping it. That’s worse than a streamlined process that tests only high-risk changes.

    For low-stakes updates, use a checklist instead: back up the database, update, check two representative pages, verify one user flow. If it breaks, restore. If your host offers one-click staging, use it. If you’re manually cloning databases and running search-replace scripts, reserve staging for changes that justify the time cost.

    What to Do After You Push

    Staging can’t catch everything. Production has real traffic, real user behavior, real edge cases. After you deploy, monitor actively for 24 hours.

    Check server error logs, watch for broken form submissions, scan your checkout flow if you touched payments, verify email delivery if you updated SMTP routing. Use a simple uptime monitor—Uptime Robot’s free tier works—and set an alert for HTTP 500 errors.

    If something breaks, your staging tests didn’t predict it. Add that failure mode to your next staging checklist. Over time, you’ll build a list of tests that actually matter for your site, not just the generic advice.

    What’s your staging workflow? Reply and tell us what you test before you push live—or what broke in production despite passing staging. We read every reply.

  • Paid ads vs. organic SEO: the real break-even timeline

    Paid ads vs. organic SEO: the real break-even timeline

    Two operators I know launched similar content sites in Q3 2025. Same niche—B2B SaaS workflows. Same publishing cadence—two posts per week. Same monetisation model—affiliate revenue and a small paid community.

    One went all-in on Google Ads from day one. The other committed to pure SEO for six months, then layered in paid only after organic traffic hit 10,000 monthly visits.

    They compared notes in April 2026. The data surprised both of them.

    What the paid-first operator spent

    Operator A launched with a $1,500/month Google Ads budget, targeting bottom-of-funnel keywords around tool comparisons and buyer intent phrases. Cost per click averaged $2.80. Monthly traffic in month one: 520 visits. Conversion to email: 4.2%, or roughly 22 subscribers.

    By month six, the budget was still $1,500. Traffic had grown to 980 visits per month as ad copy and landing pages improved. Email conversion climbed to 6.1%. Total ad spend through six months: $9,000. Total subscribers acquired via paid: 312. Cost per subscriber: $28.85.

    Affiliate revenue during those six months: $1,840. The site was still $7,160 in the hole on traffic acquisition alone, before accounting for content production time or tooling costs.

    What the SEO-first operator saw

    Operator B published the same cadence but spent nothing on ads. Month one traffic: 14 visits, all from social shares and a few backlinks. Month three: 310 visits as Google started indexing comparison posts. Month six: 11,400 visits, driven by three posts that cracked page-one rankings for medium-competition keywords.

    Email conversion rate: 3.8%, slightly lower than paid because organic traffic skews top-of-funnel. Total subscribers by month six: 433. Cost per subscriber: $0 in media spend, though time cost was real—roughly 60 hours of keyword research, on-page optimisation, and link outreach spread across six months.

    Affiliate revenue during the same six months: $4,720, turning profitable in month five when one post started ranking for a high-intent buyer keyword.

    The real break-even point

    Operator A’s paid strategy didn’t break even on media spend until month eleven, when cumulative affiliate revenue finally overtook cumulative ad spend. By that point, the site had 640 email subscribers and was generating $890/month in predictable affiliate commissions. Paid traffic was stable and forecastable, but expensive to maintain.

    Operator B’s SEO play broke even on opportunity cost around month seven—the point where monthly affiliate revenue exceeded what the operator would have earned freelancing for the same 60 hours. Traffic continued compounding. By month eleven, the site was at 18,200 monthly visits with zero ongoing media cost.

    The gap widened from there. Operator B’s affiliate revenue hit $2,100/month by month twelve. Operator A’s hovered around $1,050, constrained by ad budget and CPCs that crept upward as competition entered the space.

    When paid makes sense anyway

    This isn’t an argument to never run ads. Operator A’s paid strategy delivered two things SEO couldn’t: speed and certainty. Subscribers showed up in week one, not month four. Conversion data came fast enough to iterate on messaging and offer positioning before building six months of content on a guess.

    Operator A also controlled the tap. Need 50 more email subscribers this week to hit a sponsor commitment? Increase the daily budget. SEO doesn’t let you do that.

    The break-even calculus shifts if you’re monetising with a higher-ticket offer. If each email subscriber is worth $80 in course revenue instead of $6 in affiliate commissions, a $28 cost per acquisition makes paid the faster path to cash flow.

    But for affiliate-driven content businesses with patient capital and time to write, the SEO curve still wins on total return. The sixth-month inflection point is real—if you can survive it.

    One thing to try this week: If you’re running paid traffic, model out what happens if you cut your budget in half and redirect that cash into content production or link outreach. Run both channels for 90 days and compare cost per conversion, not just cost per click. The answer will tell you which lever to pull harder.

    Hit reply if you’ve run this experiment yourself—I’m collecting more data points for a follow-up piece.

  • AI writing tools forget your style guide—here’s how to fix it

    AI writing tools forget your style guide—here’s how to fix it

    You’ve spent three sessions training Claude to write in your brand voice. It nails your tone, mirrors your sentence structure, finally stops using “delve” and “unlock.” Then you open a new chat two days later and it’s back to corporate buzzword soup.

    This isn’t a bug. It’s how context windows work. And if you’re using AI to draft blog posts, social captions, or email sequences at scale, you’re losing hours re-teaching the same preferences every time you start fresh.

    The fix isn’t more detailed prompts. It’s building a reusable style anchor that travels with you across sessions, tools, and team members.

    Why AI forgets your voice

    Most AI models—Claude, ChatGPT, Gemini—treat each conversation as a contained context window. When you close the chat or hit token limits (usually 100,000–200,000 tokens depending on the model), everything you taught it evaporates.

    Some tools offer “memory” features or custom instructions, but they’re shallow. ChatGPT’s custom instructions cap at 1,500 characters. Claude Projects can hold more, but most operators work across multiple tools depending on the task. Your style guide needs to be portable, not locked into one platform’s feature set.

    The other problem: vague instructions don’t work. Telling an AI to “write conversationally” or “be punchy” produces different output every time. You need examples, constraints, and a reference text it can pattern-match against.

    Build a style anchor document

    A style anchor is a 500–800 word plain-text document that lives in your notes app, project folder, or password manager. You paste it into the start of every new AI session before asking it to write anything.

    Here’s what to include:

    • Voice principles: Three to five concrete rules. Not “be casual”—instead, “Use contractions. Start sentences with conjunctions. Write like you’re replying to an operator email, not publishing a press release.”
    • Forbidden words and phrases: List the clichés and jargon your industry overuses. For online-business writing, that’s usually “leverage,” “unlock,” “game-changer,” “dive deep,” “robust.”
    • Sentence structure preferences: Max sentence length, whether you allow one-sentence paragraphs, how you handle lists.
    • Three example paragraphs: Pull these from your best-performing posts. The AI will mimic the rhythm, syntax, and vocabulary distribution.
    • Formatting conventions: How you use em dashes, whether you write “email” or “e-mail,” if you use Oxford commas, how you format tool names.

    Keep it under 1,000 words. Longer anchors eat into the AI’s working memory and slow down responses.

    How to use it in practice

    Every time you open a new chat or switch projects, paste the full style anchor as your first message. Then prompt normally.

    If you’re working in a tool with persistent memory (Claude Projects, ChatGPT with a dedicated GPT), load the anchor once and reference it explicitly: “Follow the style guide I provided. Now write an intro for a post about WordPress caching plugins.”

    For team workflows, store the anchor in a shared doc. Anyone drafting content pastes it in before prompting. This keeps voice consistent even when three people are writing under the same byline.

    One non-obvious trick: version your anchor. When you notice the AI drifting or you refine your preferences, save the updated version as style-anchor-v2.txt. This lets you A/B test tone changes without losing the original.

    What this fixes (and what it doesn’t)

    A good style anchor eliminates 80% of voice drift across sessions. You’ll stop rewriting AI drafts from scratch and spend more time editing for accuracy and structure.

    It won’t fix factual errors, and it won’t teach the AI your audience’s specific pain points. You still need to brief it on context for every piece: who you’re writing for, what problem you’re solving, what the reader should do next.

    It also won’t replace editorial judgment. AI drafts still need a human pass for logic gaps, unsupported claims, and the occasional hallucinated stat. But you’ll spend that time on substance, not rewriting every sentence to sound like you.

    If you’re generating more than five pieces of content per week with AI—blog posts, social threads, email sequences, product docs—the style anchor pays for itself in saved editing time within a week.

    Want more operator-focused breakdowns of AI tools, hosting infrastructure, and traffic strategy? Subscribe to One Two Three Send and get one tactical deep-dive every day, no fluff.

    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.

  • Instagram Threads API: What It Does and What It Still Can’t Do

    Instagram Threads API: What It Does and What It Still Can’t Do

    Meta released the Threads API in June 2024, and after two years of iteration, it’s finally stable enough for solo operators to trust. But “stable” doesn’t mean “complete.” If you’re deciding whether to pipe content into Threads via a third-party tool—or build a custom integration—you need to know where the guardrails are.

    Here’s what the API actually supports, what it doesn’t, and one non-obvious limitation that breaks scheduling workflows more often than you’d expect.

    What the Threads API Lets You Do

    The current version supports programmatic publishing: text posts up to 500 characters, single images, carousels, and video. You authenticate via Meta’s developer portal, generate a long-lived access token (valid for 60 days), and POST to the publishing endpoint. Response time averages 1.2 seconds for text-only posts, 4–7 seconds for media uploads.

    Third-party schedulers like Publer and Hootsuite route through this API. You draft in their interface, schedule a time, and the tool fires the publish request on your behalf. It works—most of the time.

    The API also supports read operations: you can pull your own thread metrics (views, likes, replies, quotes), fetch replies to a specific thread, and retrieve your profile metadata. Rate limits sit at 200 requests per hour per user token, which is enough for a solo operator scheduling 3–5 posts per day and checking analytics once or twice.

    What’s Still Missing

    Three big gaps remain, and they’re not on Meta’s public roadmap.

    First: carousel post previews. You can upload up to 10 images in a carousel via the API, but there’s no way to preview how the cropping and ordering will render before the post goes live. Desktop simulators exist for Instagram, but Threads’ mobile-first layout differs enough that what looks clean in a 1:1 preview often clips awkwardly on the actual feed. You won’t know until it’s published.

    Second: scheduling beyond 75 days. The API accepts a publish_time parameter, but it rejects any timestamp more than 75 days in the future. That’s fine for daily schedulers, but if you batch content quarterly or run evergreen campaigns tied to fixed dates six months out, you’ll need to manually reschedule or script a secondary trigger closer to publish time.

    Third: no support for polls, GIFs, or link previews. Threads introduced native polls in March 2025, but the API still doesn’t expose a poll creation endpoint. Same for GIFs—they’re supported in the mobile app, but API calls strip them to static images. Link previews render automatically when you paste a URL in the app, but API-published posts display raw text links with no card, no thumbnail, no title. Engagement on link posts drops 30–40% as a result.

    The Non-Obvious Problem: Token Expiry During Scheduled Windows

    Here’s what breaks more workflows than media upload failures: Threads access tokens expire after 60 days, and there’s no automatic refresh mechanism.

    If you schedule a post for 62 days out, the API accepts the request at queue time—because the token is still valid. But when the publish window arrives, the token has expired, and the request fails silently. Most schedulers don’t surface this failure in real time. You’ll only notice when you check your profile two days later and realise the post never went live.

    The fix: set a recurring calendar reminder every 55 days to regenerate your token, or use a scheduler that auto-refreshes tokens via OAuth. Publer handles this for Threads; Buffer and Later don’t yet (as of June 2026).

    When to Use the API vs. Posting Natively

    Use the API if you’re cross-posting the same content to Twitter, Bluesky, and Threads. The time savings justify the format compromises.

    Post natively if you’re running a campaign where polls, GIFs, or link cards matter—product launches, surveys, or affiliate content. The API isn’t mature enough to preserve those elements yet.

    And if you’re scheduling more than two months out, plan to refresh tokens manually or script a cron job that regenerates them every 50 days. The 60-day expiry isn’t changing anytime soon.

    Want breakdowns like this for other platform APIs? Reply with the tool you’re trying to automate—I’ll cover it in a future edition.

    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.

  • Google Analytics 4 event debugging: where custom events disappear

    Google Analytics 4 event debugging: where custom events disappear

    You fire a custom event in Google Analytics 4. You check DebugView. Nothing. You check the real-time report. Still nothing. Three days later, the event count sits at zero.

    Custom events in GA4 fail more often than platform defaults, and the diagnostic trail is deliberately obscure. If you run a content business that tracks signups, downloads, or affiliate clicks through GA4 events, silent failures cost you attribution data you can’t recover.

    Here’s where custom events break, how to trace the failure, and what to fix before you file a support ticket or hire a developer to rebuild your entire tracking stack.

    The four places custom events disappear

    1. The event never fires in the browser. Your tag manager condition is wrong, the trigger element doesn’t exist on the page, or JavaScript errors block execution. Open your browser’s console, filter by “gtag” or “dataLayer,” and watch for the push. If you see nothing when you click the button or load the page, the event isn’t leaving the client.

    2. The event fires but GA4 rejects it. Event names longer than 40 characters get dropped. Parameter names with spaces, hyphens, or uppercase letters get silently ignored. If your event is called affiliate_link_clicked_homepage_sidebar_cta, GA4 truncates it. If your parameter is link-URL, it’s gone. Check the naming rules and test with a simplified version.

    3. The event arrives but DebugView doesn’t show it. DebugView only displays events from sessions where debug mode is active—either through the GA4 DebugView Chrome extension, a debug_mode parameter in your gtag config, or a query string flag. If you’re testing in an incognito window without the extension, you won’t see anything even if the event is logging correctly in production. Switch to the real-time report or wait 24–48 hours for the event to appear in the standard reports.

    4. The event logs but doesn’t appear in reports. GA4 has a 500-event-name limit per property. If you’ve already registered 500 custom events (common in properties that auto-track every button click or scroll depth), new events get dropped. You won’t get a warning. Check your event list under Configure → Events and archive unused events to free up slots.

    What to check first

    Start with the browser console, not DebugView. Log in as a test user, trigger the event, and confirm the dataLayer.push fires. If it does, check the payload for naming violations—no spaces, no capitals, no special characters except underscores.

    Next, verify the event reaches Google. Open the Network tab in your browser’s developer tools, filter by “collect,” and look for a request to google-analytics.com/g/collect with your event name in the query string. If you see it there, the event left your site. If GA4 still doesn’t show it, the rejection happened server-side.

    Finally, check your property’s event quota. Go to Configure → Events and count how many are marked as custom. If you’re near 500, you’ve hit the ceiling. Archive old events or consolidate similar actions under a single event name with dynamic parameters.

    Common silent failures

    Measurement Protocol events submitted without a valid client_id get logged but attributed to no user. If you’re sending server-side events from a backend script, make sure you’re passing the same client_id that the client-side gtag generated. Mismatched IDs orphan the event.

    Events fired before the GA4 config tag loads get lost. If you’re triggering a custom event on page load and your tag manager fires it before the GA4 initialization completes, the event won’t attach to a session. Add a delay or fire the event only after gtag('config') resolves.

    Cross-domain tracking breaks event attribution if the _ga cookie doesn’t transfer. If you’re tracking affiliate clicks that redirect to an external domain and back, make sure your linker parameter is appended correctly. A missing or malformed linker drops the session context, and the returning event lands in a new session with no history.

    When to rebuild vs. patch

    If fewer than 10% of expected events are missing, patch the specific failure—usually a naming issue or a trigger condition. If more than half your custom events don’t log, your implementation is structurally broken. Start over with a fresh tag manager container, test each event in isolation, and document the client_id and session flow.

    GA4’s error messages are deliberately vague. The platform won’t tell you which parameter failed or why an event didn’t register. Build your own logging layer—either a server-side event collector that mirrors GA4 calls or a Google Sheets endpoint that receives a copy of every dataLayer push. When GA4 goes silent, your backup log will show what actually fired.

    Got a GA4 event that refuses to log? Reply with the event name and trigger setup—I’ll tell you where to look.

  • Notion’s API rate limits: what breaks and how to route around them

    Notion’s API rate limits: what breaks and how to route around them

    If you’re running automations that read from or write to Notion—content calendars, CRM pipelines, client dashboards—you’ve probably hit the wall where everything just… stops working. No error message in your automation tool. No failed tasks in Zapier or Make. Just silence.

    The culprit is usually Notion’s API rate limit, and it’s stricter than most solo operators realize.

    What Notion actually throttles

    Notion’s public API enforces a hard limit of 3 requests per second per integration. That sounds generous until you understand what counts as a request.

    Every time your automation reads a database, updates a page property, appends a block, or queries a filtered view, that’s one request. If you’re syncing a content calendar with 20 rows, updating each row’s status, and logging a timestamp, you’ve just burned through 60 requests in under a second—triggering a 20-second cooldown.

    The API returns a 429 status code when you hit the limit, but most no-code tools don’t surface that error clearly. Zapier marks the task as successful. Make shows a generic timeout. Your data just doesn’t update.

    Notion also enforces a secondary limit: 1,000 requests per 5 minutes per workspace. That’s the one that breaks bulk imports, CSV syncs, and any automation that loops through more than a few dozen records at once.

    Where rate limits break your workflow

    The most common failure point is multi-step Zaps or Make scenarios that chain database reads. Let’s say you’re running a weekly automation that:

    • Fetches all published posts from a Notion database
    • Checks each post’s performance in an analytics tool
    • Writes the traffic number back to Notion

    If you have 15 posts, that’s 15 read requests, 15 API calls to your analytics tool, and 15 write requests back to Notion—45 total requests to Notion in under 10 seconds. You’ll hit the rate limit on request 30, and the remaining 15 posts won’t update.

    Another common break: real-time syncs. If you’re using Notion as a CRM and updating deal stages every time a lead replies, you’ll trip the limit during high-volume days. A burst of 10 inbound emails in 3 seconds means 10 Notion writes—well over the 3-per-second threshold.

    How to route around the limit without rewriting everything

    The simplest fix is to add delays. In Zapier, insert a 400-millisecond delay step between each Notion action. In Make, set your iterator to process one record every 350 milliseconds. That keeps you under 3 requests per second with a small buffer for API jitter.

    For bulk operations, batch your updates. Instead of updating 50 Notion rows one at a time, collect the changes in an array, then write them in chunks of 10 with 4-second pauses between chunks. Make handles this better than Zapier—its Array Aggregator and Sleep modules make batching straightforward.

    If you’re syncing data that doesn’t need to be real-time, switch to scheduled runs. A Zap that runs every 15 minutes instead of on every trigger gives Notion’s rate limit time to reset between batches. You lose immediacy, but you gain reliability.

    For high-volume workflows, consider using Notion as a read-only dashboard and writing updates to Airtable or Google Sheets first. Both have more forgiving API limits (Airtable allows 5 requests per second; Google Sheets is effectively unlimited for small operators). You can still display the data in Notion by embedding a synced view, but the write-heavy work happens elsewhere.

    When to skip Notion entirely

    If your workflow requires more than 100 Notion updates per hour, you’re fighting the platform. Notion’s API is built for lightweight integrations—pulling a task list into Slack, logging form submissions, syncing a handful of records. It’s not designed to be a transactional database.

    For high-frequency writes—CRM activity logs, real-time inventory updates, live analytics dashboards—use a tool with a higher rate ceiling. Airtable, Baserow, or even a simple PostgreSQL instance on a $6/month DigitalOcean droplet will handle the load without throttling.

    Notion still works well as the interface for that data. You can run a nightly sync from your transactional database into Notion, giving you the clean UX for planning and review without the API bottleneck during live operations.

    If you’re running into silent automation failures and can’t figure out why, check your Notion request volume first. Add delays, batch your updates, or move the write-heavy work to a tool that won’t throttle you at 3 requests per second. Your automations will thank you.

    Hit reply if you’ve found a cleaner workaround—I’d love to hear how you’re handling this.