Author: onetwothreeadmin

  • ChatGPT’s Custom Instructions feature: what it actually remembers

    ChatGPT’s Custom Instructions feature: what it actually remembers

    ChatGPT's Custom Instructions feature: what it actually remembers
    Photo by Andrew Neel on Unsplash

    ChatGPT’s Custom Instructions feature lets you define persistent context that carries across every new chat. For solo operators running content calendars, client briefs, or repetitive workflows, it’s supposed to eliminate the copy-paste ritual of re-stating your role, audience, and formatting preferences every single time.

    In practice, it works—but only within specific boundaries that aren’t surfaced in the UI. Understanding what the feature actually retains, when it gets overridden, and how token allocation works will determine whether it saves you time or quietly undermines your prompts.

    What Custom Instructions stores

    The feature splits into two text boxes: “What would you like ChatGPT to know about you?” and “How would you like ChatGPT to respond?” Each accepts up to 1,500 characters. That’s roughly 300–400 tokens, depending on vocabulary.

    The first box is for context: your role, business model, audience, constraints. The second is for output preferences: tone, structure, length, formatting rules.

    Both get prepended to every new conversation as invisible system-level instructions. They don’t appear in the chat transcript, but they consume part of the context window before your first user message even loads.

    This matters because ChatGPT-4’s context window is 8,192 tokens (standard) or 32,768 tokens (extended, via API or Plus with longer chats enabled). If your Custom Instructions use 400 tokens and your conversation history fills another 6,000, you’ve got roughly 1,800 tokens left for the next user prompt and model response combined. Long conversations will eventually push Custom Instructions out of active memory—the model still “sees” them in the system prompt, but prioritises recent turns.

    When instructions get ignored

    Custom Instructions apply to new chats only. If you edit them mid-conversation, the changes don’t retroactively alter the existing thread. Start a fresh chat to pick up the edits.

    They also don’t override explicit contradictions in your user prompt. If your Custom Instructions say “always respond in bullet points” but your message says “write this as a paragraph,” the user prompt wins. The model treats Custom Instructions as defaults, not mandates.

    This is useful when you need to temporarily deviate—run a one-off analysis in a different format—but it also means vague user prompts can dilute or ignore your standing instructions entirely. Specificity in the moment beats standing context.

    Finally, Custom Instructions don’t persist across different ChatGPT interfaces. They apply to the web UI and the iOS/Android apps, but not to API calls, plugins, or third-party wrappers. If you’re running ChatGPT via Zapier, Make, or a custom script, you’ll need to inject that context manually in each request.

    What to put in—and what to skip

    Effective Custom Instructions are narrow and structural, not aspirational. “I run a weekly newsletter about SaaS pricing for B2B founders” is useful. “I value creativity and outside-the-box thinking” is not—it’s too abstract to influence output in a measurable way.

    Good candidates for the context box:

    • Your primary business model and audience (e.g., “solo operator running a paid Substack on AI regulation”)
    • Constraints you apply consistently (e.g., “posts are 800 words, American English, no listicles”)
    • Tools or platforms you use regularly (e.g., “I use ConvertKit and WordPress, not Mailchimp or Wix”)
    • Terminology preferences (e.g., “call them ‘subscribers,’ not ‘users’”)

    Good candidates for the response box:

    • Structural defaults (e.g., “use H2 subheadings, no H3s”)
    • Tone boundaries (e.g., “conversational but not casual, no exclamation marks”)
    • Output length (e.g., “default to 600–800 words unless I specify otherwise”)
    • Formatting rules (e.g., “return HTML, not Markdown”)

    Skip anything that changes project-to-project. Don’t embed client names, specific article topics, or one-off formatting requests—those belong in the user prompt, not standing instructions.

    One non-obvious tip: version your instructions

    Custom Instructions have no built-in versioning or change log. If you tweak them and output quality shifts, you won’t have a record of what changed unless you save snapshots externally.

    Keep a simple text file or note with dated versions of your instructions. When you experiment—tightening tone, adding a structural rule, removing a constraint—log the edit and the date. If output degrades or drifts after a few weeks, you can diff versions and pinpoint what shifted.

    This is especially useful if you’re running ChatGPT in parallel with Claude or another model. Custom Instructions are ChatGPT-specific, but the principles transfer. A versioned reference file lets you port tested context patterns across tools without starting from scratch each time.

    If you’re using Custom Instructions already, reply and tell us what’s in yours—or what you’ve tried and removed. We’re cataloging what actually works for operators running content businesses, not just what the feature says it does.

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

  • Analytics pixel load order changes what conversion data you see

    Analytics pixel load order changes what conversion data you see

    Analytics pixel load order changes what conversion data you see

    Most solo operators install analytics pixels the same way: copy the snippet, paste it into a header tag manager or WordPress plugin, and move on. But the order those scripts execute changes which events get tracked, how sessions are attributed, and whether conversions appear at all.

    Load order isn’t a hosting quirk—it’s a silent filter on your data. When a payment confirmation fires before your analytics library finishes initializing, that conversion never gets logged. When a UTM parameter gets stripped by a redirect before your tracking pixel reads it, attribution breaks. And because these failures happen in milliseconds, you won’t notice until you’re reconciling Stripe revenue against reported conversions and the numbers don’t match.

    What happens when pixels fire out of sequence

    Most analytics platforms—Google Analytics 4, Plausible, Fathom, Mixpanel—need their base library loaded before any event tracking calls execute. If a custom event fires while the library is still downloading, it gets dropped. No error. No retry. The event just doesn’t exist in your dashboard.

    This happens most often on single-page apps, checkout flows, and any page where a conversion event fires on page load rather than user action. A typical failure case: you use a Zapier webhook to log a new subscriber in your CRM, and that webhook triggers a thank-you page redirect. If the redirect happens before GA4’s gtag('event', 'conversion') call completes, the conversion never reaches Google’s servers.

    Even when the base library loads in time, the order pixels fire relative to each other determines what data each one sees. If a Facebook Pixel fires before a UTM-stripping redirect, it captures source attribution. If it fires after, it logs the visit as direct traffic. Neither setup is “wrong”—but one gives you attribution data you can act on, and the other doesn’t.

    Where load order gets decided

    If you’re using a tag manager—Google Tag Manager, Matomo Tag Manager, or a WordPress plugin like Site Kit—load order is controlled by trigger rules and priority settings. Most operators leave these at default, which means tags fire in the sequence they were added. That’s fine until you add a new pixel six months later and it fires last, missing fast-loading events.

    GTM lets you set a “tag firing priority” number. Higher numbers fire first. If your GA4 base tag has priority 10 and a custom conversion event has priority 5, the event will try to fire before the library exists. Set the base tag to a higher number than any dependent event, and the problem goes away.

    In WordPress, most analytics plugins inject scripts into wp_head or wp_footer hooks. The order depends on plugin load sequence, which is alphabetical by folder name unless you force a specific order with a plugin like Code Snippets or a custom functions.php entry. If two plugins both hook into wp_head with default priority (10), the one whose folder name comes first alphabetically loads first.

    That’s why renaming a plugin folder or switching from “Google Analytics for WordPress” to “Site Kit by Google” can silently change your tracking setup.

    What breaks when checkout flows redirect too fast

    Payment processors and course platforms almost always redirect immediately after a transaction. Stripe Checkout, Gumroad, and most hosted course tools send the buyer to a confirmation URL within milliseconds of payment. If your analytics pixel hasn’t finished sending the conversion event by the time that redirect fires, the event is abandoned mid-request.

    The fix is to delay the redirect until tracking calls return a success callback—but most platforms don’t expose that hook. Stripe Checkout’s success_url is a hard redirect; there’s no “wait for analytics” option. The workaround is to fire the conversion event on the confirmation page itself, not the checkout page. That way, even if the redirect is instant, the event fires after the user lands on a stable URL.

    This also means your conversion tracking needs to deduplicate. If someone refreshes the thank-you page, the event fires again. GA4 handles this with a client ID and session timestamp; other tools require a transaction ID parameter you pass through the URL and check against a cookie or localStorage flag.

    How to audit what’s actually firing

    Open your browser’s network tab, filter by “analytics,” “gtag,” “pixel,” or the domain of your tracking provider, and reload the page. Watch the order requests appear. If a conversion event request fires before the base library’s analytics.js or gtag.js, you’ve found the problem.

    For checkout flows, test with network throttling enabled (Chrome DevTools lets you simulate slow 3G). If your conversion event only fires on fast connections, it’s a timing race you’ll lose on mobile networks.

    If you’re using Postmark or another transactional email service to send purchase confirmations, compare the timestamp of the email sent against the timestamp of the conversion event in your analytics dashboard. If the email consistently arrives before the event logs, your tracking is firing too late—or not at all.

    Want more operator-to-operator breakdowns of what actually works? Subscribe to One Two Three Send—one article daily, no fluff, no affiliate spam unless the tool genuinely fits the topic.

  • Zapier filter conditions fail when field types mismatch

    Zapier filter conditions fail when field types mismatch

    Zapier filter conditions fail when field types mismatch
    Photo by Patrick Martin on Unsplash

    Zapier filters are supposed to be simple: if this field equals that value, continue. If not, stop. But filters fail more often than you’d expect—not because your logic is wrong, but because the data types don’t match what Zapier expects.

    A subscriber count from your email platform might arrive as text instead of a number. An empty field might be null, an empty string, or the word “null.” Your filter sees the mismatch and silently stops the Zap. No error email. No log entry flagged as critical. Just… nothing.

    Here’s how to catch these failures before they cost you hours of debugging.

    How Zapier evaluates filter conditions

    Zapier’s filter step compares two values: the field from your trigger or previous action, and the reference value you type in. The comparison operator—equals, contains, greater than—determines how Zapier interprets both sides.

    When you choose “equals,” Zapier performs a string comparison by default. If your trigger sends a number but the comparison field expects text, the filter might pass or fail unpredictably depending on how the source app formats the data.

    Example: your email platform sends subscriber count as 1250 (integer). You filter for “greater than 1000” (text). Zapier converts both to strings and compares them lexicographically. "1250" is not greater than "1000" in string comparison—it’s less than "2". The filter fails, and your Zap stops.

    This happens most often with:

    • Numeric fields sent as strings (subscriber counts, order totals, timestamps)
    • Boolean fields sent as "true" or 1 instead of true/false
    • Empty fields that arrive as null, "", "null", or "N/A"
    • Date fields formatted inconsistently across apps

    Diagnosing type mismatches in Zapier’s task history

    When a Zap stops unexpectedly, open the task history and expand the filter step. Zapier shows you the exact values it compared, but it doesn’t label their types.

    Look for these red flags:

    • Quoted numbers: "42" instead of 42
    • Inconsistent empty values: sometimes blank, sometimes "null"
    • Boolean values as strings: "true" instead of true

    If you see quotes around a value that should be numeric, the source app sent it as text. If an empty field shows "" in one run and nothing in another, the app’s API is inconsistent.

    Zapier’s task history keeps logs for 14 days on paid plans (7 days on free). If you’re debugging intermittent filter failures, screenshot the mismatched values before they expire.

    Fixing type coercion with formatter steps

    The fix is to normalise field types before the filter step. Add a Formatter by Zapier action between your trigger and filter, then choose the Transform operation that matches your data:

    For numeric comparisons: Use “Numbers > Format Number” to convert text to integer or decimal. Set the input to your dynamic field, leave the format as “plain number,” and pass the output to your filter.

    For boolean checks: Use “Text > Default Value” to replace empty or inconsistent fields with a standard fallback. If your trigger sometimes sends "true", sometimes 1, and sometimes nothing, map it to "yes" or "no" explicitly.

    For empty-field handling: Use “Text > Default Value” again. Set your dynamic field as input, and specify a fallback like "none" or 0. This ensures your filter always compares against a known value, not an unpredictable empty state.

    For date comparisons: Use “Date/Time > Format” to standardise timestamps into ISO 8601 or Unix epoch format. Then compare them as numbers (epoch seconds) instead of strings.

    Each formatter step costs one task. For high-volume Zaps, that adds up—but it’s cheaper than manually re-running failed tasks or missing critical automations.

    When to use Paths instead of Filters

    If your filter logic has more than two branches—e.g., if subscriber count is under 500, do A; if 500–2000, do B; if over 2000, do C—use Zapier’s Paths feature instead of stacking multiple filters.

    Paths let you define multiple conditions in a single step, each with its own downstream actions. They’re clearer to debug, and they don’t silently stop your Zap if one branch doesn’t match—they just skip that path and try the next one.

    Paths are available on Zapier’s Professional plan and above ($49/month as of mid-2026). If you’re on a lower tier and need branching logic, you’ll need to chain Zaps with webhooks or upgrade.

    Test with edge cases, not happy-path data

    Most operators test Zaps with clean, complete sample data. That’s why type mismatches don’t surface until production.

    Before you turn a Zap on, manually trigger it with:

    • An empty field where you expect a number
    • A zero or negative value where you expect positive
    • A malformed date (e.g., "2026-13-01")
    • A boolean field set to an unexpected value ("false" as text, not false)

    Zapier’s test step only runs with the most recent trigger data. If that data is clean, your test passes—but your production Zap still breaks when messy data arrives.

    Want more debugging tactics for no-code workflows? Reply with the automation tool you use most—I’ll cover its failure modes in a future issue.

  • Stop hoarding traffic sources—concentrate on two

    Stop hoarding traffic sources—concentrate on two

    Stop hoarding traffic sources—concentrate on two
    Photo: Spatms via Wikimedia Commons (CC BY-SA 4.0)

    The typical solo operator’s traffic mix looks like this: a little organic social, some SEO, sporadic guest posts, an underfunded Facebook ad campaign, a LinkedIn presence that gets updated twice a month, and maybe a Reddit comment here and there.

    The result? Marginal traction everywhere and momentum nowhere.

    If you’re running a content-driven business alone or with a tiny team, you don’t have the bandwidth to maintain six traffic channels. You barely have enough to run two well. And running two well will deliver more than running six poorly.

    Why diversification backfires for solo operators

    Diversification makes sense when you have a team. A social manager can own Twitter and LinkedIn. An SEO lead can build out a content calendar. A paid strategist can optimize ad spend.

    When you’re alone, diversification becomes dilution.

    Each traffic channel has its own learning curve, content format, posting cadence, and algorithmic quirks. SEO requires consistent publishing, keyword research, and backlink outreach. Twitter needs daily engagement. Paid ads need creative testing and conversion tracking. LinkedIn wants long-form native posts, not links.

    Switching between them incurs a cognitive tax. You’re not just creating content—you’re context-switching between platforms that reward different behaviors. That overhead kills the compounding effect that makes any single channel work.

    Traffic doesn’t compound. But channel-specific skill does. The more reps you get on one platform, the faster you learn what works, the better your content performs, and the less time each piece takes to produce.

    Pick two, not six

    Here’s the framework: choose one owned channel and one discovery channel.

    Owned: SEO, email, or your own site. Something you control, that builds equity over time, and that doesn’t disappear if an algorithm shifts. For most operators, this is SEO—organic search traffic that arrives because you published something useful and Google indexed it.

    Discovery: Social media, paid ads, communities, or guest platforms. Somewhere people find you before they know you exist. This is where new readers come from. For most, it’s one social platform or a narrow paid strategy.

    If you’re writing a weekly newsletter and trying to grow it, your mix might be: SEO + Twitter. You publish articles on your site, optimize them for search, and share insights and threads on Twitter that link back. Both feed your email list.

    Or: SEO + LinkedIn. You write long-form posts natively on LinkedIn to build authority, and publish evergreen how-tos on your own site that rank and convert.

    Or: Email + Reddit. You don’t have a blog. You participate in niche subreddits, answer questions with real value, and your profile links to your newsletter signup.

    The pair matters less than the commitment. Two channels, both run well, will outperform six channels run inconsistently.

    What “run well” actually means

    Running a channel well means you:

    • Publish or engage on a predictable cadence
    • Track what works and do more of it
    • Understand the platform’s content format and native behavior
    • Spend enough time to see compounding return—usually 3–6 months minimum

    For SEO, that’s 2–4 articles a month, keyword-targeted, with internal links and a basic backlink strategy. For Twitter, it’s daily replies, weekly threads, and a clear niche. For LinkedIn, it’s 2–3 long posts a week that add value without asking for anything.

    If you can’t commit to that cadence on a channel, cut it.

    When to add a third

    Only after one of your two is working without you.

    That usually means you’ve automated part of it (SEO content is ranking and driving passive traffic), hired it out (someone else schedules and monitors your social), or built enough momentum that it runs on reduced effort (your Twitter replies generate inbound DMs even when you take a week off).

    Until then, adding a third channel just splits your attention and stalls progress on the two that matter.

    If you’re spread across six traffic sources right now, audit the last 90 days. Which two drove the most qualified traffic—people who actually signed up, bought, or engaged? Double down on those. Let the other four go quiet.

    You’ll lose the illusion of omnipresence. You’ll gain the reality of traction.

    Reply and tell us: which two channels are you concentrating on? We read every response.

  • Buffer vs. Publer vs. Hootsuite: scheduling APIs, queue limits, pricing

    Buffer vs. Publer vs. Hootsuite: scheduling APIs, queue limits, pricing

    Buffer vs. Publer vs. Hootsuite: scheduling APIs, queue limits, pricing
    Photo by Rubaitul Azad on Unsplash

    If you’re running content across Twitter, LinkedIn, Instagram, and Facebook, you need a scheduler that won’t drop posts, hit arbitrary limits, or charge you triple when you add a second brand account.

    Here’s how Buffer, Publer, and Hootsuite stack up for solo operators and small teams publishing 50–300 posts a month across 3–6 accounts.

    Queue depth and post limits

    Buffer’s free tier lets you schedule 10 posts per connected account. The Essentials plan ($6/month per channel) removes the queue cap but limits you to one user. If you’re managing client accounts or a team, you’ll need Team at $12/month per channel—which gets expensive fast if you’re active on four networks.

    Publer‘s free plan allows 10 scheduled posts total, but its Professional tier ($12/month) gives you unlimited scheduling across unlimited accounts and workspaces. That’s the same price Buffer charges per channel. If you’re cross-posting to five platforms, Publer saves you $48/month.

    Hootsuite’s pricing starts at $99/month for one user and 10 social accounts. The platform is built for agencies and enterprises—overkill unless you’re managing 20+ accounts or need approval workflows.

    Platform support and media handling

    All three handle Twitter, Facebook, LinkedIn, and Instagram. Publer also supports Pinterest, TikTok, YouTube, Mastodon, and Google Business—useful if you’re diversifying or testing new channels without adding another tool.

    Buffer compresses images above 5MB and doesn’t warn you before upload. If you’re scheduling high-res carousels or infographics, check the preview carefully—some detail gets lost. Publer and Hootsuite both preserve originals up to 8MB and 10MB respectively, then compress with a warning.

    Video support varies. Buffer caps video uploads at 512MB and transcodes everything to MP4. Publer allows up to 1GB and supports more native formats. Hootsuite allows 512MB but charges extra for bulk video libraries on lower tiers.

    Scheduling reliability and API quirks

    Buffer and Publer both use direct platform APIs. Posts queue client-side, then fire via webhook at the scheduled time. If the API is down (rare but it happens—Twitter’s API went dark for 90 minutes in May), your post waits in retry for up to four hours before failing silently. Neither tool emails you when a post fails unless you explicitly enable notifications in settings.

    Hootsuite uses a hybrid model: some posts go direct, others route through Hootsuite’s proxy layer for compliance monitoring. This adds 15–30 seconds of delay but catches posts that violate platform TOS before they go live. Helpful if you’re managing clients; irrelevant if you’re solo.

    One non-obvious issue: Instagram carousel scheduling fails on all three platforms if your images have mismatched aspect ratios. The API rejects the batch and gives a generic error. Publer’s preview catches this before you schedule; Buffer and Hootsuite don’t flag it until the post fails.

    Pricing summary

    • Buffer: $6/month per channel (Essentials), $12/month per channel for teams. Free tier: 10 posts per account, 3 channels max.
    • Publer: $12/month for unlimited posts and accounts (Professional). Free tier: 10 total scheduled posts, 3 accounts.
    • Hootsuite: $99/month (Professional), includes 10 accounts and one user. Free tier: 2 accounts, 5 scheduled posts.

    Who each is best for

    Pick Buffer if you’re only active on two or three platforms, post fewer than 50 times a month, and want the simplest possible interface. It’s clean, fast, and doesn’t try to upsell analytics dashboards you don’t need.

    Pick Publer if you’re cross-posting to four or more networks, testing new platforms like Mastodon or TikTok, or running multiple brands from one account. The per-channel pricing model makes it the cheapest option once you pass three active accounts.

    Pick Hootsuite only if you’re managing 10+ accounts for clients, need approval workflows, or require compliance logging for regulated industries. Everyone else is overpaying.

    One last note: all three platforms let you connect Google Analytics UTM parameters automatically. Buffer and Publer apply them at the account level; Hootsuite requires manual tagging per post unless you set up a campaign template. If attribution matters to you, test this before committing.

    Want more tool breakdowns like this? Subscribe to One Two Three Send for weekly comparisons, tutorials, and operator Q&A—no fluff, just the details that matter when you’re running a one-person content business.

    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.

  • WordPress plugin conflict logs: where errors hide and how to read them

    WordPress plugin conflict logs: where errors hide and how to read them

    WordPress plugin conflict logs: where errors hide and how to read them
    Photo by Brett Jordan on Unsplash

    When a WordPress plugin breaks your site, you usually get a white screen, a cryptic error message, or—worse—nothing at all. The checkout button stops working. The contact form silently drops submissions. A scheduled post never publishes.

    Most solo operators disable plugins one by one until something works again. That approach finds the culprit, but it doesn’t tell you why the conflict happened or whether it’ll break again after the next update.

    WordPress writes conflict and error data to several places. If you know where to look and what patterns matter, you can diagnose plugin conflicts in minutes instead of hours, and you’ll catch silent failures before readers do.

    Where WordPress writes plugin error logs

    WordPress doesn’t enable debug logging by default. When a plugin conflict occurs, the error might surface in your browser, but more often it gets written to a server log that most operators never open.

    There are three places to check:

    • debug.log in /wp-content/ — only appears if WP_DEBUG_LOG is enabled in wp-config.php. This is the primary conflict log. It captures PHP errors, warnings, notices, and deprecated function calls. Most plugin conflicts show up here first.
    • Server error logs — your hosting provider writes PHP fatal errors and web server errors here. Location varies: cPanel puts them in /logs/, managed WordPress hosts expose them in dashboards. BigScoots surfaces them in the control panel under “Error Log.” Fatal errors that kill the site bypass debug.log and land here.
    • Browser console — JavaScript conflicts don’t write to PHP logs. Open your browser’s developer tools (F12) and check the Console tab. A missing .js file, a jQuery version mismatch, or a React component error will show here, not in WordPress logs.

    If WP_DEBUG_LOG isn’t enabled, add this to wp-config.php just above the line that says /* That's all, stop editing! */:

    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', true);
    define('WP_DEBUG_DISPLAY', false);

    This writes errors to debug.log without displaying them to site visitors. Leave it on for a week. If a conflict exists, it’ll log.

    What plugin conflict entries actually look like

    A typical conflict log entry looks like this:

    [23-Jul-2026 14:32:18 UTC] PHP Fatal error: Uncaught Error: Call to undefined function wp_mail() in /home/user/public_html/wp-content/plugins/custom-contact-form/contact.php:47

    Here’s what matters:

    • Timestamp — when the error fired. Cross-reference this with when you updated a plugin or when a visitor reported a problem.
    • Error type — Fatal errors break execution. Warnings and notices don’t stop the site, but they signal a conflict that might escalate after the next plugin update.
    • File path — tells you which plugin triggered the error. In this case, custom-contact-form is the culprit.
    • Function name — wp_mail() is undefined, which usually means the plugin loaded too early, before WordPress core functions were available.

    Not all conflicts are this clear. Sometimes you’ll see dozens of deprecation notices from a single plugin. That’s noise. Look for fatal errors and repeated warnings tied to the same plugin and function. Those are the patterns that predict breakage.

    Tracing breaking changes after plugin updates

    If your site breaks immediately after a plugin update, the log will show the new error. But if the conflict is silent—forms stop submitting, emails stop sending, scheduled posts don’t publish—you need to correlate log timestamps with plugin update times.

    WordPress logs plugin updates in the database, but doesn’t surface them in a readable timeline. If you suspect a recent update caused a conflict, check debug.log for the first error timestamp, then compare it to your plugin update history in the WordPress admin under Dashboard → Updates. That page shows recent updates, but only for the last few days.

    For longer history, query the database directly or use a plugin like WP Activity Log, which tracks every plugin activation, update, and deactivation with timestamps. Cross-reference the log with your debug.log entries. If the first error appeared within an hour of a plugin update, that’s your conflict source.

    What to do once you’ve identified the conflict

    Once you know which plugin is logging errors, you have three options:

    • Roll back the plugin — most managed WordPress hosts offer one-click plugin rollback. If yours doesn’t, download the previous version from the WordPress plugin repository’s “Advanced View” tab and upload it manually. This buys time while you wait for a patch.
    • Disable the conflicting feature — some plugins let you toggle features. If the conflict stems from a feature you don’t use, turn it off instead of disabling the entire plugin.
    • Contact the developer — if the plugin is actively maintained, report the conflict with your log excerpt, WordPress version, PHP version, and conflicting plugin name. Most developers fix conflicts within a few days if you give them clean reproduction steps.

    Don’t leave WP_DEBUG enabled indefinitely on a live site. Once you’ve identified and resolved the conflict, set WP_DEBUG and WP_DEBUG_LOG back to false. Debug logs grow large and can expose server paths to anyone who guesses the debug.log URL.

    One non-obvious tip: check for JavaScript conflicts separately

    PHP logs won’t capture JavaScript conflicts. If a plugin breaks your site’s front-end interactivity—buttons stop responding, modals don’t open, checkout forms freeze—open your browser console and look for red error messages. Common culprits: two plugins loading different versions of jQuery, or a plugin enqueueing a script that depends on another script that didn’t load.

    To confirm a JavaScript conflict, disable plugins one by one while keeping the browser console open. When the red errors disappear, you’ve found the plugin responsible.

    Want more WordPress infrastructure breakdowns like this? Reply with the hosting or plugin behaviour you want explained next—we read every response and route the best questions into future issues.

  • Beehiiv ad network earnings: what solo operators actually make per 1k opens

    Beehiiv ad network earnings: what solo operators actually make per 1k opens

    Beehiiv ad network earnings: what solo operators actually make per 1k opens
    Photo by Kanchanara on Unsplash

    The Beehiiv Ad Network promises simple monetisation: turn on ads, get paid per thousand opens, skip the sponsor outreach grind. But the earnings data operators share publicly rarely matches what you’ll see in your own dashboard—especially in the first few months.

    Here’s what the revenue actually looks like at different scale points, based on anonymised data from five operators running content newsletters between 2,500 and 45,000 subscribers.

    The CPM range: $8 to $38 per thousand opens

    Beehiiv‘s ad network pays on a CPM basis—cost per mille, or per thousand email opens. The range is wide, and it’s not just about list size.

    An operator with 6,200 subscribers in the personal finance niche reported an average CPM of $22 across Q2 2026, with individual sends ranging from $14 to $31. A tech commentary newsletter with 18,000 subscribers averaged $28. A general productivity newsletter with 12,500 subscribers sat at $11.

    The biggest CPM driver isn’t audience size—it’s advertiser category match. Finance, SaaS, and B2B newsletters pull higher rates because those advertisers pay more to reach decision-makers. Lifestyle, general productivity, and entertainment newsletters sit at the lower end, often below $15.

    Open rate matters too, but indirectly. Beehiiv’s ad network pays per actual open, not per subscriber. If your list has a 45% open rate, you’re monetising 4,500 opens on a 10,000-subscriber send. If it’s 25%, you’re monetising 2,500. The CPM stays the same; your total payout shrinks.

    Monthly revenue at different tiers

    At 5,000 subscribers with a 40% open rate and two sends per week, you’re looking at roughly 16,000 opens per month. At a $15 CPM, that’s $240. At $25, it’s $400.

    At 15,000 subscribers with the same cadence and open rate, you hit 48,000 opens monthly. That’s $720 at $15 CPM, $1,200 at $25.

    At 40,000 subscribers, assuming open rates drop slightly to 35% and you send twice weekly, you’re near 112,000 opens per month. At $20 CPM, that’s $2,240. At $30, it’s $3,360.

    These numbers assume consistent ad fill rate—Beehiiv doesn’t guarantee an ad in every send. Operators report fill rates between 70% and 95% depending on niche and time of year. In January and September, fill drops. In Q4, it peaks.

    When the math breaks down

    The ad network becomes less attractive once you can sell direct sponsorships. A single sponsor paying $500 for a dedicated slot in one send to 15,000 subscribers beats four weeks of ad network revenue at typical CPMs—and you control placement, messaging, and relationship.

    Operators also report that ad creative quality varies. Some ads are single-line text with a tracking link. Others are multi-paragraph placements that disrupt reading flow. You can reject individual ads, but doing so regularly lowers your fill rate and delays payout timing.

    Beehiiv’s payout threshold is $25, and payments process via Stripe 30 days after the calendar month closes. If you earn $18 in July, you won’t see it until you cross $25—possibly September or later if your list is small.

    Who should turn it on

    The ad network makes sense for operators between 3,000 and 20,000 subscribers who don’t want to manage sponsor relationships yet, or who publish in niches where direct sponsorship deals are hard to close. It’s passive income with near-zero effort once enabled.

    It also works as a revenue floor while you build a media kit and test sponsor outreach. You’re not leaving money on the table while you figure out pricing and positioning.

    But if you’re over 25,000 subscribers and getting inbound sponsor interest, or if you’re in a high-value niche like SaaS, finance, or developer tools, you’ll earn more by selling direct—even at lower volumes.

    Want more breakdowns like this? Reply and tell us what monetisation model you want numbers on next—affiliate rev share, course launch cohorts, or paid community tiers.

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

  • ConvertKit’s custom field limits: when segmentation hits a ceiling

    ConvertKit’s custom field limits: when segmentation hits a ceiling

    ConvertKit's custom field limits: when segmentation hits a ceiling
    Photo: Caladusp via Wikimedia Commons (CC BY-SA 4.0)

    ConvertKit lets you add up to 100 custom fields per account. That sounds generous until you’ve been running a newsletter for two years, tagging readers by interest, purchase history, geography, onboarding date, referral source, content preferences, and engagement tier.

    Then you hit the wall.

    The limit isn’t documented prominently. You discover it when the “Add Field” button grays out, or when an automation fails to create a new field and your sequence quietly stops working.

    What counts toward the limit

    Every custom field you create—whether it’s a text field, number, or date—counts toward the 100-field cap. This includes:

    • Active fields currently in use
    • Archived fields you’re no longer using but haven’t deleted
    • Fields created by integrations (Zapier, API calls, third-party forms)

    Deleting a field frees up a slot, but only if you’re certain no automation or segment references it. ConvertKit doesn’t warn you before deletion, and there’s no “undo.”

    Tags, by contrast, are unlimited. Subscribers are unlimited. It’s only custom fields—the structured data layer—that hits a ceiling.

    Where operators waste field slots

    Most operators I’ve audited are using 40–60 fields. The bloat comes from:

    Redundant date fields. Separate fields for “trial_start,” “trial_end,” “first_purchase,” “last_purchase,” “onboarding_completed.” You can often collapse these into tags with date-based automations, or store only the field you’ll actually query.

    One-off campaign tracking. A field for every lead magnet, webinar, or promo. If you’re not segmenting on it after 90 days, archive or delete it.

    Text fields that should be tags. A “interests” field with comma-separated values like “SEO, WordPress, email” is harder to segment than three tags. ConvertKit’s segment builder can combine tags with AND/OR logic; custom field text matching is clunkier.

    Legacy fields from old integrations. A Typeform you used once in 2024, a Zapier zap you turned off, a WordPress plugin you uninstalled. Each left fields behind.

    How to design segments that scale

    If you’re approaching the limit—or want to avoid it—here’s the structure that works:

    Use tags for categorical data. Interests, content preferences, lead sources, engagement tiers. Tags are unlimited, combinable, and easier to audit.

    Reserve custom fields for values you’ll calculate or compare. Numbers (purchase count, total spend, engagement score), dates (signup date, last click), or IDs (Stripe customer ID, external CRM reference).

    Audit every 90 days. Export your field list. Flag anything unused in the last quarter. Archive first, delete after another 30 days if no automations break.

    Document field purpose and owner. Keep a spreadsheet. Column A: field name. Column B: what it tracks. Column C: which automations or segments use it. Column D: date created. When you hit 80 fields, you’ll thank yourself.

    What happens if you hit the cap

    Automations that try to create or update a field beyond the 100th slot fail silently. The automation continues, but the field write doesn’t happen. You won’t get an error email. The subscriber moves to the next step as if nothing broke.

    If you’re relying on that field for downstream segmentation—say, tagging high-intent leads based on a quiz score—you’ll lose data without noticing until you spot the gap in your reports.

    ConvertKit support can’t raise the limit. It’s a hard platform cap, same across all pricing tiers.

    The workaround: delete unused fields, or rethink your data model. Some operators move complex segmentation logic into an external CRM (like Brevo or a dedicated CDP) and sync only the essential fields back to ConvertKit. That adds complexity, but it scales past 100.

    When to stay under 50

    If you’re running a solo operation with fewer than 10,000 subscribers, aim to stay under 50 fields. It forces clarity. Every field you add should answer: “What decision does this let me make that I can’t make with tags?”

    If the answer is “nothing,” use a tag.

    Most operators don’t need purchase history in a custom field—they need a “purchased” tag and a “last_purchase_date” field for recency-based re-engagement. That’s two slots instead of five.

    ConvertKit’s segmentation is powerful, but it rewards restraint. The ceiling exists whether you plan for it or not.

    Hit a segmentation problem you can’t solve with tags? Reply and tell us what you’re trying to track—we’ll feature operator solutions in a future issue.

    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.

  • Newsletter referral programs pay per signup—but measure net growth

    Newsletter referral programs pay per signup—but measure net growth

    Newsletter referral programs pay per signup—but measure net growth
    Photo by Defrino Maasy on Unsplash

    Most newsletter referral programs report one number: gross signups. Someone shares your link, three people subscribe, you see +3 in the dashboard. The referring subscriber unlocks a reward tier. Everyone’s happy.

    Except gross signups don’t tell you whether those three people are still reading 60 days later—or whether they bounced the moment the referrer claimed their prize.

    If you’re running a referral program through Beehiiv, SparkLoop, or a similar tool, you need to track net referral growth: how many referred subscribers remain engaged after the incentive window closes. Otherwise, you’re paying for churn with extra steps.

    Why gross referral counts mislead

    Referral programs reward the act of signing someone up, not the quality of that subscriber. If your reward tiers unlock at 3, 10, or 25 referrals, the person sharing your link is optimized for volume. They’ll post it in group chats, tag friends who aren’t interested, or share it in communities where your topic is tangential at best.

    Those signups count. The platform credits them. But six weeks later, half of them have unsubscribed or gone cold. Your list grew by 25, but your engaged audience grew by 12. You paid the referrer’s reward in full.

    This isn’t theoretical. One operator I spoke with ran a referral campaign offering a $50 Amazon gift card at 10 referrals. Average churn rate for referred subscribers in the first 90 days: 48%. For organic signups in the same period: 22%. The campaign grew the list by 340 subscribers. Six months later, 140 of them were still active. Cost per retained subscriber: higher than a modest Facebook ad budget would have delivered.

    What to measure instead

    Track referral cohorts separately from organic signups, and measure engagement at 30, 60, and 90 days post-signup. Most ESPs let you tag subscribers by source; if yours doesn’t, add a hidden field or custom property when someone arrives via a referral link.

    Compare:

    • Open rate at day 30: Are referred subscribers opening at the same rate as organic signups?
    • Unsubscribe rate by day 60: When does referred churn plateau?
    • Click rate on monetized content: If you’re running sponsorships or affiliate links, do referred subscribers engage with revenue-driving content?

    If referred subscribers churn or disengage faster than organic, your referral program is subsidizing vanity metrics. A list of 10,000 with 40% engagement beats 15,000 with 25% engagement in every scenario that matters: deliverability, sponsor value, product conversion.

    When referral programs still make sense

    Referral mechanics work when:

    • Your content has strong word-of-mouth fit—people genuinely want to share it, and the reward is a bonus, not the primary driver.
    • You’re willing to adjust reward tiers based on retention data, not just signup volume.
    • You can afford to treat referred subscribers as a separate, lower-intent cohort and nurture them differently in your first 90 days.

    If you’re below 1,000 subscribers and still defining your audience, a referral program will accelerate list growth but may also dilute signal. You’ll spend months figuring out what content works for two different cohorts instead of one.

    Above 5,000 subscribers, referral programs become more defensible—but only if you’re already retaining >70% of organic signups past 90 days. If your baseline retention is weak, a referral program will amplify the problem, not solve it.

    One non-obvious fix

    Delay reward fulfillment by 60 days. Instead of unlocking rewards the moment a referrer hits 10 signups, unlock them 60 days after the tenth signup—and only if at least 7 of those 10 are still subscribed.

    This shifts the incentive from volume to quality. Referrers will share your link with people more likely to stick around, because they only get paid if those subscribers stay. It also filters out referral farmers who game the system by cycling through throwaway emails.

    Most referral platforms don’t support conditional reward logic natively, but you can build it with a weekly script that checks subscriber status and manually triggers rewards. It’s friction, but it’s worth it if you’re spending four figures a year on referral incentives.

    If you’re running a referral program right now: pull your referral cohort data for the last 90 days and compare retention to organic signups. If referred churn is more than 10 percentage points higher, either tighten your reward criteria or redirect that budget to a channel with better unit economics.

    Want more breakdowns like this? Subscribe to One Two Three Send—we cover the operational details most online-business newsletters skip.

    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 content rewriter tools break your voice—here’s the tradeoff

    AI content rewriter tools break your voice—here’s the tradeoff

    AI content rewriter tools break your voice—here's the tradeoff
    Photo by Deepak Gupta on Unsplash

    Most AI content rewriter tools promise the same thing: take your draft, smooth out the rough patches, tighten the prose, and hand back something publishable in seconds. They work. The output is cleaner. But every operator who uses them regularly hits the same problem after a few weeks: the writing stops sounding like them.

    This isn’t about quality. The rewritten version is often technically better—shorter sentences, fewer filler words, clearer structure. The problem is that it’s better in a way that erases the small habits and choices that make your voice distinct. The casual aside. The sentence fragment. The specific word you’d use instead of the synonym the model picked.

    Readers don’t consciously notice voice most of the time, but they feel it when it shifts. If your last ten posts had a consistent rhythm and suddenly post eleven reads like it came from a different person, open rates drop. Replies dry up. The content still works, but the connection weakens.

    What rewriters actually change

    AI rewriter tools—whether standalone like Wordtune or built into larger platforms like Jasper and Copy.ai—operate by rephrasing your input to match patterns the model learned from training data. That data skews toward polished, formal, widely-published writing. The model doesn’t know your tics. It doesn’t know you always use “folks” instead of “people” or that you start half your paragraphs with a dependent clause.

    Here’s what typically gets flattened:

    • Sentence rhythm. If you write in a mix of long and short bursts, the rewriter will smooth it into medium-length sentences.
    • Colloquialisms. Casual phrases get swapped for neutral equivalents. “A pain to set up” becomes “difficult to configure.”
    • Redundancy you use for emphasis. Repeating a word or idea for effect gets trimmed as inefficiency.
    • Personality markers. Em dashes, parenthetical asides, rhetorical questions—anything that breaks formal structure tends to get rewritten or removed.

    None of this is wrong. But if those elements are why your readers recognize your writing, stripping them out is a problem.

    When rewriters make sense

    There are situations where flattening your voice is the correct tradeoff. If you’re writing help documentation, product updates, or onboarding emails, clarity beats personality. Readers aren’t there for your voice—they’re there to solve a problem or understand a feature. A rewriter can take a tangled explanation and make it scannable in seconds.

    Rewriters also help when you’re stuck. If you’ve written the same paragraph three times and it still feels off, running it through a tool can break the loop. You won’t keep the output verbatim, but it gives you a new angle to edit from.

    And if English isn’t your first language, rewriters handle grammar edge cases faster than you can look them up. The risk is still there—your voice might get smoothed out—but the time saved often outweighs it.

    How to use them without losing yourself

    If you’re going to use a rewriter regularly, treat it like a first-pass editor, not a replacement for your judgment. Here’s the workflow that works:

    Write the full draft first. Don’t rewrite as you go. Get your ideas out in your natural voice, then decide which sections need help.

    Rewrite in chunks, not whole pieces. Run one paragraph or section at a time. If you feed an entire post into a rewriter, you lose control over which changes matter and which don’t.

    Edit the rewrite. Don’t publish the output as-is. Read it aloud. If a sentence doesn’t sound like something you’d say, change it back or meet halfway. The goal is to use the tool’s structure while keeping your word choices.

    Keep a voice reference. Save three or four posts you’re proud of—ones where the voice feels right. Before you hit publish on something that’s been rewritten, compare it. If the tone feels off, you’ll catch it.

    The long-term cost

    The risk isn’t just that one post sounds different. It’s that if you rely on a rewriter for every piece, you stop practicing the skill of editing your own voice. Over six months, your drafts start to sound more like the tool’s output even before you run them through it. You’re training yourself to write in a way that needs less rewriting, which means writing in a way that sounds like everyone else using the same model.

    This is fixable, but it requires noticing it’s happening. If you’ve published twenty posts in the last two months and none of them feel like you anymore, the rewriter is doing too much of the work.

    Voice is one of the few competitive advantages solo operators have. It’s free, it’s hard to replicate, and it’s why readers pick your site over the fifty others covering the same topics. Rewriters are useful tools, but they’re not neutral. Every time you use one, you’re making a tradeoff. Just make sure you’re choosing it, not defaulting to it.

    Trying to balance speed and voice in your own workflow? Reply with what you’re struggling with—I’ll cover reader questions in an upcoming piece.