Author: onetwothreeadmin

  • AI writing assistants lose your brand voice after 10,000 words

    AI writing assistants lose your brand voice after 10,000 words

    You feed Claude or ChatGPT your style guide, brand voice doc, and three sample articles. The first draft comes back clean. The fifth is still coherent. By draft twelve, you’re rewriting entire sections because the output sounds like a SaaS landing page written by committee.

    The problem isn’t the model. It’s context decay—and most solo operators don’t notice it until they’re deep into a content sprint.

    How context windows actually behave in production

    Modern AI assistants advertise context windows between 100,000 and 200,000 tokens. That sounds massive. In practice, a 2,000-word article with formatting consumes roughly 3,000 tokens. A detailed style guide adds another 1,500. Add three reference articles, a content brief, and iterative edits, and you’re at 15,000 tokens before you hit “generate.”

    The issue isn’t hitting the hard limit. It’s recency bias. AI models weight recent inputs more heavily than older ones. Your brand voice document, uploaded at the start of the session, fades in influence as the conversation grows. By message twenty, the model is prioritizing your last three corrections over the foundational voice rules you set up front.

    This isn’t speculation. Run the same prompt in a fresh session and in a thread with fifteen prior exchanges. The tone, sentence structure, and word choice drift measurably. The fresh session respects your style guide. The deep thread defaults to generic clarity.

    Where the breakdown happens

    Three scenarios accelerate context decay:

    Iterative editing. You ask for a rewrite of paragraph four. Then paragraph seven. Then a punchier intro. Each edit adds tokens. The model starts optimizing for your edits rather than your original brief. If your edits are vague (“make it snappier”), the output drifts toward the model’s base training—usually bland, corporate prose.

    Multi-article sessions. You’re batching content. Article one turns out great. Article two is fine. Article three reads like it was written by a different person. The model is still referencing article one’s context, but it’s now buried under 20,000 tokens of intermediate work. Your style guide is functionally invisible.

    Supplemental instructions mid-thread. You realize the model isn’t using contractions, so you add a note: “Use contractions. Write like a person.” That instruction applies to the current output, but it doesn’t retroactively fix the earlier drift. Worse, it competes with your original style guide, which may have said something more nuanced.

    How to architect around it

    The fix isn’t to abandon AI writing tools. It’s to structure your workflow so the model never has to remember too much at once.

    Start fresh for each piece. Don’t reuse threads across articles. A new session costs you thirty seconds of setup but guarantees your brand voice sits at the top of the context stack. If you’re batching content, open a new chat per article. Yes, you’ll paste your style guide multiple times. That redundancy is weight, not waste.

    Anchor instructions at both ends. Put your core voice rules in the first message and repeat the two most important points in your content brief. Example: if your style guide says “no jargon” and “lead with specifics,” embed those phrases in the article prompt itself. Repetition reinforces priority in the model’s attention mechanism.

    Use system prompts where available. Claude lets you set a system prompt that persists across a conversation. ChatGPT offers custom instructions. Both sit outside the regular context window and don’t decay. Load your brand voice there. Keep it under 300 words—short, imperative statements work better than discursive guidelines.

    Separate editing from generation. If you’re deep into revisions and the tone starts slipping, don’t keep editing in the same thread. Copy the draft into a fresh session, paste your style guide, and ask for a single-pass cleanup. The model will treat your draft as raw input and apply the voice rules uniformly, rather than layering fixes onto fixes.

    What this means for content operations

    If you’re publishing once a week, context decay is invisible. If you’re running a content engine—daily newsletters, multi-author blogs, high-volume SEO plays—it’s the difference between consistent voice and a patchwork of tones.

    The operators who scale AI writing successfully treat it like a stateless function. Each invocation gets the same inputs. No conversation persists long enough to drift. Workflows that rely on “the model will remember” break at volume.

    Track this in your own work. Open your last five AI-generated drafts. Read them in sequence. If draft five sounds meaningfully different from draft one—and you didn’t change your instructions—you’re watching context decay in action.

    One Two Three Send covers the tools and workflows that power solo operations. If you’re running content at scale, subscribe for weekly breakdowns of what works, what breaks, and what costs you time when no one’s watching.

    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.

  • Traffic attribution breaks when you rely on a single UTM parameter

    Traffic attribution breaks when you rely on a single UTM parameter

    You slap a ?utm_source=twitter on a link, post it, and watch Google Analytics log the visits. Job done. Except when you want to know which tweet drove traffic, or whether the thread performed better than the standalone post, you’re looking at an aggregate number that tells you nothing.

    Single-parameter UTM tagging is the norm because it’s fast. But it collapses every variation of a campaign into one bucket. When you run the same link across multiple posts, test different copy, or repost content weeks later, you lose the ability to see what actually worked.

    Why one parameter isn’t enough

    UTM parameters exist in sets: source, medium, campaign, term, and content. Most operators use only source, sometimes medium. That’s enough to tell you traffic came from Twitter or your newsletter, but it won’t help you answer:

    • Did the morning post outperform the evening one?
    • Which subject line variation drove more clicks?
    • Is this week’s guest post pulling better than last month’s?

    Without campaign and content tags, you’re aggregating everything from a source into one line item. If you’re running any kind of test—creative, timing, format—you’re flying blind.

    What to track in each parameter

    Here’s a structure that scales without getting obsessive:

    utm_source: The platform. twitter, linkedin, newsletter, reddit. Keep it consistent. Don’t use Twitter one week and twitter the next—analytics tools are case-sensitive and will split them into separate sources.

    utm_medium: The format or channel type. social, email, paid, organic. This groups sources into broader buckets and makes cross-channel comparisons possible.

    utm_campaign: The specific push or theme. product-launch-june, weekly-roundup-24, black-friday-2026. This is your container for everything related to one coordinated effort.

    utm_content: The variable you’re testing or the specific placement. thread-version-a, header-link, ps-cta. This is where you differentiate two posts in the same campaign.

    Example: You’re running a product launch. You post on Twitter three times over two days—morning thread, afternoon standalone, evening reply-guy style. Tag them:

    • ?utm_source=twitter&utm_medium=social&utm_campaign=product-launch-june&utm_content=morning-thread
    • ?utm_source=twitter&utm_medium=social&utm_campaign=product-launch-june&utm_content=afternoon-standalone
    • ?utm_source=twitter&utm_medium=social&utm_campaign=product-launch-june&utm_content=evening-reply

    Now your analytics show not just that Twitter drove 150 visits, but that the morning thread drove 90, the afternoon post drove 40, and the evening reply drove 20. You know what to repeat.

    Common mistakes that break tracking

    Inconsistent naming. utm_source=Twitter and utm_source=twitter appear as two separate sources. Pick lowercase-with-hyphens and stick to it. Same goes for campaigns: launch_june and launch-june are different.

    Overloading utm_content. Don’t stuff timestamps, user IDs, or session tokens into this field. It’s for human-readable variants, not programmatic tracking. If you need per-user attribution, use a separate query parameter and log it server-side.

    Tagging internal links. Don’t add UTM parameters to links between pages on your own site unless you’re running a specific cross-domain campaign. It resets the session and attributes internal navigation as a new traffic source, which destroys your funnel data.

    Not documenting your taxonomy. Six months from now, you won’t remember whether utm_campaign=june-launch or utm_campaign=product-launch-june was the one you used. Keep a spreadsheet or a Notion page with every active campaign and its naming convention.

    When to simplify

    If you’re posting a link once and never again, a single utm_source is fine. If you’re sharing a static resource—like a media kit or a one-time freebie—you don’t need campaign-level granularity.

    But the moment you’re testing anything—post timing, copy, format, audience segment—you need at least three parameters: source, campaign, and content.

    Traffic attribution only works when you can compare apples to apples. A single UTM parameter turns every variation into the same apple. Add two more, and you’ll finally see what’s working.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools and tactics that actually move the needle for solo operators.

  • LinkedIn newsletters: when to publish there vs. your own list

    LinkedIn newsletters: when to publish there vs. your own list

    LinkedIn launched native newsletters in 2021, and they’ve quietly become one of the better ways to grow a professional audience without paying for ads. But they’re not a replacement for an owned email list—they’re a different tool with different trade-offs.

    If you’re running a content business, you probably need both. The question is which one gets your best material, and when you should cross-post versus publish exclusive content on each platform.

    How LinkedIn newsletters actually work

    A LinkedIn newsletter is a recurring publication tied to your personal profile or company page. When you publish an issue, LinkedIn notifies subscribers and pushes it into the algorithmic feed for non-subscribers who follow related topics.

    That second part is the big difference. A traditional email newsletter only reaches people who opted in. A LinkedIn newsletter can reach tens of thousands of impressions on the first issue if LinkedIn’s algorithm decides your topic has momentum.

    Subscribers get an email notification (from LinkedIn, not you) and a bell icon alert. You don’t own the email addresses. You can’t export them. You can’t segment, tag, or automate follow-ups. LinkedIn owns the relationship.

    Publishing cadence matters more here than on a self-hosted list. LinkedIn rewards consistency—weekly or biweekly posts perform better than monthly because the algorithm favors active publishers. Miss three weeks and your next issue will get buried.

    When LinkedIn newsletters win

    If you’re starting from zero and need fast traction in a B2B niche, LinkedIn newsletters are hard to beat. You can get your first 500 subscribers in a month without spending a dollar, especially if you’re writing about SaaS, freelancing, recruiting, or professional development.

    The platform is also ideal for reach-focused content that doesn’t require a hard conversion. Thought leadership posts, contrarian takes, and industry commentary all perform well because LinkedIn’s feed amplifies debate and engagement.

    One operator I know runs a DevOps newsletter entirely on LinkedIn. He hit 12,000 subscribers in six months, gets 40–60 comments per issue, and converts readers into consulting clients through DMs. He’s never sent a traditional email newsletter and doesn’t plan to.

    His model works because his business relies on visibility and inbound leads, not product sales or affiliate revenue. LinkedIn’s algorithm does the distribution work for him.

    When your own list wins

    If you’re monetizing through sponsorships, affiliate links, paid subscriptions, or product launches, you need an owned list. LinkedIn doesn’t let you run third-party ads in newsletters, and their affiliate link policies are murky at best.

    You also can’t A/B test subject lines, track click-through rates by segment, or automate a welcome sequence. LinkedIn’s analytics show opens, clicks, and basic demographics, but you can’t funnel readers into a product waitlist or tag them based on behavior.

    Control matters more as your business matures. Platforms change policies, shut down features, or deprioritize content types without warning. In 2023, LinkedIn throttled newsletter reach for accounts that cross-posted identical content from Substack or Beehiiv. The algo spotted duplicate intros and punished them.

    If your revenue depends on email, you can’t afford that risk. One algorithm shift shouldn’t kill your income.

    The hybrid approach that works

    Most operators I know who do this well publish different content on each platform. LinkedIn gets the high-level, debate-worthy stuff—opinion pieces, trend commentary, and open-ended questions. The owned list gets tactical how-tos, product updates, and anything with a monetization angle.

    You can also use LinkedIn as a top-of-funnel tool. Publish a condensed version of your best content there, then link to the full piece on your site or in your email archive. Include a low-friction CTA at the end: “I send a deeper dive every Thursday—join 3,200 operators here.” Link to your signup page.

    That approach works because LinkedIn subscribers are already in consumption mode. They’re not cold traffic. A 2–5% conversion rate from LinkedIn newsletter subscriber to owned-list subscriber is realistic if your CTA is clear and the value proposition is obvious.

    One workflow: write your main newsletter issue in Beehiiv or MailerLite, pull the intro and one key section, rewrite it for LinkedIn’s feed tone (more casual, more debate-friendly), publish it as a LinkedIn newsletter, and link back to the full version. Track conversions in your email platform to see if the crossover is worth the extra 20 minutes per week.

    Don’t post identical content on both. LinkedIn’s algorithm will bury it, and your email subscribers will feel like they’re reading reruns.

    Want to compare email platforms for your owned list? We covered ConvertKit vs. Beehiiv vs. Substack in detail last week, including pricing breakpoints and feature gaps that matter for monetization.

    Platform lock-in is real

    The biggest long-term risk with LinkedIn newsletters is that you’re building on rented land. LinkedIn could sunset the feature, change the notification system, or require a paid tier to reach your own subscribers. It’s happened before on other platforms.

    If LinkedIn newsletters are your primary audience channel, set a reminder every quarter to test a migration offer. Send one issue with a clear ask: “I’m testing a standalone email list—if you want these posts delivered outside LinkedIn, sign up here.” Track how many people convert. If it’s under 1%, you’re locked in. If it’s over 5%, you have options.

    The goal isn’t to abandon LinkedIn—it’s to make sure you’re not hostage to it.

    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.

  • MailerLite’s Auto-Resend Feature: How It Works and When to Use It

    MailerLite’s Auto-Resend Feature: How It Works and When to Use It

    MailerLite offers a feature most solo operators ignore: auto-resend to non-openers. You send a campaign, wait a set number of days, then MailerLite automatically resends the same email to everyone who didn’t open it the first time—with a new subject line you provide.

    It sounds like free engagement. Sometimes it is. Sometimes it’s a waste of deliverability budget. Here’s how to know the difference.

    How Auto-Resend Works

    When you schedule or send a campaign in MailerLite, you’ll see a checkbox: “Resend this campaign to non-openers.” Enable it, and you choose:

    • How many days to wait before resending (minimum 1 day, maximum 10)
    • A new subject line for the resend
    • Whether to resend to people who didn’t open or didn’t click (two separate filters)

    MailerLite tracks opens via a 1×1 pixel embedded in the email. If that pixel doesn’t load within your wait window, the subscriber gets the resend. The body content stays identical; only the subject line changes.

    The feature is available on all MailerLite plans, including the free tier (up to 1,000 subscribers and 12,000 emails per month). No extra charge per resend—it just counts against your monthly send quota.

    When Auto-Resend Actually Works

    This feature pays off in three scenarios:

    Time-sensitive content with a narrow window. If you’re promoting a webinar, sale, or limited offer, a resend 2–3 days before the deadline can recover 8–15% additional opens. The urgency justifies the repeat send, and the new subject line can emphasize scarcity (“Last chance” vs. your original angle).

    Evergreen content you’re confident in. If your original open rate was below 30% and you believe the content itself is strong—tutorial, case study, resource roundup—a resend with a clearer or more specific subject line often pulls another 5–10% open rate. You’re not pestering; you’re giving the email a second chance to surface in a cleaner inbox.

    Large lists with inconsistent engagement. If you have 5,000+ subscribers and your median open rate sits around 25–35%, auto-resend becomes a volume play. Even a modest 8% lift on the resend adds hundreds of opens you wouldn’t have captured otherwise, and the deliverability risk is minimal if your sender reputation is healthy.

    When to Skip It

    Auto-resend backfires when:

    Your original subject line wasn’t the problem. If your open rate is consistently above 40%, the issue isn’t visibility—it’s relevance or timing. Resending won’t fix that. You’ll just train subscribers to expect duplicates and ignore both.

    You send frequently. If you publish three or more emails per week, a resend starts to feel like spam. Subscribers who didn’t open the first time likely weren’t interested, and showing up again 48 hours later erodes trust faster than it recovers engagement.

    You’re resending promotional content repeatedly. If every sales email gets auto-resent, subscribers notice the pattern. It signals desperation, and it trains them to wait for the resend (or unsubscribe). Reserve auto-resend for your strongest content, not every broadcast.

    One Non-Obvious Tip

    Most operators test two subject lines by running A/B splits on the initial send, then using the winner for the resend. Flip that logic.

    Send your safer, clearer subject line first—the one that accurately describes what’s inside. Then use the resend to test a riskier, more curiosity-driven or emotional angle. If it flops, you’ve only burned the non-openers. If it works, you’ve discovered a subject-line style that breaks through inbox noise, and you can apply that learning to future campaigns.

    This approach also avoids the common mistake of making the resend subject line worse than the original. I’ve seen operators rewrite a specific, compelling subject into a vague one just to make it “different.” The resend open rate craters, and they blame the feature instead of the execution.

    MailerLite’s auto-resend costs you nothing but send volume. If you’re already paying for a plan and sitting below your monthly limit, the feature is pure upside—as long as you use it strategically, not reflexively. Test it on one high-value campaign, measure the lift, and decide from there.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep-dives on the tools and tactics that actually move the needle for solo operators.

  • Analytics dashboards hide more than they reveal

    Analytics dashboards hide more than they reveal

    Open Google Analytics, Plausible, or Fathom right now. You’ll see pageviews, sessions, bounce rate, referrers. Clean charts. Tidy numbers. Everything you need to know about your traffic.

    Except you’re looking at a summary of a summary of a summary. The dashboard is a lossy compression algorithm designed to make patterns visible—and in doing so, it hides the outliers, the edge cases, and the signal buried in the noise.

    If you’re running a content business, those hidden details are where the decisions live.

    What the default view doesn’t show you

    Most analytics dashboards aggregate by default. They show you total sessions, average time on page, top landing pages. That’s fine for a monthly report, but it flattens the distribution.

    Here’s what vanishes:

    • Single-page sessions that converted. A reader lands on your pricing page, scrolls to the bottom, clicks “subscribe,” and leaves. Bounce rate: 100%. Value: high. The dashboard flags it as a failure.
    • Referrer context beyond the domain. You see “twitter.com” in your referrer log. You don’t see which tweet, which reply thread, or whether it came from a quote-tweet with 800 impressions or a reply buried three levels deep.
    • Time-on-page outliers. Your median time on page is 1:20. One reader spent 22 minutes. Another spent four seconds. The average says nothing about either.
    • Entry and exit paths that don’t follow your funnel. You assume readers land on your homepage, browse, then subscribe. Half of them land on a three-year-old post, read two paragraphs, and subscribe from the inline CTA. Your dashboard doesn’t highlight that path unless you go looking.

    Default dashboards are built for SaaS companies with linear funnels. Content businesses don’t have linear funnels. Readers enter from anywhere, stay as long as they want, and convert when something clicks. The dashboard doesn’t map that.

    The data you need to export manually

    If you want to see what’s actually happening, you need to pull raw session logs or build custom reports. Here’s what to look for:

    Session duration distribution, not average. Export time-on-site data and chart it as a histogram. You’ll see three clusters: under ten seconds (accidental clicks or bots), 30 seconds to two minutes (skimmers), and five minutes-plus (engaged readers). The third group is your real audience. The dashboard average blends all three into a number that describes no one.

    Conversion paths, not just conversion rate. Most analytics tools let you build a funnel report. Set it to show all paths, not just the primary one. You’ll find readers who convert after visiting your about page, your uses page, and a random blog post from 2023. That’s not a broken funnel—it’s how trust builds in a content business.

    Referrer URLs, not referrer domains. If you’re using GA4, enable the full referrer URL in your data stream settings. If you’re using Plausible or Fathom, export your referrer data and sort by frequency. You’ll see which specific tweets, Reddit threads, or Hacker News comments are sending traffic. That tells you what to do more of.

    Exit pages for engaged sessions only. Filter your exit-page report to sessions longer than two minutes. You’ll see where your best readers leave. If they’re exiting from your pricing page, your CTA might be unclear. If they’re exiting from a post with no CTA, you’re leaving conversions on the table.

    When to ignore the dashboard entirely

    Sometimes the dashboard is wrong in a way that matters.

    If you’re running a small operation—under 10,000 sessions a month—your sample size is too small for statistical patterns to emerge. A single Reddit post can double your traffic for a day and skew your monthly average. The dashboard will show a spike, then a drop, and suggest you’re losing momentum. You’re not. You just had one good day.

    If you’re publishing sporadically, your traffic will look like a sawtooth. The dashboard will show declining engagement because it assumes consistent output. It doesn’t know you took two weeks off.

    If you’re testing a new traffic channel—say, you’re experimenting with Pinterest or Threads—the dashboard will bury it under “other” until it hits 5% of total traffic. You won’t see early traction unless you filter for it.

    In all three cases, the dashboard is technically accurate. It’s just not useful.

    What to do instead

    Set up three custom reports and review them monthly:

    • A session-duration histogram, filtered to organic and referral traffic only.
    • A conversion-path report showing all routes to subscription, not just the top funnel.
    • A referrer-URL export, sorted by engaged sessions (two minutes or longer).

    These three views will tell you more about your audience than any pre-built dashboard. They take ten minutes to set up and five minutes to review. The insight-to-effort ratio is better than anything else in your analytics stack.

    Want more breakdowns like this? Subscribe to One Two Three Send for weekly deep dives on the tools and tactics that actually move the needle for solo operators.

  • WordPress multisite migration: what breaks and what doesn’t

    WordPress multisite migration isn’t the same as moving a single-site install. The network architecture means your database holds cross-site references, your media library spans domains, and your DNS has to route traffic through the primary domain before handing off to subsites.

    If you’ve ever moved a multisite network to a new host and watched half your images vanish or login redirects break, you know the pain. Here’s what actually breaks, what survives the move, and how to fix the common failure points before they cost you traffic.

    URL mappings break first

    Multisite stores site URLs in wp_blogs and wp_site tables. When you migrate, your old domain references stay hardcoded unless you run a search-and-replace across the network database.

    If you’re running subdomain multisite (like site1.yourdomain.com), every subsite has its own domain entry in wp_blogs. A standard WP migration plugin won’t catch these—it only updates siteurl and home in wp_options for the primary site.

    Run a network-wide search-and-replace using WP-CLI’s search-replace command with the --network flag, or use a plugin like Better Search Replace in network mode. Target the old domain string and replace it with the new one across all tables. Don’t skip serialized data—WordPress stores arrays and objects in the database, and a partial string replacement corrupts them.

    Media library paths don’t update automatically

    Multisite stores uploaded files in /wp-content/uploads/sites/{site_id}/ directories. When you migrate, the files move with the server, but image URLs in post content and media library metadata still point to the old domain.

    Your search-and-replace will catch most of these if you’re thorough. But if you’re moving from HTTP to HTTPS, or changing the subdirectory path (like moving from /blog/ to root), you’ll have orphaned image references that don’t render.

    Check wp_posts.guid and wp_postmeta for _wp_attached_file and _wp_attachment_metadata keys. These hold the full image paths and need manual correction if your directory structure changed. A broken guid won’t stop images from displaying, but it will break media library searches and attachment page URLs.

    Subdomain DNS has to route through the primary domain

    If you’re running subdomain multisite, your DNS needs a wildcard A record pointing *.yourdomain.com to your server IP. When you migrate hosts, that wildcard has to update to the new IP—and if your DNS propagation is slow, subsites will be unreachable even after the primary domain resolves.

    Check your DNS panel and confirm the wildcard record exists and points to the correct IP. If you’re using Cloudflare or another proxy, make sure the wildcard is set to DNS only (gray cloud) during migration, not Proxied (orange cloud). Proxied wildcard records can break subsite routing if the SSL certificate doesn’t cover all subdomains.

    If you’re moving to a managed WordPress host like BigScoots, ask support whether they handle wildcard DNS automatically. Some hosts provision it; others require manual setup.

    Plugin network activation states don’t transfer cleanly

    Multisite lets you activate plugins network-wide or per-site. When you migrate, the wp_sitemeta table holds network activation data, and wp_{site_id}_options tables hold per-site activation.

    If you’re moving between hosts with different PHP versions or server configurations, plugins that worked network-wide on the old host may fail silently on the new one. Check the active_sitewide_plugins key in wp_sitemeta after migration and deactivate any plugins that throw errors in the WordPress admin.

    Some plugins—especially caching and security plugins—store server paths in their settings. If your new host uses a different document root (like /var/www/html/ instead of /home/username/public_html/), those plugins will break until you regenerate their config files.

    What actually survives the move

    Your post content, user accounts, and plugin settings all migrate cleanly if you’re using a proper database export. The wp_users and wp_usermeta tables are network-global, so user logins work across all subsites immediately after the move.

    Theme files and uploads transfer intact if you copy the entire /wp-content/ directory. Just make sure file permissions are set correctly on the new host—644 for files, 755 for directories. If your new host uses a different user/group (like www-data instead of nobody), you’ll need to chown the files or uploads will fail.

    Test before you flip DNS

    Before you point your domain to the new host, test the migration using your server’s temporary URL or by editing your local /etc/hosts file to map your domain to the new IP.

    Log in to the network admin, visit a few subsites, upload a test image, and check whether plugins activate correctly. If anything breaks, you can fix it without taking the live site offline.

    Once you’re confident, update your DNS A records, wait for propagation, and flush any page caches. Multisite migrations take longer than single-site moves, but if you catch the URL mappings, media paths, and DNS routing, the network will come up clean.

    Got a multisite migration story? Reply with what broke for you—we’ll cover edge cases in a future issue.

  • Social media automation rules throttle your best content

    Social media automation rules throttle your best content

    Most social media schedulers let you build automation rules: post every blog article to Twitter, share Instagram posts to Facebook, cross-post YouTube videos to LinkedIn. The logic seems bulletproof—maximize reach, minimize manual work.

    But automation rules trip over platform rate limits and duplicate-content filters more often than solo operators realize. The result: your best content gets delayed, hidden, or flagged as spam, and you don’t find out until days later when the numbers don’t add up.

    Platform rate limits don’t care about your publishing calendar

    Twitter’s API allows 300 posts per three-hour window for standard access. LinkedIn throttles at roughly 100 posts per day across all company pages tied to your account. Instagram’s Graph API lets you publish 25 posts per user per day, but Stories and Reels share that quota.

    When you stack automation rules—new blog post triggers Twitter thread, Facebook post, and LinkedIn article—you can hit daily limits faster than expected if you’re also manually posting, replying, or running other integrations. Schedulers like Buffer and Hootsuite queue posts when limits are reached, but they don’t always surface the delay prominently. You think a post went live at 9 a.m.; it actually published at 4 p.m. after the API window reset.

    Publer surfaces rate-limit warnings in its activity log, but you have to check the dashboard. Most operators don’t.

    Duplicate-content detection penalizes cross-posting

    Facebook and LinkedIn use content fingerprinting to detect duplicate posts across pages and profiles. If your automation rule posts identical text and images to your personal profile, company page, and group within minutes, the second and third instances get suppressed in the feed. Engagement drops to near zero, and the algorithm interprets that as a signal to deprioritize future posts.

    Instagram’s duplicate filter works differently—it doesn’t block the post, but it won’t surface it in Explore or hashtag feeds. You’ll see normal reach among existing followers, but discovery traffic flatlines.

    The fix isn’t to disable automation entirely. It’s to add variation. Change the caption, swap the image crop, or stagger publish times by at least two hours. Some schedulers let you define per-network caption templates; others require manual edits before each cross-post. Neither is automatic anymore, which defeats the original promise.

    High-velocity posting triggers spam filters

    Twitter’s spam-detection system flags accounts that post more than 20 times per hour, even if you’re within the API rate limit. The account doesn’t get suspended immediately—tweets just stop appearing in follower timelines. You’ll notice a sudden drop in impressions and replies, but Twitter doesn’t send a notification.

    LinkedIn’s spam filter is less aggressive but more opaque. Posting identical links across multiple profiles or pages within a short window can trigger a temporary reach reduction that lasts 48 to 72 hours. The post stays live, but LinkedIn stops recommending it beyond first-degree connections.

    If you’re running automation rules that trigger on RSS feeds or Zapier webhooks, a single burst of new content—say, publishing five blog posts in one morning—can trip these filters before you realize what’s happening.

    What to do instead

    First, audit your existing automation rules. Log into your scheduler and list every active trigger. Count how many posts each rule could generate in a 24-hour period if all your content sources published at once. Compare that total against platform rate limits.

    Second, add random delays between cross-posts. Most schedulers support a “randomize publish time within X minutes” setting. Set it to at least 30 minutes for major platforms, two hours if you’re cross-posting identical content.

    Third, write platform-specific captions for any post you expect to perform well. Automation works for low-stakes updates—new podcast episode, weekly roundup—but high-value content deserves custom framing for each network’s audience and format norms.

    Fourth, monitor your scheduler’s activity log weekly. Look for posts marked “queued,” “delayed,” or “failed.” If you see patterns—say, LinkedIn posts always queue on Tuesdays—you’re hitting a limit or filter you didn’t account for.

    Finally, accept that full automation doesn’t scale past a certain content velocity. If you’re publishing more than ten pieces of content per week across multiple platforms, manual scheduling with templates will outperform rigid automation rules. The time you save upfront gets eaten by troubleshooting suppressed posts and diagnosing reach drops.

    One Two Three Send covers social media strategy, newsletter tools, and workflow automation for solo operators. Subscribe to get one focused article like this in your inbox twice a week—no fluff, just the mechanics that matter.

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

  • AI token counters lie—here’s how to bill clients accurately

    AI token counters lie—here’s how to bill clients accurately

    If you bill clients for AI-assisted work—copywriting, image generation, data extraction—you’ve probably noticed that the token count in your API dashboard doesn’t match the estimate your prompt tool gave you. Sometimes the difference is negligible. Other times it’s 20% or more, and you’re left trying to explain why the invoice doesn’t match the quote.

    Token counting isn’t standardized across models, and the tools we use to estimate cost rarely account for the invisible overhead that APIs add. Here’s what’s actually happening, and how to track usage in a way that holds up when a client asks questions.

    Why token counts don’t match between tools

    Most AI token counters—like the estimators built into prompt libraries or third-party calculators—use open-source tokenizers that approximate how a model splits text. OpenAI’s tiktoken library is the most common. It’s accurate for GPT-3.5 and GPT-4, but it doesn’t account for function calling, system messages, or the formatting overhead that APIs inject when you use features like JSON mode or structured outputs.

    Anthropic’s Claude models use a different tokenizer entirely. If you’re using a calculator built for OpenAI and then running prompts through Claude, your estimate can be off by 15–30%. The variance gets worse with non-English text, code blocks, or anything that includes special characters.

    Then there’s the API wrapper problem. If you’re using a tool like LangChain, Make, or Zapier to call an AI model, the platform often adds its own metadata—timestamps, user IDs, retry logic—that inflates token usage without appearing in your prompt preview.

    What your API dashboard is actually counting

    Your API provider’s usage dashboard is the source of truth, but it’s counting more than you think. Every API call includes:

    • System messages that set model behavior (e.g., “You are a helpful assistant”).
    • Function definitions if you’re using tools or structured outputs.
    • Conversation history if you’re maintaining context across multiple turns.
    • Formatting tokens for JSON mode, which adds schema instructions behind the scenes.

    A 500-token prompt can easily become 650 tokens by the time it hits the API. If you quoted a client based on the prompt alone, you’re eating the difference.

    OpenAI’s API returns token counts in the response object (usage.prompt_tokens and usage.completion_tokens), so you can log the actual cost per call. Anthropic does the same in the usage field. If you’re not capturing that data, you’re guessing.

    How to track usage without undercharging

    The simplest fix: log every API response and pull token counts directly from the provider. If you’re using Python, store the usage object in a CSV or database after each call. If you’re using a no-code tool like Make or Zapier, add a step that writes the token count to a Google Sheet or Airtable base.

    For client work, I run a weekly script that sums token usage by project tag and multiplies by the current API rate (OpenAI charges $0.01 per 1K prompt tokens and $0.03 per 1K completion tokens for GPT-4). That number goes into the invoice as a line item, and I attach a CSV export if the client asks for proof.

    If you’re quoting a fixed price, pad your estimate by 25% to cover system message overhead, retries, and any follow-up calls the client requests mid-project. Estimators are useful for ballpark numbers, but they shouldn’t be the final quote.

    When flat-rate pricing beats usage tracking

    Some operators skip per-token billing entirely and charge a flat rate per deliverable—$200 for a landing page, $500 for a lead magnet, regardless of how many API calls it takes. This works if you’re confident in your workflow and don’t want to explain token math to every client.

    The tradeoff: you absorb cost volatility. If a client requests three rounds of revisions, you’re paying for the extra tokens. If you’re using a model like GPT-4 or Claude Opus, a single long-context project can cost $15–$30 in API fees. Flat pricing makes sense when your process is repeatable and your margins are wide enough to cover outliers.

    For subscription clients—content retainers, weekly reports—I set a token budget per month (e.g., 100K tokens) and log usage in a shared dashboard. If they go over, the next invoice includes an overage charge at $0.02 per 1K tokens. That rate is higher than my cost, but it discourages scope creep and keeps the math transparent.

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

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

  • Stripe checkout sessions expire after 24 hours—here’s why

    Stripe checkout sessions expire after 24 hours—here’s why

    If you’ve ever sent someone a Stripe checkout link and had them come back a day later saying it doesn’t work, you’ve run into session expiration. Stripe Checkout sessions expire exactly 24 hours after creation, and there’s no setting to extend that window.

    This isn’t a bug. It’s a deliberate design choice that affects how you structure payment flows, follow-up sequences, and cart abandonment recovery. Here’s what the 24-hour limit actually does, when it becomes a problem, and how to work around it.

    What happens when a checkout session expires

    When you create a Stripe Checkout session via API or no-code tool, Stripe generates a unique URL. That URL is valid for 24 hours from the moment of creation—not from the moment someone opens it.

    After 24 hours, the link returns a “This Checkout Session has expired” error. The customer can’t complete payment. You don’t get notified. The session just stops working.

    This matters most when you’re pre-generating checkout links in automated emails, Slack messages, or scheduled posts. If someone receives your email at 9 a.m. Monday and clicks at 10 a.m. Tuesday, the link is dead.

    Stripe’s expiration clock starts when the session is created, not when the email is opened or the link is clicked. That’s the key mistake: assuming the 24-hour window begins when the customer engages.

    Why Stripe enforces the 24-hour limit

    Stripe’s documentation doesn’t spell out the reasoning, but the expiration window serves two purposes: fraud mitigation and inventory accuracy.

    Payment sessions that stay open indefinitely create opportunities for replay attacks and price manipulation. If a checkout session for a $49 product remains valid for weeks, someone could exploit outdated pricing or coupon codes long after you’ve changed them.

    The 24-hour window also keeps your checkout flow aligned with real-time inventory, seat availability, or limited-time offers. If you’re selling a cohort-based course with 50 spots, a session created when 10 spots remain shouldn’t stay valid when the cohort fills two days later.

    For subscription products and digital goods with no inventory constraints, the expiration feels arbitrary. But Stripe’s Checkout API handles everything from physical products to event tickets, so the 24-hour rule applies universally.

    When expiration breaks your workflow

    The 24-hour limit causes problems in three common scenarios.

    Pre-scheduled email sequences. If you’re running a five-day email course that ends with a checkout link, and you generate all five sessions at once, the link in email five is already expired by the time it sends. You need to generate each session just before its corresponding email goes out.

    Abandoned cart recovery. Standard cart abandonment flows wait 24–72 hours before sending a reminder. If you generate the checkout session when someone first adds a product to their cart, the recovery email will contain a dead link. You’ll need to regenerate the session when the reminder triggers.

    Public checkout links in evergreen content. Embedding a Stripe Checkout URL in a blog post, help doc, or pinned social media post doesn’t work. The link dies within a day. You’ll need to use Stripe Payment Links (which don’t expire) or dynamically generate sessions when someone clicks.

    How to work around session expiration

    The cleanest solution is to generate checkout sessions on-demand, right when the customer needs them.

    If you’re using Zapier, delay the “Create Checkout Session” action until immediately before the email sends. Don’t create all sessions upfront. In a drip sequence, each email should trigger its own session creation step.

    For abandoned cart emails, store the product details (price ID, quantity, customer email) instead of the checkout URL. When the reminder triggers 48 hours later, generate a fresh session using those stored details.

    If you need a persistent checkout link—something you can post publicly or reuse across emails—use Stripe Payment Links instead of Checkout sessions. Payment Links don’t expire and support the same features (custom fields, tax calculation, subscription billing). The trade-off: you lose some advanced customisation options available in the Checkout API, like dynamic pricing or complex line-item logic.

    For high-touch sales where you’re sending invoices manually, Stripe Invoices are a better fit than Checkout. Invoices stay open until you close them or they’re 90 days past due, and customers can pay directly from the invoice page without a session.

    One non-obvious detail: Stripe’s expires_at parameter lets you set a shorter expiration window (as brief as 30 minutes), but you can’t extend it past 24 hours. If you’re running flash sales or time-sensitive offers, setting expires_at to match your sale deadline keeps pricing consistent and adds urgency. Just make sure your customers know the link has a ticking clock.

    If you’re building payment flows for courses, memberships, or digital products and need help choosing between Checkout sessions, Payment Links, and invoice-based billing, subscribe to One Two Three Send—we break down one tool decision like this every week.

  • SEO meta descriptions don’t improve rankings—here’s what they do

    Every SEO checklist tells you to write meta descriptions. Most don’t tell you why—or what happens when you skip them.

    Meta descriptions carry zero direct ranking weight in Google’s algorithm. They never have. Google confirmed this in 2009 and has repeated it since. If you’re optimizing them to rank higher, you’re spending time on the wrong lever.

    But they still matter. Here’s what meta descriptions actually control, when Google ignores them, and how to write ones that pull traffic without wasting your time.

    What meta descriptions actually control

    Meta descriptions influence click-through rate from search results. When your page appears in a SERP, Google often (but not always) displays your meta description as the snippet below the title. If that snippet is compelling, clear, and relevant to the query, more people click. If it’s generic or missing, fewer do.

    Higher CTR can indirectly improve rankings over time—Google interprets consistent clicks as a signal that your result satisfies the query. But the meta description itself isn’t a ranking factor. The behavior it triggers is.

    This matters because most operators treat meta descriptions like keyword fields. They stuff them with target terms, hoping for algorithmic credit. That doesn’t work. The person reading the SERP doesn’t care about your keyword density. They care whether your page answers their question.

    When Google ignores your meta description

    Google rewrites meta descriptions more than 60% of the time, according to studies by Ahrefs and Moz. It pulls snippets from your page content instead, based on what it thinks matches the query.

    This happens when:

    • Your meta description doesn’t match the searcher’s query closely enough
    • The description is too short (under ~50 characters) or too long (over ~160 characters)
    • Google finds a passage on your page that better answers the query
    • Your page ranks for a long-tail query you didn’t write the description for

    You can’t prevent rewrites entirely. But you can reduce them by writing descriptions that closely mirror your H1 and the primary intent of the page. If your meta description says one thing and your page delivers another, Google will ignore it and pull a snippet that matches.

    How to write meta descriptions that pull clicks

    Stop writing for the algorithm. Write for the person deciding whether to click.

    Good meta descriptions:

    • Match the search intent — If someone searches “how to export WordPress posts,” your description should promise exactly that, not a general guide to WordPress management
    • Front-load the value — Put the payoff in the first 120 characters, because mobile SERPs truncate after that
    • Include a clear outcome — “Learn how to configure cron jobs so background tasks don’t slow your site” beats “A guide to WordPress cron jobs”
    • Avoid duplication — Every page needs a unique description; if you copy-paste across pages, Google sees it as low-effort and ignores them

    You don’t need to stuff keywords. If your target keyword appears naturally in the description, fine. If it doesn’t, skip it. The keyword will be bolded in the SERP if it matches the query, whether it’s in your meta description or pulled from your body text.

    When to skip meta descriptions entirely

    If you’re running a content site with hundreds of posts, writing unique meta descriptions for every page is a time sink with diminishing returns. Prioritize:

    • Your homepage
    • Your highest-traffic landing pages (check Google Search Console)
    • Pages targeting commercial or high-intent keywords
    • Pages where you control the SERP narrative (product pages, sales pages)

    For everything else—blog archives, tag pages, low-traffic posts—let Google pull snippets from your content. If your first paragraph is clear and relevant, Google’s auto-generated snippet will often outperform a generic meta description you wrote in five seconds.

    One exception: if you’re using a page builder or your content starts with a hero image or embedded video, write a meta description anyway. Google can’t pull useful snippets from non-text elements, and you’ll end up with a blank or garbled snippet.

    Meta descriptions don’t rank your pages. But they do determine whether people click when your page does rank. Write them for humans, front-load the value, and skip them when your first paragraph already does the job.

    Want more clear-eyed breakdowns of what actually moves the needle in your online business? Subscribe to One Two Three Send and get one operator-focused article in your inbox every week—no fluff, no filler.