diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 9247d24..1661b61 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,23 +12,6 @@ "version": "2.1.0" }, "plugins": [ - { - "name": "marketing-skills", - "source": "./marketing-skill", - "description": "6 marketing skills: content creator, demand generation, product marketing, ASO, social media analytics, campaign analytics", - "version": "1.0.0", - "author": { - "name": "Alireza Rezvani" - }, - "keywords": [ - "marketing", - "content", - "seo", - "demand-gen", - "social-media" - ], - "category": "marketing" - }, { "name": "engineering-skills", "source": "./engineering-team", @@ -340,6 +323,16 @@ "self-improvement", "learning" ] + }, + { + "slug": "marketing-skills", + "name": "Marketing Division", + "version": "2.0.0", + "description": "42-skill marketing division: 7 pods (Content, SEO, CRO, Channels, Growth, Intelligence, Sales) + context foundation + orchestration router. 27 Python tools, 60 reference docs. All stdlib-only.", + "path": "marketing-skill/", + "skills_count": 42, + "category": "marketing" } - ] + ], + "total_plugins": 18 } \ No newline at end of file diff --git a/.codex/skills-index.json b/.codex/skills-index.json index 95fdf61..9d48a8f 100644 --- a/.codex/skills-index.json +++ b/.codex/skills-index.json @@ -3,7 +3,7 @@ "name": "claude-code-skills", "description": "Production-ready skill packages for AI agents - Marketing, Engineering, Product, C-Level, PM, and RA/QM", "repository": "https://github.com/alirezarezvani/claude-skills", - "total_skills": 89, + "total_skills": 124, "skills": [ { "name": "contract-and-proposal-writer", @@ -341,23 +341,131 @@ "category": "finance", "description": "Performs financial ratio analysis, DCF valuation, budget variance analysis, and rolling forecast construction for strategic decision-making" }, + { + "name": "ab-test-setup", + "source": "../../marketing-skill/ab-test-setup", + "category": "marketing", + "description": "When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions \"A/B test,\" \"split test,\" \"experiment,\" \"test this change,\" \"variant copy,\" \"multivariate test,\" \"hypothesis,\" \"conversion experiment,\" \"statistical significance,\" or \"test this.\" For tracking implementation, see analytics-tracking." + }, + { + "name": "ad-creative", + "source": "../../marketing-skill/ad-creative", + "category": "marketing", + "description": "When the user needs to generate, iterate, or scale ad creative for paid advertising. Use when they say 'write ad copy,' 'generate headlines,' 'create ad variations,' 'bulk creative,' 'iterate on ads,' 'ad copy validation,' 'RSA headlines,' 'Meta ad copy,' 'LinkedIn ad,' or 'creative testing.' This is pure creative production \u2014 distinct from paid-ads (campaign strategy). Use ad-creative when you need the copy, not the campaign plan." + }, + { + "name": "ai-seo", + "source": "../../marketing-skill/ai-seo", + "category": "marketing", + "description": "Optimize content to get cited by AI search engines \u2014 ChatGPT, Perplexity, Google AI Overviews, Claude, Gemini, Copilot. Use when you want your content to appear in AI-generated answers, not just ranked in blue links. Triggers: 'optimize for AI search', 'get cited by ChatGPT', 'AI Overviews', 'Perplexity citations', 'AI SEO', 'generative search', 'LLM visibility', 'GEO' (generative engine optimization). NOT for traditional SEO ranking (use seo-audit). NOT for content creation (use content-production)." + }, + { + "name": "analytics-tracking", + "source": "../../marketing-skill/analytics-tracking", + "category": "marketing", + "description": "Set up, audit, and debug analytics tracking implementation \u2014 GA4, Google Tag Manager, event taxonomy, conversion tracking, and data quality. Use when building a tracking plan from scratch, auditing existing analytics for gaps or errors, debugging missing events, or setting up GTM. Trigger keywords: GA4 setup, Google Tag Manager, GTM, event tracking, analytics implementation, conversion tracking, tracking plan, event taxonomy, custom dimensions, UTM tracking, analytics audit, missing events, tracking broken. NOT for analyzing marketing campaign data \u2014 use campaign-analytics for that. NOT for BI dashboards \u2014 use product-analytics for in-product event analysis." + }, { "name": "app-store-optimization", "source": "../../marketing-skill/app-store-optimization", "category": "marketing", "description": "App Store Optimization toolkit for researching keywords, optimizing metadata, and tracking mobile app performance on Apple App Store and Google Play Store." }, + { + "name": "brand-guidelines", + "source": "../../marketing-skill/brand-guidelines", + "category": "marketing", + "description": "When the user wants to apply, document, or enforce brand guidelines for any product or company. Also use when the user mentions 'brand guidelines,' 'brand colors,' 'typography,' 'logo usage,' 'brand voice,' 'visual identity,' 'tone of voice,' 'brand standards,' 'style guide,' 'brand consistency,' or 'company design standards.' Covers color systems, typography, logo rules, imagery guidelines, and tone matrix for any brand \u2014 including Anthropic's official identity." + }, { "name": "campaign-analytics", "source": "../../marketing-skill/campaign-analytics", "category": "marketing", "description": "Analyzes campaign performance with multi-touch attribution, funnel conversion, and ROI calculation for marketing optimization" }, + { + "name": "churn-prevention", + "source": "../../marketing-skill/churn-prevention", + "category": "marketing", + "description": "Reduce voluntary and involuntary churn through cancel flow design, save offers, exit surveys, and dunning sequences. Use when designing or optimizing a cancel flow, building save offers, setting up dunning emails, or reducing failed-payment churn. Trigger keywords: cancel flow, churn reduction, save offers, dunning, exit survey, payment recovery, win-back, involuntary churn, failed payments, cancel page. NOT for customer health scoring or expansion revenue \u2014 use customer-success-manager for that." + }, + { + "name": "cold-email", + "source": "../../marketing-skill/cold-email", + "category": "marketing", + "description": "When the user wants to write, improve, or build a sequence of B2B cold outreach emails to prospects who haven't asked to hear from them. Use when the user mentions 'cold email,' 'cold outreach,' 'prospecting emails,' 'SDR emails,' 'sales emails,' 'first touch email,' 'follow-up sequence,' or 'email prospecting.' Also use when they share an email draft that sounds too sales-y and needs to be humanized. Distinct from email-sequence (lifecycle/nurture to opted-in subscribers) \u2014 this is unsolicited outreach to new prospects. NOT for lifecycle emails, newsletters, or drip campaigns (use email-sequence)." + }, + { + "name": "competitor-alternatives", + "source": "../../marketing-skill/competitor-alternatives", + "category": "marketing", + "description": "When the user wants to create competitor comparison or alternative pages for SEO and sales enablement. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'switch from competitor,' or 'comparison content.' Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. Emphasizes deep research, modular content architecture, and varied section types beyond feature tables." + }, { "name": "content-creator", "source": "../../marketing-skill/content-creator", "category": "marketing", - "description": "Create SEO-optimized marketing content with consistent brand voice. Includes brand voice analyzer, SEO optimizer, content frameworks, and social media templates. Use when writing blog posts, creating social media content, analyzing brand voice, optimizing SEO, planning content calendars, or when user mentions content creation, brand voice, SEO optimization, social media marketing, or content strategy." + "description": "DEPRECATED \u2014 Use content-production for full content pipeline, or content-strategy for planning. This skill redirects to the appropriate specialist." + }, + { + "name": "content-humanizer", + "source": "../../marketing-skill/content-humanizer", + "category": "marketing", + "description": "Makes AI-generated content sound genuinely human \u2014 not just cleaned up, but alive. Use when content feels robotic, uses too many AI clich\u00e9s, lacks personality, or reads like it was written by committee. Triggers: 'this sounds like AI', 'make it more human', 'add personality', 'it feels generic', 'sounds robotic', 'fix AI writing', 'inject our voice'. NOT for initial content creation (use content-production). NOT for SEO optimization (use content-production Mode 3)." + }, + { + "name": "content-production", + "source": "../../marketing-skill/content-production", + "category": "marketing", + "description": "Full content production pipeline \u2014 takes a topic from blank page to published-ready piece. Use when you need to execute content: write a blog post, article, or guide end-to-end. Triggers: 'write a post about', 'draft an article', 'create content for', 'help me write', 'I need a blog post'. NOT for content strategy or calendar planning (use content-strategy). NOT for repurposing existing content (use content-repurposing). NOT for social captions only." + }, + { + "name": "content-strategy", + "source": "../../marketing-skill/content-strategy", + "category": "marketing", + "description": "When the user wants to plan a content strategy, decide what content to create, or figure out what topics to cover. Also use when the user mentions \\\"content strategy,\\\" \\\"what should I write about,\\\" \\\"content ideas,\\\" \\\"blog strategy,\\\" \\\"topic clusters,\\\" or \\\"content planning.\\\" For writing individual pieces, see copywriting. For SEO-specific audits, see seo-audit." + }, + { + "name": "copy-editing", + "source": "../../marketing-skill/copy-editing", + "category": "marketing", + "description": "When the user wants to edit, review, or improve existing marketing copy. Also use when the user mentions 'edit this copy,' 'review my copy,' 'copy feedback,' 'proofread,' 'polish this,' 'make this better,' or 'copy sweep.' This skill provides a systematic approach to editing marketing copy through multiple focused passes." + }, + { + "name": "copywriting", + "source": "../../marketing-skill/copywriting", + "category": "marketing", + "description": "When the user wants to write, rewrite, or improve marketing copy for any page \u2014 including homepage, landing pages, pricing pages, feature pages, about pages, or product pages. Also use when the user says \\\"write copy for,\\\" \\\"improve this copy,\\\" \\\"rewrite this page,\\\" \\\"marketing copy,\\\" \\\"headline help,\\\" or \\\"CTA copy.\\\" For email copy, see email-sequence. For popup copy, see popup-cro." + }, + { + "name": "email-sequence", + "source": "../../marketing-skill/email-sequence", + "category": "marketing", + "description": "When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions \"email sequence,\" \"drip campaign,\" \"nurture sequence,\" \"onboarding emails,\" \"welcome sequence,\" \"re-engagement emails,\" \"email automation,\" or \"lifecycle emails.\" For in-app onboarding, see onboarding-cro." + }, + { + "name": "form-cro", + "source": "../../marketing-skill/form-cro", + "category": "marketing", + "description": "When the user wants to optimize any form that is NOT signup/registration \u2014 including lead capture forms, contact forms, demo request forms, application forms, survey forms, or checkout forms. Also use when the user mentions \"form optimization,\" \"lead form conversions,\" \"form friction,\" \"form fields,\" \"form completion rate,\" or \"contact form.\" For signup/registration forms, see signup-flow-cro. For popups containing forms, see popup-cro." + }, + { + "name": "free-tool-strategy", + "source": "../../marketing-skill/free-tool-strategy", + "category": "marketing", + "description": "When the user wants to build a free tool for marketing \u2014 lead generation, SEO value, or brand awareness. Use when they mention 'engineering as marketing,' 'free tool,' 'calculator,' 'generator,' 'checker,' 'grader,' 'marketing tool,' 'lead gen tool,' 'build something for traffic,' 'interactive tool,' or 'free resource.' Covers idea evaluation, tool design, and launch strategy. For pure SEO content strategy (no tool), use seo-audit or content-strategy instead." + }, + { + "name": "launch-strategy", + "source": "../../marketing-skill/launch-strategy", + "category": "marketing", + "description": "When the user wants to plan a product launch, feature announcement, or release strategy. Also use when the user mentions 'launch,' 'Product Hunt,' 'feature release,' 'announcement,' 'go-to-market,' 'beta launch,' 'early access,' 'waitlist,' 'product update,' 'GTM plan,' 'launch checklist,' or 'launch momentum.' This skill covers phased launches, channel strategy, and ongoing launch momentum." + }, + { + "name": "marketing-context", + "source": "../../marketing-skill/marketing-context", + "category": "marketing", + "description": "Create and maintain the marketing context document that all marketing skills read before starting. Use when the user mentions 'marketing context,' 'brand voice,' 'set up context,' 'target audience,' 'ICP,' 'style guide,' 'who is my customer,' 'positioning,' or wants to avoid repeating foundational information across marketing tasks. Run this at the start of any new project before using other marketing skills." }, { "name": "marketing-demand-acquisition", @@ -365,17 +473,113 @@ "category": "marketing", "description": "Multi-channel demand generation, paid media optimization, SEO strategy, and partnership programs for Series A+ startups" }, + { + "name": "marketing-ideas", + "source": "../../marketing-skill/marketing-ideas", + "category": "marketing", + "description": "When the user needs marketing ideas, inspiration, or strategies for their SaaS or software product. Also use when the user asks for 'marketing ideas,' 'growth ideas,' 'how to market,' 'marketing strategies,' 'marketing tactics,' 'ways to promote,' or 'ideas to grow.' This skill provides 139 proven marketing approaches organized by category." + }, + { + "name": "marketing-ops", + "source": "../../marketing-skill/marketing-ops", + "category": "marketing", + "description": "Central router for the marketing skill ecosystem. Use when unsure which marketing skill to use, when orchestrating a multi-skill campaign, or when coordinating across content, SEO, CRO, channels, and analytics. Also use when the user mentions 'marketing help,' 'campaign plan,' 'what should I do next,' 'marketing priorities,' or 'coordinate marketing.'" + }, + { + "name": "marketing-psychology", + "source": "../../marketing-skill/marketing-psychology", + "category": "marketing", + "description": "When the user wants to apply psychological principles, mental models, or behavioral science to marketing. Also use when the user mentions 'psychology,' 'mental models,' 'cognitive bias,' 'persuasion,' 'behavioral science,' 'why people buy,' 'decision-making,' or 'consumer behavior.' This skill provides 70+ mental models organized for marketing application." + }, { "name": "marketing-strategy-pmm", "source": "../../marketing-skill/marketing-strategy-pmm", "category": "marketing", "description": "Product marketing skill for positioning, GTM strategy, competitive intelligence, and product launches. Covers April Dunford positioning, ICP definition, competitive battlecards, launch playbooks, and international market entry." }, + { + "name": "onboarding-cro", + "source": "../../marketing-skill/onboarding-cro", + "category": "marketing", + "description": "When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions \"onboarding flow,\" \"activation rate,\" \"user activation,\" \"first-run experience,\" \"empty states,\" \"onboarding checklist,\" \"aha moment,\" or \"new user experience.\" For signup/registration optimization, see signup-flow-cro. For ongoing email sequences, see email-sequence." + }, + { + "name": "page-cro", + "source": "../../marketing-skill/page-cro", + "category": "marketing", + "description": "When the user wants to optimize, improve, or increase conversions on any marketing page \u2014 including homepage, landing pages, pricing pages, feature pages, or blog posts. Also use when the user says \"CRO,\" \"conversion rate optimization,\" \"this page isn't converting,\" \"improve conversions,\" or \"why isn't this page working.\" For signup/registration flows, see signup-flow-cro. For post-signup activation, see onboarding-cro. For forms outside of signup, see form-cro. For popups/modals, see popup-cro." + }, + { + "name": "paid-ads", + "source": "../../marketing-skill/paid-ads", + "category": "marketing", + "description": "When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ad copy,' 'ad creative,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' or 'audience targeting.' This skill covers campaign strategy, ad creation, audience targeting, and optimization." + }, + { + "name": "paywall-upgrade-cro", + "source": "../../marketing-skill/paywall-upgrade-cro", + "category": "marketing", + "description": "When the user wants to create or optimize in-app paywalls, upgrade screens, upsell modals, or feature gates. Also use when the user mentions \"paywall,\" \"upgrade screen,\" \"upgrade modal,\" \"upsell,\" \"feature gate,\" \"convert free to paid,\" \"freemium conversion,\" \"trial expiration screen,\" \"limit reached screen,\" \"plan upgrade prompt,\" or \"in-app pricing.\" Distinct from public pricing pages (see page-cro) \u2014 this skill focuses on in-product upgrade moments where the user has already experienced value." + }, + { + "name": "popup-cro", + "source": "../../marketing-skill/popup-cro", + "category": "marketing", + "description": "When the user wants to create or optimize popups, modals, overlays, slide-ins, or banners for conversion purposes. Also use when the user mentions \"exit intent,\" \"popup conversions,\" \"modal optimization,\" \"lead capture popup,\" \"email popup,\" \"announcement banner,\" or \"overlay.\" For forms outside of popups, see form-cro. For general page conversion optimization, see page-cro." + }, + { + "name": "pricing-strategy", + "source": "../../marketing-skill/pricing-strategy", + "category": "marketing", + "description": "Design, optimize, and communicate SaaS pricing \u2014 tier structure, value metrics, pricing pages, and price increase strategy. Use when building a pricing model from scratch, redesigning existing pricing, planning a price increase, or improving a pricing page. Trigger keywords: pricing tiers, pricing page, price increase, packaging, value metric, per seat pricing, usage-based pricing, freemium, good-better-best, pricing strategy, monetization, pricing page conversion, Van Westendorp. NOT for broader product strategy \u2014 use product-strategist for that. NOT for customer success or renewals \u2014 use customer-success-manager for expansion revenue." + }, + { + "name": "programmatic-seo", + "source": "../../marketing-skill/programmatic-seo", + "category": "marketing", + "description": "When the user wants to create SEO-driven pages at scale using templates and data. Also use when the user mentions \"programmatic SEO,\" \"template pages,\" \"pages at scale,\" \"directory pages,\" \"location pages,\" \"[keyword] + [city] pages,\" \"comparison pages,\" \"integration pages,\" or \"building many pages for SEO.\" For auditing existing SEO issues, see seo-audit." + }, { "name": "prompt-engineer-toolkit", "source": "../../marketing-skill/prompt-engineer-toolkit", "category": "marketing", - "description": "Skill from marketing-skill" + "description": "When the user wants to improve prompts for AI-assisted marketing, build prompt templates, or optimize AI content workflows. Also use when the user mentions 'prompt engineering,' 'improve my prompts,' 'AI writing quality,' 'prompt templates,' or 'AI content workflow.'" + }, + { + "name": "referral-program", + "source": "../../marketing-skill/referral-program", + "category": "marketing", + "description": "When the user wants to design, launch, or optimize a referral or affiliate program. Use when they mention 'referral program,' 'affiliate program,' 'word of mouth,' 'refer a friend,' 'incentive program,' 'customer referrals,' 'brand ambassador,' 'partner program,' 'referral link,' or 'growth through referrals.' Covers program mechanics, incentive design, and optimization \u2014 not just the idea of referrals but the actual system." + }, + { + "name": "schema-markup", + "source": "../../marketing-skill/schema-markup", + "category": "marketing", + "description": "When the user wants to implement, audit, or validate structured data (schema markup) on their website. Use when the user mentions 'structured data,' 'schema.org,' 'JSON-LD,' 'rich results,' 'rich snippets,' 'schema markup,' 'FAQ schema,' 'Product schema,' 'HowTo schema,' or 'structured data errors in Search Console.' Also use when someone asks why their content isn't showing rich results or wants to improve AI search visibility. NOT for general SEO audits (use seo-audit) or technical SEO crawl issues (use site-architecture)." + }, + { + "name": "seo-audit", + "source": "../../marketing-skill/seo-audit", + "category": "marketing", + "description": "When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions \"SEO audit,\" \"technical SEO,\" \"why am I not ranking,\" \"SEO issues,\" \"on-page SEO,\" \"meta tags review,\" or \"SEO health check.\" For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema-markup." + }, + { + "name": "signup-flow-cro", + "source": "../../marketing-skill/signup-flow-cro", + "category": "marketing", + "description": "When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions \"signup conversions,\" \"registration friction,\" \"signup form optimization,\" \"free trial signup,\" \"reduce signup dropoff,\" or \"account creation flow.\" For post-signup onboarding, see onboarding-cro. For lead capture forms (not account creation), see form-cro." + }, + { + "name": "site-architecture", + "source": "../../marketing-skill/site-architecture", + "category": "marketing", + "description": "When the user wants to audit, redesign, or plan their website's structure, URL hierarchy, navigation design, or internal linking strategy. Use when the user mentions 'site architecture,' 'URL structure,' 'internal links,' 'site navigation,' 'breadcrumbs,' 'topic clusters,' 'hub pages,' 'orphan pages,' 'silo structure,' 'information architecture,' or 'website reorganization.' Also use when someone has SEO problems and the root cause is structural (not content or schema). NOT for content strategy decisions about what to write (use content-strategy) or for schema markup (use schema-markup)." + }, + { + "name": "social-content", + "source": "../../marketing-skill/social-content", + "category": "marketing", + "description": "When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform-specific strategies." }, { "name": "social-media-analyzer", @@ -383,6 +587,12 @@ "category": "marketing", "description": "Social media campaign analysis and performance tracking. Calculates engagement rates, ROI, and benchmarks across platforms. Use for analyzing social media performance, calculating engagement rate, measuring campaign ROI, comparing platform metrics, or benchmarking against industry standards." }, + { + "name": "social-media-manager", + "source": "../../marketing-skill/social-media-manager", + "category": "marketing", + "description": "When the user wants to develop social media strategy, plan content calendars, manage community engagement, or grow their social presence across platforms. Also use when the user mentions 'social media strategy,' 'social calendar,' 'community management,' 'social media plan,' 'grow followers,' 'engagement rate,' 'social media audit,' or 'which platforms should I use.' For writing individual social posts, see social-content. For analyzing social performance data, see social-media-analyzer." + }, { "name": "agile-product-owner", "source": "../../product-team/agile-product-owner", @@ -562,7 +772,7 @@ "description": "Financial analysis, valuation, and forecasting skills" }, "marketing": { - "count": 7, + "count": 42, "source": "../../marketing-skill", "description": "Marketing, content, and demand generation skills" }, diff --git a/.codex/skills/ab-test-setup b/.codex/skills/ab-test-setup new file mode 120000 index 0000000..b8dbfd4 --- /dev/null +++ b/.codex/skills/ab-test-setup @@ -0,0 +1 @@ +../../marketing-skill/ab-test-setup \ No newline at end of file diff --git a/.codex/skills/ad-creative b/.codex/skills/ad-creative new file mode 120000 index 0000000..f711d76 --- /dev/null +++ b/.codex/skills/ad-creative @@ -0,0 +1 @@ +../../marketing-skill/ad-creative \ No newline at end of file diff --git a/.codex/skills/ai-seo b/.codex/skills/ai-seo new file mode 120000 index 0000000..729b13a --- /dev/null +++ b/.codex/skills/ai-seo @@ -0,0 +1 @@ +../../marketing-skill/ai-seo \ No newline at end of file diff --git a/.codex/skills/analytics-tracking b/.codex/skills/analytics-tracking new file mode 120000 index 0000000..c8fef57 --- /dev/null +++ b/.codex/skills/analytics-tracking @@ -0,0 +1 @@ +../../marketing-skill/analytics-tracking \ No newline at end of file diff --git a/.codex/skills/brand-guidelines b/.codex/skills/brand-guidelines new file mode 120000 index 0000000..1e7aa06 --- /dev/null +++ b/.codex/skills/brand-guidelines @@ -0,0 +1 @@ +../../marketing-skill/brand-guidelines \ No newline at end of file diff --git a/.codex/skills/churn-prevention b/.codex/skills/churn-prevention new file mode 120000 index 0000000..f285d48 --- /dev/null +++ b/.codex/skills/churn-prevention @@ -0,0 +1 @@ +../../marketing-skill/churn-prevention \ No newline at end of file diff --git a/.codex/skills/cold-email b/.codex/skills/cold-email new file mode 120000 index 0000000..94bf69d --- /dev/null +++ b/.codex/skills/cold-email @@ -0,0 +1 @@ +../../marketing-skill/cold-email \ No newline at end of file diff --git a/.codex/skills/competitor-alternatives b/.codex/skills/competitor-alternatives new file mode 120000 index 0000000..844423b --- /dev/null +++ b/.codex/skills/competitor-alternatives @@ -0,0 +1 @@ +../../marketing-skill/competitor-alternatives \ No newline at end of file diff --git a/.codex/skills/content-humanizer b/.codex/skills/content-humanizer new file mode 120000 index 0000000..226a3b7 --- /dev/null +++ b/.codex/skills/content-humanizer @@ -0,0 +1 @@ +../../marketing-skill/content-humanizer \ No newline at end of file diff --git a/.codex/skills/content-production b/.codex/skills/content-production new file mode 120000 index 0000000..82b51cc --- /dev/null +++ b/.codex/skills/content-production @@ -0,0 +1 @@ +../../marketing-skill/content-production \ No newline at end of file diff --git a/.codex/skills/content-strategy b/.codex/skills/content-strategy new file mode 120000 index 0000000..6498a5a --- /dev/null +++ b/.codex/skills/content-strategy @@ -0,0 +1 @@ +../../marketing-skill/content-strategy \ No newline at end of file diff --git a/.codex/skills/copy-editing b/.codex/skills/copy-editing new file mode 120000 index 0000000..c36e53e --- /dev/null +++ b/.codex/skills/copy-editing @@ -0,0 +1 @@ +../../marketing-skill/copy-editing \ No newline at end of file diff --git a/.codex/skills/copywriting b/.codex/skills/copywriting new file mode 120000 index 0000000..f21a248 --- /dev/null +++ b/.codex/skills/copywriting @@ -0,0 +1 @@ +../../marketing-skill/copywriting \ No newline at end of file diff --git a/.codex/skills/email-sequence b/.codex/skills/email-sequence new file mode 120000 index 0000000..3676fe2 --- /dev/null +++ b/.codex/skills/email-sequence @@ -0,0 +1 @@ +../../marketing-skill/email-sequence \ No newline at end of file diff --git a/.codex/skills/form-cro b/.codex/skills/form-cro new file mode 120000 index 0000000..8db5313 --- /dev/null +++ b/.codex/skills/form-cro @@ -0,0 +1 @@ +../../marketing-skill/form-cro \ No newline at end of file diff --git a/.codex/skills/free-tool-strategy b/.codex/skills/free-tool-strategy new file mode 120000 index 0000000..0abd796 --- /dev/null +++ b/.codex/skills/free-tool-strategy @@ -0,0 +1 @@ +../../marketing-skill/free-tool-strategy \ No newline at end of file diff --git a/.codex/skills/launch-strategy b/.codex/skills/launch-strategy new file mode 120000 index 0000000..dc5bd25 --- /dev/null +++ b/.codex/skills/launch-strategy @@ -0,0 +1 @@ +../../marketing-skill/launch-strategy \ No newline at end of file diff --git a/.codex/skills/marketing-context b/.codex/skills/marketing-context new file mode 120000 index 0000000..5befda7 --- /dev/null +++ b/.codex/skills/marketing-context @@ -0,0 +1 @@ +../../marketing-skill/marketing-context \ No newline at end of file diff --git a/.codex/skills/marketing-ideas b/.codex/skills/marketing-ideas new file mode 120000 index 0000000..aa9f97f --- /dev/null +++ b/.codex/skills/marketing-ideas @@ -0,0 +1 @@ +../../marketing-skill/marketing-ideas \ No newline at end of file diff --git a/.codex/skills/marketing-ops b/.codex/skills/marketing-ops new file mode 120000 index 0000000..5beb76a --- /dev/null +++ b/.codex/skills/marketing-ops @@ -0,0 +1 @@ +../../marketing-skill/marketing-ops \ No newline at end of file diff --git a/.codex/skills/marketing-psychology b/.codex/skills/marketing-psychology new file mode 120000 index 0000000..bca4023 --- /dev/null +++ b/.codex/skills/marketing-psychology @@ -0,0 +1 @@ +../../marketing-skill/marketing-psychology \ No newline at end of file diff --git a/.codex/skills/onboarding-cro b/.codex/skills/onboarding-cro new file mode 120000 index 0000000..1be4183 --- /dev/null +++ b/.codex/skills/onboarding-cro @@ -0,0 +1 @@ +../../marketing-skill/onboarding-cro \ No newline at end of file diff --git a/.codex/skills/page-cro b/.codex/skills/page-cro new file mode 120000 index 0000000..166678d --- /dev/null +++ b/.codex/skills/page-cro @@ -0,0 +1 @@ +../../marketing-skill/page-cro \ No newline at end of file diff --git a/.codex/skills/paid-ads b/.codex/skills/paid-ads new file mode 120000 index 0000000..8835f9e --- /dev/null +++ b/.codex/skills/paid-ads @@ -0,0 +1 @@ +../../marketing-skill/paid-ads \ No newline at end of file diff --git a/.codex/skills/paywall-upgrade-cro b/.codex/skills/paywall-upgrade-cro new file mode 120000 index 0000000..7c81664 --- /dev/null +++ b/.codex/skills/paywall-upgrade-cro @@ -0,0 +1 @@ +../../marketing-skill/paywall-upgrade-cro \ No newline at end of file diff --git a/.codex/skills/popup-cro b/.codex/skills/popup-cro new file mode 120000 index 0000000..46e7fde --- /dev/null +++ b/.codex/skills/popup-cro @@ -0,0 +1 @@ +../../marketing-skill/popup-cro \ No newline at end of file diff --git a/.codex/skills/pricing-strategy b/.codex/skills/pricing-strategy new file mode 120000 index 0000000..8e6a217 --- /dev/null +++ b/.codex/skills/pricing-strategy @@ -0,0 +1 @@ +../../marketing-skill/pricing-strategy \ No newline at end of file diff --git a/.codex/skills/programmatic-seo b/.codex/skills/programmatic-seo new file mode 120000 index 0000000..79d145a --- /dev/null +++ b/.codex/skills/programmatic-seo @@ -0,0 +1 @@ +../../marketing-skill/programmatic-seo \ No newline at end of file diff --git a/.codex/skills/referral-program b/.codex/skills/referral-program new file mode 120000 index 0000000..e26de80 --- /dev/null +++ b/.codex/skills/referral-program @@ -0,0 +1 @@ +../../marketing-skill/referral-program \ No newline at end of file diff --git a/.codex/skills/schema-markup b/.codex/skills/schema-markup new file mode 120000 index 0000000..68d1cfb --- /dev/null +++ b/.codex/skills/schema-markup @@ -0,0 +1 @@ +../../marketing-skill/schema-markup \ No newline at end of file diff --git a/.codex/skills/seo-audit b/.codex/skills/seo-audit new file mode 120000 index 0000000..c592c7b --- /dev/null +++ b/.codex/skills/seo-audit @@ -0,0 +1 @@ +../../marketing-skill/seo-audit \ No newline at end of file diff --git a/.codex/skills/signup-flow-cro b/.codex/skills/signup-flow-cro new file mode 120000 index 0000000..0c9347d --- /dev/null +++ b/.codex/skills/signup-flow-cro @@ -0,0 +1 @@ +../../marketing-skill/signup-flow-cro \ No newline at end of file diff --git a/.codex/skills/site-architecture b/.codex/skills/site-architecture new file mode 120000 index 0000000..b539900 --- /dev/null +++ b/.codex/skills/site-architecture @@ -0,0 +1 @@ +../../marketing-skill/site-architecture \ No newline at end of file diff --git a/.codex/skills/social-content b/.codex/skills/social-content new file mode 120000 index 0000000..1bb1868 --- /dev/null +++ b/.codex/skills/social-content @@ -0,0 +1 @@ +../../marketing-skill/social-content \ No newline at end of file diff --git a/.codex/skills/social-media-manager b/.codex/skills/social-media-manager new file mode 120000 index 0000000..7481b3d --- /dev/null +++ b/.codex/skills/social-media-manager @@ -0,0 +1 @@ +../../marketing-skill/social-media-manager \ No newline at end of file diff --git a/.github/workflows/virustotal-scan.yml b/.github/workflows/virustotal-scan.yml index ff2e2d2..5d65505 100644 --- a/.github/workflows/virustotal-scan.yml +++ b/.github/workflows/virustotal-scan.yml @@ -29,10 +29,12 @@ jobs: run: | mkdir -p /tmp/vt-scan + # Only scan executable/binary-capable files — skip text-only formats + # (.md, .py, .json, .yml are plain text; VT adds no value scanning them) CHANGED=$(git diff --name-only \ ${{ github.event.pull_request.base.sha }} \ ${{ github.sha }} \ - | grep -E '\.(js|ts|py|sh|json|yml|yaml|md|mjs|cjs)$' || true) + | grep -E '\.(js|ts|sh|mjs|cjs|exe|dll|so|bin|wasm)$' || true) if [ -z "$CHANGED" ]; then echo "No scannable files changed" diff --git a/README.md b/README.md index a294f80..072fc35 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Claude Skills Library -**134 production-ready skill packages for Claude Code, OpenAI Codex, and OpenClaw** — reusable expertise bundles that transform AI agents into specialized professionals across engineering, product, marketing, compliance, and more. +**169 production-ready skill packages for Claude Code, OpenAI Codex, and OpenClaw** — reusable expertise bundles that transform AI agents into specialized professionals across engineering, product, marketing, compliance, and more. [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![Skills](https://img.shields.io/badge/Skills-134-brightgreen.svg)](#skills-overview) +[![Skills](https://img.shields.io/badge/Skills-169-brightgreen.svg)](#skills-overview) [![Stars](https://img.shields.io/github/stars/alirezarezvani/claude-skills?style=flat)](https://github.com/alirezarezvani/claude-skills/stargazers) [![SkillCheck Validated](https://img.shields.io/badge/SkillCheck-Validated-4c1)](https://getskillcheck.com) @@ -31,7 +31,7 @@ Skills are modular instruction packages that give AI agents domain expertise the /plugin install engineering-skills@claude-code-skills # 21 core engineering /plugin install engineering-advanced-skills@claude-code-skills # 25 POWERFUL-tier /plugin install product-skills@claude-code-skills # 8 product skills -/plugin install marketing-skills@claude-code-skills # 7 marketing skills +/plugin install marketing-skills@claude-code-skills # 42 marketing skills /plugin install ra-qm-skills@claude-code-skills # 12 regulatory/quality /plugin install pm-skills@claude-code-skills # 6 project management /plugin install c-level-skills@claude-code-skills # 10 C-level advisory (full C-suite) @@ -78,7 +78,7 @@ git clone https://github.com/alirezarezvani/claude-skills.git | **🧠 Self-Improving Agent** | 5+2 | Auto-memory curation, pattern promotion, skill extraction, memory health | [engineering-team/self-improving-agent](engineering-team/self-improving-agent/) | | **⚔ Engineering — POWERFUL** | 25 | Agent designer, RAG architect, database designer, CI/CD builder, security auditor, MCP builder | [engineering/](engineering/) | | **šŸŽÆ Product** | 8 | Product manager, agile PO, strategist, UX researcher, UI design, landing pages, SaaS scaffolder | [product-team/](product-team/) | -| **šŸ“£ Marketing** | 7 | Content creator, demand gen, PMM strategy, ASO, social media, campaign analytics, prompt engineering | [marketing-skill/](marketing-skill/) | +| **šŸ“£ Marketing** | 42 | 7 pods: Content (8), SEO (5), CRO (6), Channels (5), Growth (4), Intelligence (4), Sales (2) + context foundation + orchestration router. 27 Python tools. | [marketing-skill/](marketing-skill/) | | **šŸ“‹ Project Management** | 6 | Senior PM, scrum master, Jira, Confluence, Atlassian admin, templates | [project-management/](project-management/) | | **šŸ„ Regulatory & QM** | 12 | ISO 13485, MDR 2017/745, FDA, ISO 27001, GDPR, CAPA, risk management | [ra-qm-team/](ra-qm-team/) | | **šŸ’¼ C-Level Advisory** | 28 | Full C-suite (10 roles) + orchestration + board meetings + culture & collaboration | [c-level-advisor/](c-level-advisor/) | diff --git a/SKILL-AUTHORING-STANDARD.md b/SKILL-AUTHORING-STANDARD.md new file mode 100644 index 0000000..440891b --- /dev/null +++ b/SKILL-AUTHORING-STANDARD.md @@ -0,0 +1,458 @@ +# Skill Authoring Standard + +The DNA of every skill in this repository. Follow this standard when creating new skills or upgrading existing ones. + +--- + +## SKILL.md Template + +```markdown +--- +name: skill-name +description: "When to use this skill. Include trigger keywords and phrases users might say. Mention related skills for disambiguation." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: domain-name + updated: YYYY-MM-DD +--- + +# Skill Name + +You are an expert in [domain]. Your goal is [specific outcome for the user]. + +## Before Starting + +**Check for context first:** +If `[domain]-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Gather this context (ask if not provided): + +### 1. Current State +- What exists today? +- What's working / not working? + +### 2. Goals +- What outcome do they want? +- What constraints exist? + +### 3. [Domain-Specific Context] +- [Questions specific to this skill] + +## How This Skill Works + +This skill supports [N] modes: + +### Mode 1: Build from Scratch +When starting fresh — no existing [artifact] to work with. + +### Mode 2: Optimize Existing +When improving something that already exists. Analyze what's working, identify gaps, recommend changes. + +### Mode 3: [Situation-Specific] +When [specific scenario that needs a different approach]. + +## [Core Content Sections] + +[Action-oriented workflow. Not a textbook — a practitioner guiding you through it.] + +[Tables for structured information. Checklists for processes. Examples for clarity.] + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- [Trigger 1: specific condition → what to flag] +- [Trigger 2: specific condition → what to flag] +- [Trigger 3: specific condition → what to flag] + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| [Common request 1] | [Specific deliverable with format] | +| [Common request 2] | [Specific deliverable with format] | +| [Common request 3] | [Specific deliverable with format] | + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding has all three +- **Actions have owners and deadlines** — no "we should consider" +- **Confidence tagging** — 🟢 verified / 🟔 medium / šŸ”“ assumed + +## Related Skills + +- **skill-name**: Use when [specific scenario]. NOT for [disambiguation]. +- **skill-name**: Use when [specific scenario]. NOT for [disambiguation]. +- **skill-name**: Use when [specific scenario]. NOT for [disambiguation]. +``` + +--- + +## The 10 Patterns + +### Pattern 1: Context-First + +Every skill checks for domain context before asking questions. Only ask for what's missing. + +**Implementation:** +```markdown +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. +Use that context and only ask for information not already covered. +``` + +**Domain context files:** + +| Domain | Context File | Created By | +|--------|-------------|-----------| +| C-Suite | `company-context.md` | `/cs:setup` (cs-onboard skill) | +| Marketing | `marketing-context.md` | marketing-context skill | +| Engineering | `project-context.md` | codebase-onboarding skill | +| Product | `product-context.md` | product-strategist skill | +| RA/QM | `regulatory-context.md` | regulatory-affairs-head skill | + +**Rules:** +- If context exists → read it, use it, only ask for gaps +- If context doesn't exist → offer to create it (auto-draft from available info) +- Never dump all questions at once — conversational, one section at a time +- Push for verbatim language — exact customer/user phrases beat polished descriptions + +--- + +### Pattern 2: Practitioner Voice + +Every skill opens with an expert persona and clear goal. Not a textbook — a senior practitioner coaching you. + +**Implementation:** +```markdown +You are an expert in [domain]. Your goal is [outcome]. +``` + +**Rules:** +- Write as someone who has done this 100 times +- Use contractions, direct language +- If something sounds like a Wikipedia article, rewrite it +- Opinionated > neutral. State what works and what doesn't. +- "Do X" beats "You might consider X" +- Industry jargon is fine when talking to practitioners — explain when talking to founders + +**Anti-patterns:** +- āŒ "This skill provides comprehensive coverage of..." +- āŒ "The following section outlines the various approaches to..." +- āŒ "It is recommended that one should consider..." +- āœ… "You are an expert in SaaS pricing. Your goal is to help design pricing that captures value." +- āœ… "Lead with their world, not yours." +- āœ… "If it sounds like marketing copy, rewrite it." + +--- + +### Pattern 3: Multi-Mode Workflows + +Most skills have 2-3 natural entry points. Design for all of them. + +**Implementation:** +```markdown +## How This Skill Works + +### Mode 1: Build from Scratch +When starting fresh — [describe the greenfield scenario]. + +### Mode 2: Optimize Existing +When [artifact] exists but isn't performing. Analyze → identify gaps → recommend. + +### Mode 3: [Situation-Specific] +When [edge case or specific scenario that needs a different approach]. +``` + +**Common mode pairs:** + +| Skill Type | Mode 1 | Mode 2 | Mode 3 | +|-----------|--------|--------|--------| +| CRO skills | Audit a page | Redesign flow | A/B test specific element | +| Content skills | Write new | Rewrite/optimize | Repurpose for channel | +| SEO skills | Full audit | Fix specific issue | Competitive gap analysis | +| Strategy skills | Create plan | Review/critique plan | Pivot existing plan | +| Analytics skills | Set up tracking | Debug tracking | Analyze data | + +**Rules:** +- Mode 2 (optimize) should ask for current performance data +- If user has performance data → use it to inform recommendations +- Each mode should be self-contained (don't assume they read the other modes) + +--- + +### Pattern 4: Related Skills Navigation + +Every skill ends with a curated list of related skills. Not just links — **when to use each and when NOT to.** + +**Implementation:** +```markdown +## Related Skills + +- **copywriting**: For landing page and web copy. NOT for email sequences or ad copy. +- **page-cro**: For optimizing any marketing page. NOT for signup flows (use signup-flow-cro). +- **email-sequence**: For lifecycle/nurture emails. NOT for cold outreach (use cold-email). +``` + +**Rules:** +- Include 3-7 related skills (not all of them — curate) +- Each entry: skill name + WHEN to use + WHEN NOT TO (disambiguation) +- Cross-references must be bidirectional (A mentions B, B mentions A) +- Include cross-domain references when relevant (e.g., marketing skill → business-growth skill) +- Group by relationship type if >5: "Works with", "Instead of", "After this" + +--- + +### Pattern 5: Reference Separation + +SKILL.md is the workflow. Reference docs are the knowledge base. Keep them separate. + +**Implementation:** +``` +skill-name/ +ā”œā”€ā”€ SKILL.md # ≤10KB — what to do, how to decide, when to act +ā”œā”€ā”€ references/ +│ ā”œā”€ā”€ frameworks.md # Deep framework catalog +│ ā”œā”€ā”€ benchmarks.md # Industry data and benchmarks +│ ā”œā”€ā”€ platform-specs.md # Platform-specific details +│ └── examples.md # Real-world examples +ā”œā”€ā”€ templates/ +│ └── template.md # User-fillable templates +└── scripts/ + └── tool.py # Python automation +``` + +**Rules:** +- SKILL.md ≤10KB — if it's longer, move content to references +- SKILL.md links to references inline: `See [references/frameworks.md](references/frameworks.md) for the full catalog.` +- References are loaded on demand — zero startup cost +- Each reference doc is self-contained (can be read independently) +- Templates are user-fillable files with clear placeholder markers + +--- + +### Pattern 6: Proactive Triggers + +Skills surface issues without being asked when they detect patterns in context. + +**Implementation:** +```markdown +## Proactive Triggers + +Surface these without being asked: + +- **[Condition]** → [What to flag and why] +- **[Condition]** → [What to flag and why] +``` + +**Rules:** +- 4-6 triggers per skill +- Each trigger: specific condition + business consequence +- Triggers should be things the user wouldn't think to ask about +- Format: condition → flag → recommended action +- Don't trigger on obvious things — trigger on hidden risks + +**Examples:** +- SEO: "Keyword cannibalization detected — two pages targeting the same term" → flag +- Pricing: "Conversion rate >40% — likely underpriced" → flag +- Content: "No content updated in 6+ months" → flag +- CRO: "Form has >7 fields with no multi-step" → flag + +--- + +### Pattern 7: Output Artifacts + +Map common requests to specific, concrete deliverables. + +**Implementation:** +```markdown +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Help with pricing" | Pricing recommendation with tier structure, value metrics, and competitive positioning | +| "Audit my SEO" | SEO scorecard (0-100) with prioritized fixes and quick wins | +``` + +**Rules:** +- 4-6 artifacts per skill +- Each artifact has a specific format (scorecard, matrix, plan, audit, template) +- Artifacts are actionable — not just analysis, but recommendations with next steps +- Include what the output looks like (table? checklist? narrative?) + +--- + +### Pattern 8: Quality Loop + +Skills self-verify before presenting findings. + +**Implementation:** +```markdown +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Peer-verify: cross-functional claims validated by the owning skill +- Output format: Bottom Line → What (with confidence) → Why → How to Act → Your Decision +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. +``` + +**Rules:** +- Every finding tagged with confidence level +- Assumptions explicitly marked as assumptions +- "I don't know" > fake confidence +- Cross-functional claims reference the relevant skill +- High-stakes recommendations get extra scrutiny + +--- + +### Pattern 9: Communication Standard + +Structured output format for all skill output. + +**Standard output:** +``` +BOTTOM LINE: [One sentence answer] + +WHAT: +• [Finding 1] — 🟢/🟔/šŸ”“ +• [Finding 2] — 🟢/🟔/šŸ”“ + +WHY THIS MATTERS: [Business impact] + +HOW TO ACT: +1. [Action] → [Owner] → [Deadline] + +YOUR DECISION (if needed): +Option A: [Description] — [Trade-off] +Option B: [Description] — [Trade-off] +``` + +**Rules:** +- Bottom line first — always +- Max 5 bullets per section +- Actions have owners and deadlines +- Decisions framed as options with trade-offs +- No process narration ("First I analyzed...") — results only + +--- + +### Pattern 10: Python Tools + +Stdlib-only automation that provides quantitative analysis. + +**Implementation:** +```python +#!/usr/bin/env python3 +"""Tool description — what it does in one line.""" + +import json +import sys +from collections import Counter + +def main(): + # Accept input from file arg or stdin + # Process with stdlib only + # Output JSON for programmatic use + # Also print human-readable summary + pass + +if __name__ == "__main__": + main() +``` + +**Rules:** +- **stdlib-only** — zero external dependencies (no pip install) +- **CLI-first** — run from command line with file args or stdin +- **JSON output** — structured output for integration +- **Sample data embedded** — runs with zero config for demo/testing +- **One tool, one job** — focused, not Swiss Army knife +- **Scoring tools output 0-100** — consistent scale across all tools + +**Naming convention:** `snake_case_verb_noun.py` (e.g., `seo_checker.py`, `headline_scorer.py`, `churn_risk_scorer.py`) + +--- + +## File Structure Standard + +``` +skill-name/ +ā”œā”€ā”€ SKILL.md # ≤10KB — workflow, decisions, actions +ā”œā”€ā”€ references/ # Deep knowledge (loaded on demand) +│ ā”œā”€ā”€ [topic]-guide.md # Comprehensive guide +│ ā”œā”€ā”€ [topic]-benchmarks.md # Industry data +│ └── [topic]-examples.md # Real-world examples +ā”œā”€ā”€ templates/ # User-fillable templates +│ └── [artifact]-template.md # With placeholder markers +└── scripts/ # Python automation + └── [verb]_[noun].py # Stdlib-only, CLI-first +``` + +**Naming rules:** +- Skill folder: `kebab-case` +- Python scripts: `snake_case.py` +- Reference docs: `kebab-case.md` +- Templates: `kebab-case-template.md` + +--- + +## Quality Checklist + +Before a skill is considered done: + +### Structure +- [ ] YAML frontmatter with name, description (trigger keywords), version +- [ ] Practitioner voice — "You are an expert in X. Your goal is Y." +- [ ] Context-first — checks domain context before asking questions +- [ ] Multi-mode — at least 2 workflows (build/optimize) +- [ ] SKILL.md ≤10KB — heavy content in references/ + +### Content +- [ ] Action-oriented — tells you what to do, not just what exists +- [ ] Opinionated — states what works, not just options +- [ ] Tables for structured comparisons +- [ ] Checklists for processes +- [ ] Examples for clarity + +### Integration +- [ ] Related Skills section with WHEN/NOT disambiguation +- [ ] Cross-references are bidirectional +- [ ] Listed in domain CLAUDE.md +- [ ] Listed in `.codex/skills-index.json` +- [ ] Listed in `.claude-plugin/marketplace.json` + +### Quality Standard +- [ ] Proactive Triggers (4-6 per skill) +- [ ] Output Artifacts table (4-6 per skill) +- [ ] Communication standard reference +- [ ] Confidence tagging on findings + +### Automation (if applicable) +- [ ] Python tool(s) — stdlib-only, CLI-first, JSON output +- [ ] Sample data embedded — runs with zero config +- [ ] Scoring uses 0-100 scale + +--- + +## Domain Context Files + +| Domain | File | Sections | +|--------|------|----------| +| **C-Suite** | `company-context.md` | Stage, team, burn rate, competitive landscape, strategic priorities | +| **Marketing** | `marketing-context.md` | Brand voice, style guide, target keywords, internal links map, competitor analysis, audience personas, writing examples, customer language | +| **Engineering** | `project-context.md` | Tech stack, architecture, conventions, CI/CD, testing strategy | +| **Product** | `product-context.md` | Roadmap, personas, metrics, feature priorities, user research | +| **RA/QM** | `regulatory-context.md` | Device classification, applicable standards, audit schedule, SOUP list | + +Each domain's context skill creates this file via guided interview + auto-draft from available information. + +--- + +*This standard applies to all new skills and skill upgrades across the entire repository.* +*Version: 1.0.0 | Created: 2026-03-06* diff --git a/marketing-skill/.codex/instructions.md b/marketing-skill/.codex/instructions.md new file mode 100644 index 0000000..c3d1b87 --- /dev/null +++ b/marketing-skill/.codex/instructions.md @@ -0,0 +1,42 @@ +# Marketing Skills — Codex CLI Instructions + +When working on marketing tasks, use the marketing skill system: + +## Routing + +1. **First**, read `marketing-skill/marketing-ops/SKILL.md` to identify the right specialist skill +2. **Then**, read the specialist skill's SKILL.md for detailed instructions +3. **If this is a first-time user**, recommend running `marketing-context` first + +## Context + +If `marketing-context.md` exists in the project root, read it before any marketing task. It contains brand voice, audience personas, and competitive landscape. + +## Python Tools + +All scripts in `marketing-skill/*/scripts/` are stdlib-only and CLI-first. Run them directly: + +```bash +python3 marketing-skill/content-production/scripts/content_scorer.py +python3 marketing-skill/content-humanizer/scripts/humanizer_scorer.py +python3 marketing-skill/ad-creative/scripts/ad_copy_validator.py +``` + +## Key Skills by Task + +| Task | Skill | +|------|-------| +| Write content | content-production | +| Plan content | content-strategy | +| SEO audit | seo-audit | +| AI search optimization | ai-seo | +| Page conversion | page-cro | +| Email sequences | email-sequence | +| Pricing | pricing-strategy | +| Launch planning | launch-strategy | + +## Rules + +- Never load all 42 skills at once — route to 1-2 per request +- Check marketing-context.md before starting +- Use Python tools for scoring and validation, not manual judgment diff --git a/marketing-skill/CLAUDE.md b/marketing-skill/CLAUDE.md index 4b79c88..ffcd7d0 100644 --- a/marketing-skill/CLAUDE.md +++ b/marketing-skill/CLAUDE.md @@ -1,334 +1,38 @@ -# Marketing Skills - Claude Code Guidance +# Marketing Skills — Agent Instructions -This guide covers the 4 production-ready marketing skills and their Python automation tools. +## For All Agents (Claude Code, Codex CLI, OpenClaw) -## Marketing Skills Overview +This directory contains 42 marketing skills organized into specialist pods. -**Available Skills:** -1. **content-creator/** - Content creation, brand voice, SEO optimization (2 Python tools) -2. **marketing-demand-acquisition/** - Demand generation and customer acquisition (1 Python tool) -3. **marketing-strategy-pmm/** - Product marketing and go-to-market strategy -4. **campaign-analytics/** - Multi-touch attribution, funnel conversion analysis, campaign ROI calculation (3 Python tools) +### How to Use -**Total Tools:** 6 Python automation tools, 9+ knowledge bases, 15+ templates +1. **Start with routing:** Read `marketing-ops/SKILL.md` — it has a routing matrix that maps user requests to the right skill. +2. **Check context:** If `marketing-context.md` exists, read it first. It has brand voice, personas, and competitive landscape. +3. **Load ONE skill:** Read only the specialist SKILL.md you need. Never bulk-load. -## Python Automation Tools +### Skill Map -### 1. Brand Voice Analyzer (`content-creator/scripts/brand_voice_analyzer.py`) +- `marketing-context/` — Run first to capture brand context +- `marketing-ops/` — Router (read this to know where to go) +- `content-production/` — Write content (blog posts, articles, guides) +- `content-strategy/` — Plan what content to create +- `ai-seo/` — Optimize for AI search engines (ChatGPT, Perplexity, Google AI) +- `seo-audit/` — Traditional SEO audit +- `page-cro/` — Conversion rate optimization +- `pricing-strategy/` — Pricing and packaging +- `content-humanizer/` — Fix AI-sounding content -**Purpose:** Analyzes text for formality, tone, perspective, and readability +### Python Tools -**Features:** -- Formality analysis (formal vs casual language patterns) -- Tone detection (professional, conversational, technical) -- Perspective analysis (1st person, 2nd person, 3rd person) -- Readability scoring (Flesch Reading Ease formula) -- Output formats: JSON or human-readable - -**Usage:** +27 scripts, all stdlib-only. Run directly: ```bash -# Basic analysis -python content-creator/scripts/brand_voice_analyzer.py content.txt - -# JSON output for integrations -python content-creator/scripts/brand_voice_analyzer.py content.txt json +python3 /scripts/.py [args] ``` +No pip install needed. Scripts include embedded samples for demo mode (run with no args). -**Output Example:** -``` -Brand Voice Analysis Results: -- Formality Score: 65/100 (Semi-formal) -- Tone: Professional with conversational elements -- Perspective: 2nd person (you-focused) -- Readability: 72 (College level) -``` +### Anti-Patterns -**Implementation Notes:** -- Pure Python (standard library only) -- No external API calls or ML models -- Fast local processing (<1 second for typical content) -- Works offline - -### 2. SEO Optimizer (`content-creator/scripts/seo_optimizer.py`) - -**Purpose:** Comprehensive SEO analysis with actionable recommendations - -**Features:** -- Keyword density analysis (primary + secondary keywords) -- Content structure evaluation (headings, paragraphs, lists) -- Meta tag validation (title, description) -- Readability assessment -- SEO score calculation (0-100) -- Actionable improvement recommendations - -**Usage:** -```bash -# Basic SEO analysis -python content-creator/scripts/seo_optimizer.py article.md "primary keyword" - -# With secondary keywords -python content-creator/scripts/seo_optimizer.py article.md "primary keyword" "secondary,keywords,here" - -# JSON output -python content-creator/scripts/seo_optimizer.py article.md "keyword" --json -``` - -**Output Example:** -``` -SEO Analysis Results: -- Overall SEO Score: 78/100 -- Primary Keyword Density: 1.8% (target: 1-2%) -- Secondary Keyword Usage: 5/7 keywords present -- Content Structure: Good (H2, H3 hierarchy) -- Meta Description: Present (145 chars) - -Recommendations: -1. Add primary keyword to H2 heading -2. Increase secondary keyword "conversion" usage -3. Add alt text to 2 images -``` - -**Implementation Notes:** -- 419 lines of pure algorithmic analysis -- No LLM calls or external APIs -- CLI-first design for automation -- Supports markdown and HTML input - -### 3. Demand Generation Analyzer (`marketing-demand-acquisition/scripts/`) - -**Purpose:** Analyze demand generation campaigns and acquisition funnels - -**Features:** -- Campaign performance analysis -- Acquisition channel evaluation -- Conversion funnel metrics -- ROI calculation - -**Usage:** -```bash -python marketing-demand-acquisition/scripts/demand_gen_analyzer.py campaign-data.csv -``` - -### Campaign Analytics Tools - -#### 4. Attribution Analyzer (`campaign-analytics/scripts/attribution_analyzer.py`) - -**Purpose:** Multi-touch attribution modeling across marketing channels - -**Features:** -- Five attribution models (first-touch, last-touch, linear, time-decay, position-based) -- Configurable time-decay half-life -- Per-channel credit allocation and revenue attribution -- Conversion and non-conversion journey analysis - -**Usage:** -```bash -python campaign-analytics/scripts/attribution_analyzer.py campaign_data.json -python campaign-analytics/scripts/attribution_analyzer.py campaign_data.json --model time-decay --half-life 14 -python campaign-analytics/scripts/attribution_analyzer.py campaign_data.json --format json -``` - -#### 5. Funnel Analyzer (`campaign-analytics/scripts/funnel_analyzer.py`) - -**Purpose:** Conversion funnel analysis with bottleneck detection - -**Features:** -- Stage-to-stage conversion rates and drop-off percentages -- Automatic bottleneck identification (largest absolute and relative drops) -- Overall funnel conversion rate -- Segment comparison when multiple segments provided - -**Usage:** -```bash -python campaign-analytics/scripts/funnel_analyzer.py funnel_data.json -python campaign-analytics/scripts/funnel_analyzer.py funnel_data.json --format json -``` - -#### 6. Campaign ROI Calculator (`campaign-analytics/scripts/campaign_roi_calculator.py`) - -**Purpose:** Calculate comprehensive campaign ROI metrics with benchmarking - -**Features:** -- ROI, ROAS, CPA, CPL, CAC calculation -- CTR and conversion rate metrics -- Industry benchmark comparison -- Underperformance flagging - -**Usage:** -```bash -python campaign-analytics/scripts/campaign_roi_calculator.py campaign_data.json -python campaign-analytics/scripts/campaign_roi_calculator.py campaign_data.json --format json -``` - -## Knowledge Bases - -### Content Creator References - -**Location:** `content-creator/references/` - -1. **brand_guidelines.md** - Brand voice framework - - 5 personality archetypes (Expert, Friend, Innovator, Guide, Motivator) - - Voice characteristics matrix - - Brand consistency checklist - - Industry-specific adaptations - -2. **content_frameworks.md** - 15+ content templates - - Blog post structures (how-to, listicle, case study) - - Email campaign frameworks - - Social media content patterns - - Video script templates - - Landing page copy structure - -3. **social_media_optimization.md** - Platform-specific best practices - - LinkedIn: Professional tone, 1,300 chars, hashtag strategy - - Twitter/X: Concise, 280 chars, thread patterns - - Instagram: Visual-first, captions, hashtag limits - - Facebook: Conversational, engagement tactics - - TikTok: Short-form video, trending sounds - -### Campaign Analytics References - -**Location:** `campaign-analytics/references/` - -1. **attribution-models-guide.md** - Deep dive into 5 attribution models with formulas, pros/cons, selection criteria -2. **campaign-metrics-benchmarks.md** - Industry benchmarks by channel and vertical for CTR, CPC, CPM, CPA, ROAS -3. **funnel-optimization-framework.md** - Stage-by-stage optimization strategies, common bottlenecks, best practices - -## User Templates - -### Content Creator Assets - -**Location:** `content-creator/assets/` - -- Content calendar template -- SEO checklist -- Social media posting schedule -- Content brief template -- Campaign planning worksheet - -**Usage:** Copy template and customize for your needs - -## Integration Patterns - -### Pattern 1: Content Quality Workflow - -```bash -# 1. Create draft content -vim blog-post.md - -# 2. Analyze brand voice -python content-creator/scripts/brand_voice_analyzer.py blog-post.md - -# 3. Optimize for SEO -python content-creator/scripts/seo_optimizer.py blog-post.md "target keyword" - -# 4. Refine based on feedback - -# 5. Publish -``` - -### Pattern 2: Campaign Planning - -```bash -# 1. Reference frameworks -cat content-creator/references/content_frameworks.md - -# 2. Draft campaign content - -# 3. Validate against brand guidelines -cat content-creator/references/brand_guidelines.md - -# 4. Analyze performance -python marketing-demand-acquisition/scripts/demand_gen_analyzer.py campaign-results.csv -``` - -### Pattern 3: Campaign Performance Analysis - -```bash -# 1. Analyze multi-touch attribution -python campaign-analytics/scripts/attribution_analyzer.py journey_data.json - -# 2. Identify funnel bottlenecks -python campaign-analytics/scripts/funnel_analyzer.py funnel_data.json - -# 3. Calculate campaign ROI -python campaign-analytics/scripts/campaign_roi_calculator.py campaign_data.json - -# 4. Document findings using templates -# Reference: campaign-analytics/assets/campaign_report_template.md -``` - -## Development Commands - -```bash -# Content analysis -python content-creator/scripts/brand_voice_analyzer.py content.txt -python content-creator/scripts/brand_voice_analyzer.py content.txt json - -# SEO optimization -python content-creator/scripts/seo_optimizer.py article.md "main keyword" -python content-creator/scripts/seo_optimizer.py article.md "main keyword" "secondary,keywords" - -# Demand generation -python marketing-demand-acquisition/scripts/demand_gen_analyzer.py data.csv - -# Campaign analytics -python campaign-analytics/scripts/attribution_analyzer.py campaign_data.json -python campaign-analytics/scripts/funnel_analyzer.py funnel_data.json -python campaign-analytics/scripts/campaign_roi_calculator.py campaign_data.json -``` - -## Quality Standards - -**All marketing Python tools must:** -- Use standard library only (no external dependencies) -- Support both JSON and human-readable output -- Provide clear error messages -- Return appropriate exit codes -- Process files locally (no API calls) - -## Roadmap - -**Current (Phase 1-2):** 4 skills deployed -- āœ… Content creator (brand voice + SEO) -- āœ… Demand generation & acquisition -- āœ… Product marketing strategy -- āœ… Campaign analytics (attribution, funnel, ROI) - -**Phase 3 (Q2 2026):** Marketing expansion -- SEO content optimizer (advanced) -- Social media manager (multi-platform) -- Email marketing automation - -**Phase 4 (Q3 2026):** Growth marketing -- Growth hacking frameworks -- Viral content analyzer -- Influencer collaboration tools - -See `marketing_skills_roadmap.md` for detailed expansion plans. - -## Related Skills - -- **Product Team:** User research, persona generation → `../product-team/` -- **Engineering:** Web analytics integration → `../engineering-team/` -- **C-Level:** Strategic marketing planning → `../c-level-advisor/` - -## Best Practices - -1. **Brand Consistency** - Always reference brand_guidelines.md before creating content -2. **SEO-First** - Run seo_optimizer.py on all published content -3. **Data-Driven** - Use analytics to inform content strategy -4. **Platform-Specific** - Adapt content using social_media_optimization.md guidelines -5. **Iterative** - Analyze, optimize, republish - -## Additional Resources - -- **Marketing Roadmap:** `marketing_skills_roadmap.md` -- **Team Overview:** `README.md` -- **Main Documentation:** `../CLAUDE.md` - ---- - -**Last Updated:** February 2026 -**Skills Deployed:** 4/4 marketing skills production-ready -**Total Tools:** 6 Python automation tools +āŒ Don't read all 42 SKILL.md files +āŒ Don't skip marketing-context.md if it exists +āŒ Don't use content-creator (deprecated → use content-production) +āŒ Don't install pip packages for Python tools diff --git a/marketing-skill/MARKETING-EXECUTION-PLAN.md b/marketing-skill/MARKETING-EXECUTION-PLAN.md new file mode 100644 index 0000000..4f74ea5 --- /dev/null +++ b/marketing-skill/MARKETING-EXECUTION-PLAN.md @@ -0,0 +1,334 @@ +# Marketing Team Expansion — Execution Plan + +## Final Architecture + +``` +CMO Advisor (c-level-advisor/cmo-advisor/) + │ + │ reads company-context.md + marketing-context.md + │ +Marketing Ops (router + orchestrator) + │ + ā”œā”€ā”€ Content Pod (8) + │ ā”œā”€ā”€ content-creator .......... [UPGRADE] add context integration, quality loop + │ ā”œā”€ā”€ content-strategy ......... [IMPORT] from workspace + │ ā”œā”€ā”€ copywriting .............. [IMPORT] from workspace + │ ā”œā”€ā”€ copy-editing ............. [IMPORT] from workspace + │ ā”œā”€ā”€ social-content ........... [IMPORT] from workspace + │ ā”œā”€ā”€ marketing-ideas .......... [IMPORT] from workspace + │ ā”œā”€ā”€ content-production ....... [NEW] research→write→optimize pipeline + │ └── content-humanizer ........ [NEW] AI watermark removal, voice injection + │ + ā”œā”€ā”€ SEO Pod (5) + │ ā”œā”€ā”€ seo-audit ................ [IMPORT] from workspace + add seo_checker.py + │ ā”œā”€ā”€ programmatic-seo ......... [IMPORT] from workspace + │ ā”œā”€ā”€ ai-seo ................... [NEW] AEO, GEO, LLMO optimization + │ ā”œā”€ā”€ schema-markup ............ [NEW] JSON-LD, structured data + │ └── site-architecture ........ [NEW] URL structure, nav, internal linking + │ + ā”œā”€ā”€ CRO Pod (6) + │ ā”œā”€ā”€ page-cro ................. [IMPORT] from workspace + │ ā”œā”€ā”€ form-cro ................. [IMPORT] from workspace + │ ā”œā”€ā”€ signup-flow-cro .......... [IMPORT] from workspace + │ ā”œā”€ā”€ onboarding-cro ........... [IMPORT] from workspace + │ ā”œā”€ā”€ popup-cro ................ [IMPORT] from workspace + │ └── paywall-upgrade-cro ...... [IMPORT] from workspace + │ + ā”œā”€ā”€ Channels Pod (5) + │ ā”œā”€ā”€ email-sequence ........... [IMPORT] from workspace + │ ā”œā”€ā”€ paid-ads ................. [IMPORT] from workspace + │ ā”œā”€ā”€ social-media-manager ..... [UPGRADE] rename + expand from social-media-analyzer + │ ā”œā”€ā”€ cold-email ............... [NEW] B2B outreach sequences + │ └── ad-creative .............. [NEW] bulk ad generation + iteration + │ + ā”œā”€ā”€ Growth Pod (3) + │ ā”œā”€ā”€ ab-test-setup ............ [IMPORT] from workspace + │ ā”œā”€ā”€ referral-program ......... [NEW] referral + affiliate programs + │ └── free-tool-strategy ....... [NEW] engineering as marketing + │ + ā”œā”€ā”€ Intelligence Pod (4) + │ ā”œā”€ā”€ campaign-analytics ....... [UPGRADE] add cross-channel synthesis + │ ā”œā”€ā”€ competitor-alternatives .. [IMPORT] from workspace + │ ā”œā”€ā”€ marketing-psychology ..... [IMPORT] from workspace + │ └── analytics-tracking ....... [NEW] GA4, GTM, event tracking setup + │ + └── Sales & GTM Pod (2) + ā”œā”€ā”€ launch-strategy .......... [IMPORT] from workspace + └── pricing-strategy ......... [NEW] pricing, packaging, monetization + + Standalone (keep in place, no pod): + ā”œā”€ā”€ marketing-demand-acquisition . [KEEP] already in repo + ā”œā”€ā”€ marketing-strategy-pmm ....... [KEEP] already in repo + ā”œā”€ā”€ app-store-optimization ....... [KEEP] already in repo + └── prompt-engineer-toolkit ...... [KEEP] already in repo + + Cross-Domain References (marketing-ops routes to these): + ā”œā”€ā”€ business-growth/revenue-operations/ (RevOps) + ā”œā”€ā”€ business-growth/sales-engineer/ (Sales Enablement) + ā”œā”€ā”€ business-growth/customer-success-manager/ (Churn Prevention) + ā”œā”€ā”€ product-team/landing-page-generator/ (Landing Pages) + ā”œā”€ā”€ product-team/competitive-teardown/ (Competitive Analysis) + └── engineering-team/email-template-builder/ (Email Templates) +``` + +## Totals + +| Action | Count | +|--------|-------| +| Import from workspace | 20 | +| Upgrade existing | 3 | +| Build new | 13 | +| Keep as-is | 4 | +| Cross-domain refs | 6 | +| **Total marketing skills** | **39** | +| **New Python tools** | ~20 | +| **New reference docs** | ~25 | +| **New agents** | 5-8 | + +--- + +## Iteration 1: Foundation + Import (20 workspace skills + 2 new) + +### 1A: Create branch and foundation skills + +**marketing-context/** (NEW — the foundation every skill reads) +``` +marketing-context/ +ā”œā”€ā”€ SKILL.md # How to use, interview flow +ā”œā”€ā”€ templates/ +│ ā”œā”€ā”€ brand-voice.md # Voice pillars, tone by content type, terminology +│ ā”œā”€ā”€ style-guide.md # Grammar, formatting, capitalization +│ ā”œā”€ā”€ target-keywords.md # Keyword clusters, search intent, current rankings +│ ā”œā”€ā”€ internal-links-map.md # Key pages, anchor text, topic clusters +│ ā”œā”€ā”€ competitor-analysis.md # Primary competitors, strategies, gaps +│ ā”œā”€ā”€ writing-examples.md # 3-5 exemplary pieces with annotations +│ └── audience-personas.md # ICP, segments, pain points, buying triggers +└── scripts/ + └── context_validator.py # Validates completeness of context files +``` +Inspired by: SEO Machine's 8 context files + marketingskills' product-marketing-context +Key difference: Templates (user fills in), not static files. Validator script checks completeness. + +**marketing-ops/** (NEW — the router) +``` +marketing-ops/ +ā”œā”€ā”€ SKILL.md # Router logic, pod assignments, escalation +ā”œā”€ā”€ references/ +│ ā”œā”€ā”€ routing-matrix.md # Trigger keywords → skill mapping (all 39 + 6 cross-domain) +│ ā”œā”€ā”€ campaign-workflow.md # End-to-end campaign orchestration steps +│ └── quality-checklist.md # Pre-delivery quality gate (mirrors C-Suite standard) +└── scripts/ + └── campaign_tracker.py # Track campaign status, tasks, owners, deadlines +``` + +### 1B: Import 20 workspace skills + +For each imported skill: +1. Copy from `~/.openclaw/workspace/skills/{name}/` to `marketing-skill/{name}/` +2. Verify YAML frontmatter (name, description, license, metadata) +3. Add `## Related Skills` section with cross-references +4. Add `## Integration` table (which pod, which skills it works with, cross-domain refs) +5. Add `## Communication` section (references marketing quality standard) + +**Import batch (parallel — 4 subagents):** + +| Subagent | Skills | Pod | +|----------|--------|-----| +| content-importer | content-strategy, copywriting, copy-editing, social-content, marketing-ideas | Content | +| seo-cro-importer | seo-audit, programmatic-seo, page-cro, form-cro, signup-flow-cro | SEO + CRO | +| cro-channel-importer | onboarding-cro, popup-cro, paywall-upgrade-cro, email-sequence, paid-ads | CRO + Channels | +| growth-intel-importer | ab-test-setup, competitor-alternatives, marketing-psychology, launch-strategy, brand-guidelines | Growth + Intel + GTM | + +Each subagent: +- Copies skill folder +- Adds Related Skills section +- Adds Integration table +- Adds Communication standard reference +- Standardizes YAML frontmatter +- Does NOT add Python tools yet (that's Iteration 3) + +### 1C: Upgrade 3 existing skills + +| Skill | Changes | +|-------|---------| +| content-creator | Add context integration (reads marketing-context), Related Skills, Communication standard | +| social-media-analyzer → social-media-manager | Rename, expand SKILL.md from analyzer to full manager (scheduling, strategy, community) | +| campaign-analytics | Add cross-channel synthesis section, Related Skills, Communication standard | + +### 1D: Update CLAUDE.md + marketplace + skills-index + +- Rewrite `marketing-skill/CLAUDE.md` (like we did for C-Suite) +- Update `.claude-plugin/marketplace.json` +- Update `.codex/skills-index.json` +- Update root `CLAUDE.md` skill counts +- Update `README.md` badge + counts + +### Iteration 1 Deliverables +- [ ] Branch `feat/marketing-expansion` +- [ ] marketing-context/ (foundation) +- [ ] marketing-ops/ (router) +- [ ] 20 imported skills (standardized) +- [ ] 3 upgraded skills +- [ ] Updated CLAUDE.md, marketplace, skills-index +- [ ] PR opened + +--- + +## Iteration 2: Build 13 New Skills (parallel subagents) + +### 2A: Content + SEO batch (5 skills — 2 subagents) + +**Subagent: content-builder** +| Skill | Key Deliverables | +|-------|-----------------| +| content-production | SKILL.md, references/production-pipeline.md, references/content-brief-template.md, scripts/content_scorer.py (readability + SEO + humanity score), scripts/outline_generator.py | +| content-humanizer | SKILL.md, references/ai-patterns-checklist.md, references/voice-injection-guide.md, scripts/humanizer_scorer.py (detect AI patterns: em-dashes, filler, passive, hedging) | + +**Subagent: seo-builder** +| Skill | Key Deliverables | +|-------|-----------------| +| ai-seo | SKILL.md, references/aeo-guide.md (answer engine optimization), references/llm-citation-tactics.md, references/ai-search-landscape.md | +| schema-markup | SKILL.md, references/schema-types-guide.md, references/implementation-patterns.md, scripts/schema_validator.py (validates JSON-LD) | +| site-architecture | SKILL.md, references/url-structure-guide.md, references/internal-linking-strategy.md, scripts/sitemap_analyzer.py | + +### 2B: Channels + Growth batch (4 skills — 2 subagents) + +**Subagent: channels-builder** +| Skill | Key Deliverables | +|-------|-----------------| +| cold-email | SKILL.md, references/outreach-frameworks.md (AIDA, PAS, BAB), references/deliverability-guide.md, templates/sequence-templates.md, scripts/email_sequence_analyzer.py | +| ad-creative | SKILL.md, references/ad-frameworks.md (by platform), references/creative-testing-guide.md, scripts/headline_scorer.py, scripts/ad_copy_generator.py | + +**Subagent: growth-builder** +| Skill | Key Deliverables | +|-------|-----------------| +| referral-program | SKILL.md, references/referral-mechanics.md, references/program-types.md (one-sided, two-sided, tiered), scripts/referral_roi_calculator.py | +| free-tool-strategy | SKILL.md, references/tool-types.md (calculators, generators, analyzers, checkers), references/build-vs-buy.md, scripts/tool_roi_estimator.py | + +### 2C: Intelligence + Sales batch (4 skills — 2 subagents) + +**Subagent: intel-builder** +| Skill | Key Deliverables | +|-------|-----------------| +| analytics-tracking | SKILL.md, references/ga4-setup-guide.md, references/gtm-patterns.md, references/event-taxonomy.md, scripts/tracking_plan_generator.py | +| pricing-strategy | SKILL.md, references/pricing-models.md (value, cost-plus, competitor, dynamic), references/packaging-guide.md, scripts/pricing_modeler.py, scripts/willingness_to_pay_analyzer.py | + +**Subagent: (main agent handles directly)** +These are kept lean — no subagent needed: +- Update marketing-ops routing matrix with all 13 new skills +- Cross-reference all new skills with existing pods + +### Iteration 2 Deliverables +- [ ] 13 new skills built (SKILL.md + refs + scripts) +- [ ] All integrated into marketing-ops routing matrix +- [ ] All cross-referenced with Related Skills +- [ ] Commit + push + +--- + +## Iteration 3: Python Tools for Knowledge-Only Skills + +Add automation to the 20 imported workspace skills (currently zero scripts). + +### Priority 1: SEO + Content tools (highest impact) +| Skill | Script | Purpose | +|-------|--------|---------| +| seo-audit | seo_checker.py | On-page SEO scoring (0-100): title, meta, headings, links, keyword density | +| seo-audit | keyword_density_analyzer.py | Keyword distribution + stuffing detection | +| content-strategy | topic_cluster_mapper.py | Map topic clusters, identify gaps, suggest pillar content | +| copywriting | headline_scorer.py | Score headlines: power words, emotional triggers, length, clarity | +| copy-editing | readability_scorer.py | Flesch Reading Ease, grade level, passive voice, sentence complexity | + +### Priority 2: CRO tools +| Skill | Script | Purpose | +|-------|--------|---------| +| page-cro | conversion_audit.py | Above-fold analysis, CTA scoring, trust signals, friction points | +| form-cro | form_friction_analyzer.py | Field count, required fields, multi-step scoring | +| signup-flow-cro | signup_funnel_analyzer.py | Step analysis, drop-off estimation | + +### Priority 3: Channel + Growth tools +| Skill | Script | Purpose | +|-------|--------|---------| +| paid-ads | roas_calculator.py | ROAS, CPA, budget allocation optimizer | +| email-sequence | email_flow_designer.py | Sequence timing, open/click estimation | +| ab-test-setup | sample_size_calculator.py | Statistical significance, test duration estimator | +| competitor-alternatives | competitor_matrix_builder.py | Feature comparison matrix generator | + +### Priority 4: Intelligence tools +| Skill | Script | Purpose | +|-------|--------|---------| +| campaign-analytics | channel_mixer.py | Cross-channel attribution synthesis | +| marketing-psychology | persuasion_audit.py | Score content against Cialdini's 6 principles | +| launch-strategy | launch_readiness_scorer.py | Pre-launch checklist scoring | + +### Iteration 3 Deliverables +- [ ] ~18 new Python scripts (stdlib-only, CLI-first, JSON output) +- [ ] All scripts have embedded sample data for zero-config runs +- [ ] Commit + push + +--- + +## Iteration 4: Quality Upgrade (C-Suite Standard) + +Apply to ALL 39 marketing skills: + +### 4A: Add to every skill +- [ ] Proactive Triggers (5-6 context-driven alerts per skill) +- [ ] Output Artifacts table (request → deliverable mapping) +- [ ] Communication standard reference +- [ ] Quality loop integration (self-verify, peer-verify) + +### 4B: Add marketing-specific agents +| Agent | Location | Purpose | +|-------|----------|---------| +| content-analyzer | marketing-ops/agents/ | Analyzes content for SEO, readability, brand voice | +| seo-optimizer | marketing-ops/agents/ | On-page SEO recommendations | +| meta-creator | marketing-ops/agents/ | Meta title/description generation | +| headline-generator | marketing-ops/agents/ | Headline variations + scoring | +| cro-analyst | marketing-ops/agents/ | CRO audit for any page | + +Inspired by SEO Machine's 10 agents, but lean (markdown agents, not Python services). + +### 4C: Parity check +Run same audit as C-Suite: +- [ ] All 39 skills: Keywords āœ…, QuickStart āœ…, Related Skills āœ…, Integration āœ…, Proactive āœ…, Outputs āœ…, Communication āœ… +- [ ] All Python scripts: syntax valid, sample data works, JSON output +- [ ] All cross-references: bidirectional (A references B, B references A) +- [ ] Marketing-ops routing matrix: all 39 skills + 6 cross-domain + +### Iteration 4 Deliverables +- [ ] Quality loop on all 39 skills +- [ ] 5 marketing agents +- [ ] Parity check passed +- [ ] Final commit + PR merge-ready + +--- + +## Execution Timeline + +| Iteration | Work | Subagents | Est. Files | +|-----------|------|-----------|-----------| +| 1: Foundation + Import | 22 skills (2 new + 20 import) + 3 upgrades + metadata | 4 | ~80 | +| 2: New Skills | 13 new skills | 6 | ~100 | +| 3: Python Tools | ~18 scripts | 2-3 | ~18 | +| 4: Quality Upgrade | Quality loop + agents + parity | 2-3 | ~50 | +| **Total** | **39 skills** | **~15** | **~250** | + +--- + +## Success Criteria + +1. **39 marketing skills** organized into 7 pods + orchestration +2. **~38 Python tools** (18 existing + ~20 new), all stdlib-only +3. **5 marketing agents** (content-analyzer, seo-optimizer, meta-creator, headline-generator, cro-analyst) +4. **Full orchestration** via marketing-ops router with routing matrix +5. **Context foundation** that every skill reads (brand voice, style guide, keywords, etc.) +6. **Cross-domain routing** to 6 skills in business-growth, product-team, engineering-team +7. **C-Suite quality standard** on all skills (proactive triggers, output artifacts, quality loop) +8. **Full cross-referencing** between all skills (Related Skills sections) +9. **CMO integration** — marketing-ops connects to c-level-advisor/cmo-advisor/ +10. **Zero external dependencies** — all Python scripts stdlib-only + +--- + +*Ready for execution on Reza's go.* diff --git a/marketing-skill/MARKETING-EXPANSION-PLAN.md b/marketing-skill/MARKETING-EXPANSION-PLAN.md new file mode 100644 index 0000000..ba12065 --- /dev/null +++ b/marketing-skill/MARKETING-EXPANSION-PLAN.md @@ -0,0 +1,396 @@ +# Marketing Team Expansion — Audit & Implementation Plan + +## Executive Summary + +We have **27 marketing skills** spread across two locations (7 in repo, 20 in workspace), zero orchestration, zero automation on the workspace skills, and significant gaps vs. the two reference repos. This plan consolidates, upgrades, and fills gaps to build a **complete marketing division** — from research to production to analytics. + +--- + +## Part 1: Competitive Audit + +### Source Repo Analysis + +#### SEO Machine (TheCraigHewitt/seomachine) +- **Focus:** SEO-first content production pipeline +- **Strengths we lack:** + - šŸ”“ **Content production workflow** — `/research → /write → /optimize → /publish` pipeline (we have no production workflow) + - šŸ”“ **10 specialized agents** — content-analyzer, seo-optimizer, meta-creator, internal-linker, keyword-mapper, editor, performance, headline-generator, cro-analyst, landing-page-optimizer + - šŸ”“ **23 Python analysis modules** — search intent, keyword density, readability scoring, content length comparator, SEO quality rater, above-fold analyzer, CTA analyzer, trust signal analyzer, landing page scorer + - šŸ”“ **Data integrations** — GA4, Google Search Console, DataForSEO + - šŸ”“ **Context-driven system** — brand-voice.md, style-guide.md, writing-examples.md, target-keywords.md, internal-links-map.md, competitor-analysis.md, seo-guidelines.md, cro-best-practices.md + - šŸ”“ **Landing page system** — `/landing-write`, `/landing-audit`, `/landing-research`, `/landing-competitor`, `/landing-publish` + - 🟔 **WordPress publishing** — API integration with Yoast SEO (useful but platform-specific) + - 🟔 **AI watermark scrubber** — `/scrub` command to remove AI patterns +- **Weaknesses:** + - No orchestration layer (CMO-level strategy missing) + - No cross-channel coordination + - External dependencies (nltk, scikit-learn, beautifulsoup4) — violates our stdlib-only rule + - WordPress-coupled publishing + - No quality loop or verification + +#### Marketing Skills (coreyhaines31/marketingskills) +- **Focus:** Broad marketing skill coverage for SaaS +- **Strengths we lack:** + - šŸ”“ **product-marketing-context** as foundation — every skill reads it first (like our company-context.md) + - šŸ”“ **ai-seo** — AI search optimization (AEO, GEO, LLMO) — entirely new category + - šŸ”“ **site-architecture** — page hierarchy, navigation, URL structure, internal linking + - šŸ”“ **schema-markup** — structured data implementation + - šŸ”“ **cold-email** — B2B cold outreach emails and sequences + - šŸ”“ **ad-creative** — bulk ad creative generation and iteration + - šŸ”“ **churn-prevention** — cancel flows, save offers, dunning, payment recovery + - šŸ”“ **referral-program** — referral and affiliate programs + - šŸ”“ **pricing-strategy** — pricing, packaging, monetization + - šŸ”“ **revops** — lead lifecycle, scoring, routing, pipeline management + - šŸ”“ **sales-enablement** — sales decks, one-pagers, objection handling, demo scripts + - šŸ”“ **Cross-referencing system** — skills reference each other with Related Skills sections +- **Weaknesses:** + - Zero Python automation (knowledge-only, same as our workspace skills) + - No orchestration or routing + - No quality loop + - No agents + +### What We Have vs What They Have + +| Capability | Us (repo) | Us (workspace) | SEO Machine | Marketing Skills | +|-----------|-----------|----------------|-------------|-----------------| +| **CRO skills** | 0 | 6 (page, form, signup, onboard, popup, paywall) | 2 (cro-analyst, landing-page-optimizer) | 6 (same as ours) | +| **SEO skills** | 0 | 3 (seo-audit, programmatic-seo, competitor-alt) | Full stack (5 agents + 5 modules) | 5 (seo-audit, ai-seo, programmatic, schema, site-arch) | +| **Content/Copy** | 1 (content-creator) | 4 (content-strategy, copywriting, copy-editing, social-content) | Full pipeline (research→write→optimize→publish) | 3 (copywriting, copy-editing, cold-email) | +| **Email** | 0 | 1 (email-sequence) | 0 | 2 (email-sequence, cold-email) | +| **Paid/Ads** | 0 | 1 (paid-ads) | 0 | 2 (paid-ads, ad-creative) | +| **Analytics** | 1 (campaign-analytics) | 1 (ab-test-setup) | 3 (GA4, GSC, DataForSEO) | 1 (analytics-tracking) | +| **Strategy** | 2 (pmm, demand-acq) | 3 (content-strategy, launch-strategy, marketing-ideas) | Content prioritization | 4 (launch, pricing, marketing-ideas, marketing-psych) | +| **Growth/Retention** | 0 | 0 | 0 | 3 (referral, free-tool, churn-prevention) | +| **Sales/RevOps** | 0 | 0 | 0 | 2 (revops, sales-enablement) | +| **Python tools** | 18 scripts | 0 | 23 modules (external deps) | 0 | +| **Agents** | 0 | 0 | 10 | 0 | +| **Orchestration** | 0 | 0 | 0 | product-marketing-context (foundation only) | +| **Context system** | 0 | 0 | 8 context files | 1 (product-marketing-context) | +| **Production workflow** | 0 | 0 | Full (research→write→optimize→publish) | 0 | +| **Landing pages** | 0 | 0 | Full (5 commands) | 0 | + +--- + +## Part 2: Gap Analysis — What's Missing + +### šŸ”“ Critical Gaps (must build) + +1. **Orchestration layer** — no router, no coordination between 27 skills +2. **Content production pipeline** — no research→write→optimize→publish workflow +3. **SEO automation** — our seo-audit is knowledge-only, no analysis tools +4. **Landing page system** — no landing page creation or CRO analysis +5. **AI SEO (AEO/GEO/LLMO)** — entirely missing category, increasingly important +6. **Context system** — no brand-voice, style-guide, or product-marketing-context foundation +7. **Cross-referencing** — skills don't know about each other + +### 🟔 Important Gaps (should build) + +8. **Schema markup** — structured data implementation +9. **Site architecture** — URL structure, navigation, internal linking strategy +10. **Cold email / outreach** — B2B outreach sequences +11. **Ad creative** — bulk ad generation and iteration +12. **Churn prevention** — cancel flows, save offers, dunning +13. **Referral programs** — referral and affiliate program design +14. **Pricing strategy** — pricing, packaging, monetization +15. **RevOps** — lead lifecycle, scoring, routing +16. **Sales enablement** — sales decks, objection handling + +### ⚪ Nice to Have + +17. **WordPress/CMS publishing** — platform-specific, lower priority +18. **AI watermark scrubber** — content de-robotification +19. **Social media manager** — full management vs. current analyzer + +--- + +## Part 3: Architecture + +``` +CMO Advisor (C-Suite — strategy, budget, growth model) + │ + │ reads company-context.md + marketing-context.md + │ + Marketing Ops (router + orchestrator) + │ + ā”Œā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” + │ │ │ │ │ │ │ + Content SEO CRO Channels Growth Intel Sales + Pod Pod Pod Pod Pod Pod Pod + (8) (5) (6) (5) (4) (4) (3) + +Total: 35 skills + 1 orchestration + 1 context foundation = 37 +``` + +### Pod Breakdown + +#### Context Foundation (1 skill — NEW) +| Skill | Status | Source | +|-------|--------|--------| +| **marketing-context** | šŸ†• Build | Inspired by SEO Machine's context system + marketingskills' product-marketing-context | + +Creates and maintains: brand-voice.md, style-guide.md, target-keywords.md, internal-links-map.md, competitor-analysis.md, writing-examples.md. Every marketing skill reads this first. + +#### Orchestration (1 skill — NEW) +| Skill | Status | Source | +|-------|--------|--------| +| **marketing-ops** | šŸ†• Build | Router + campaign orchestrator (like C-Suite Chief of Staff) | + +Routes questions, coordinates campaigns, enforces quality loop, connects to CMO above. + +#### Content Pod (8 skills — 5 existing + 3 new) +| Skill | Status | Source | +|-------|--------|--------| +| content-creator | āœ… Upgrade | Repo (add context integration, quality loop) | +| content-strategy | āœ… Import | Workspace | +| copywriting | āœ… Import | Workspace | +| copy-editing | āœ… Import | Workspace | +| social-content | āœ… Import | Workspace | +| marketing-ideas | āœ… Import | Workspace | +| **content-production** | šŸ†• Build | Inspired by SEO Machine's /research→/write→/optimize pipeline | +| **content-humanizer** | šŸ†• Build | Inspired by SEO Machine's editor agent + /scrub command | + +#### SEO Pod (5 skills — 2 existing + 3 new) +| Skill | Status | Source | +|-------|--------|--------| +| seo-audit | āœ… Import | Workspace (+ add Python tools) | +| programmatic-seo | āœ… Import | Workspace | +| **ai-seo** | šŸ†• Build | From marketingskills (AEO, GEO, LLMO optimization) | +| **schema-markup** | šŸ†• Build | From marketingskills (structured data) | +| **site-architecture** | šŸ†• Build | From marketingskills (URL structure, nav, internal linking) | + +#### CRO Pod (6 skills — all existing) +| Skill | Status | Source | +|-------|--------|--------| +| page-cro | āœ… Import | Workspace | +| form-cro | āœ… Import | Workspace | +| signup-flow-cro | āœ… Import | Workspace | +| onboarding-cro | āœ… Import | Workspace | +| popup-cro | āœ… Import | Workspace | +| paywall-upgrade-cro | āœ… Import | Workspace | + +#### Channels Pod (5 skills — 3 existing + 2 new) +| Skill | Status | Source | +|-------|--------|--------| +| email-sequence | āœ… Import | Workspace | +| paid-ads | āœ… Import | Workspace | +| social-media-analyzer → social-media-manager | āœ… Upgrade | Repo (expand from analyzer to manager) | +| **cold-email** | šŸ†• Build | From marketingskills (B2B outreach) | +| **ad-creative** | šŸ†• Build | From marketingskills (bulk ad generation) | + +#### Growth & Retention Pod (4 skills — 1 existing + 3 new) +| Skill | Status | Source | +|-------|--------|--------| +| ab-test-setup | āœ… Import | Workspace | +| **churn-prevention** | šŸ†• Build | From marketingskills (cancel flows, save offers, dunning) | +| **referral-program** | šŸ†• Build | From marketingskills (referral + affiliate) | +| **free-tool-strategy** | šŸ†• Build | From marketingskills (engineering as marketing) | + +#### Intelligence Pod (4 skills — 3 existing + 1 new) +| Skill | Status | Source | +|-------|--------|--------| +| campaign-analytics | āœ… Upgrade | Repo (add cross-channel synthesis) | +| competitor-alternatives | āœ… Import | Workspace | +| marketing-psychology | āœ… Import | Workspace | +| **analytics-tracking** | šŸ†• Build | From marketingskills (GA4, GTM, event tracking setup) | + +#### Sales & GTM Pod (3 skills — 1 existing + 2 new) +| Skill | Status | Source | +|-------|--------|--------| +| launch-strategy | āœ… Import | Workspace | +| **pricing-strategy** | šŸ†• Build | From marketingskills (pricing, packaging, monetization) | +| **sales-enablement** | šŸ†• Build | From marketingskills (sales decks, objection handling) | + +### Also Import (not in pods) +| Skill | Status | +|-------|--------| +| brand-guidelines | āœ… Import (merge into marketing-context) | +| marketing-demand-acquisition | āœ… Keep in repo | +| marketing-strategy-pmm | āœ… Keep in repo | +| app-store-optimization | āœ… Keep in repo | +| prompt-engineer-toolkit | āœ… Keep in repo | + +--- + +## Part 4: Totals + +| Category | Existing (import/upgrade) | New (build) | Total | +|----------|--------------------------|-------------|-------| +| Context | 0 | 1 | 1 | +| Orchestration | 0 | 1 | 1 | +| Content | 5 + 1 upgrade | 2 | 8 | +| SEO | 2 | 3 | 5 | +| CRO | 6 | 0 | 6 | +| Channels | 2 + 1 upgrade | 2 | 5 | +| Growth | 1 | 3 | 4 | +| Intelligence | 2 + 1 upgrade | 1 | 4 | +| Sales & GTM | 1 | 2 | 3 | +| Standalone | 4 (keep as-is) | 0 | 4 | +| **TOTAL** | **24** | **15** | **41** | + +--- + +## Part 5: What Each New Skill Needs + +Every new skill gets the C-Suite quality standard: +- YAML frontmatter (name, description, license, metadata) +- Keywords section (trigger-optimized) +- Quick Start (3-step) +- Key Questions (diagnostic) +- Integration table (which skills it works with) +- Proactive Triggers (context-driven alerts) +- Output Artifacts (request → deliverable) +- Communication standard (bottom line first, structured output) +- Related Skills section (cross-references) +- Python tools (stdlib-only, CLI-first, JSON output) +- Reference docs (heavy content here, not SKILL.md) + +--- + +## Part 6: Python Tools Plan + +### Import SEO Machine concepts (rebuilt stdlib-only) +| Script | Original | Our version | +|--------|----------|-------------| +| search_intent_analyzer.py | Uses nltk | Regex + heuristic (stdlib) | +| keyword_analyzer.py | Uses scikit-learn | Counter + re (stdlib) | +| readability_scorer.py | Uses textstat | Flesch formula (stdlib, pure math) | +| seo_quality_rater.py | External deps | Checklist scorer (stdlib) | +| content_length_comparator.py | Web scraping | Input-based comparison (stdlib) | +| above_fold_analyzer.py | BeautifulSoup | html.parser (stdlib) | +| cta_analyzer.py | BeautifulSoup | html.parser (stdlib) | +| landing_page_scorer.py | External | Composite scorer (stdlib) | + +### New tools for existing skills +| Skill | New tool | Purpose | +|-------|----------|---------| +| seo-audit | seo_checker.py | On-page SEO scoring (0-100) | +| content-strategy | topic_cluster_mapper.py | Map topic clusters and gaps | +| copywriting | headline_scorer.py | Score headlines by power words, length, emotion | +| email-sequence | email_flow_designer.py | Design drip sequences with timing | +| paid-ads | roas_calculator.py | ROAS and budget allocation | +| campaign-analytics | channel_mixer.py | Cross-channel attribution synthesis | +| pricing-strategy | pricing_modeler.py | Price sensitivity and packaging optimizer | +| churn-prevention | churn_risk_scorer.py | Score churn signals | + +--- + +## Part 7: Execution Phases + +### Phase 1: Foundation + Import (batch 1) +**Goal:** Import 20 workspace skills, create context foundation, build orchestration +**Estimated:** ~80 files, 6 subagents +- Import all 20 workspace skills into `marketing-skill/` +- Add YAML frontmatter standardization where needed +- Create `marketing-context/` (context foundation) +- Create `marketing-ops/` (router/orchestrator) +- Add Related Skills cross-references to all imported skills +- Update CLAUDE.md + +### Phase 2: New Skills (batch 2) +**Goal:** Build 13 missing skills +**Estimated:** ~100 files, 6 subagents +- SEO: ai-seo, schema-markup, site-architecture +- Content: content-production, content-humanizer +- Channels: cold-email, ad-creative +- Growth: churn-prevention, referral-program, free-tool-strategy +- Intelligence: analytics-tracking +- Sales: pricing-strategy, sales-enablement + +### Phase 3: Python Tools (batch 3) +**Goal:** Add automation to knowledge-only skills +**Estimated:** ~20 scripts +- SEO analysis tools (search intent, keyword, readability, SEO quality) +- Content tools (headline scorer, topic mapper) +- CRO tools (above-fold, CTA, landing page scorer) +- Channel tools (ROAS calculator, email flow designer) +- Growth tools (churn risk scorer, pricing modeler) + +### Phase 4: Quality Upgrade (batch 4) +**Goal:** Apply C-Suite quality standard to all 37 skills +- Proactive triggers on all skills +- Output artifacts on all skills +- Integration tables on all skills +- Communication standard references +- Quality loop integration +- Final parity check + +--- + +## Part 8: Already Exists Elsewhere in Repo — DO NOT DUPLICATE + +Cross-repo audit found these "missing" capabilities already exist in other domains. The marketing team should **reference** them, not rebuild them. + +| "Missing" Capability | Already Exists At | What It Has | +|---------------------|-------------------|-------------| +| **Revenue Operations / RevOps** | `business-growth/revenue-operations/` | 3 Python tools: pipeline_analyzer, forecast_accuracy_tracker, gtm_efficiency_calculator | +| **Sales Enablement** | `business-growth/sales-engineer/` | 3 Python tools: rfp_response_analyzer, poc_planner, competitive_matrix_builder | +| **Churn Prevention** | `business-growth/customer-success-manager/` | 3 Python tools: churn_risk_analyzer, expansion_opportunity_scorer, health_score_calculator | +| **Landing Pages** | `product-team/landing-page-generator/` | Full Next.js/React landing page generation with copy frameworks, CRO patterns | +| **Competitive Analysis** | `product-team/competitive-teardown/` | Feature matrices, SWOT, positioning maps, UX audits | +| **Email Templates** | `engineering-team/email-template-builder/` | React Email, provider integration, i18n, dark mode, spam optimization | +| **Pricing Strategy** (partial) | `product-team/product-strategist/` | OKR cascade, product strategy (pricing is a component) | +| **Financial Analysis** | `finance/financial-analyst/` | DCF, ratios, budget variance, forecasting | +| **Contract/Proposal** | `business-growth/contract-and-proposal-writer/` | Proposal generation | +| **Stripe/Payments** | `engineering-team/stripe-integration-expert/` | Payment flows, subscription billing | + +### Impact on Plan + +**Remove from "new to build" list:** +- ~~revops~~ → already at `business-growth/revenue-operations/` +- ~~sales-enablement~~ → already at `business-growth/sales-engineer/` +- ~~churn-prevention~~ → already at `business-growth/customer-success-manager/` + +**Keep building (truly missing):** +- āœ… pricing-strategy (dedicated marketing pricing, not product strategy) +- āœ… cold-email (B2B outreach — distinct from email-sequence) +- āœ… ad-creative (bulk ad generation) +- āœ… referral-program (referral + affiliate programs) +- āœ… free-tool-strategy (engineering as marketing) +- āœ… ai-seo (AEO/GEO/LLMO — entirely new category) +- āœ… schema-markup (structured data) +- āœ… site-architecture (URL structure, nav, internal linking) +- āœ… content-production (research→write→optimize pipeline) +- āœ… content-humanizer (AI watermark removal, voice injection) +- āœ… analytics-tracking (GA4, GTM, event tracking setup) +- āœ… marketing-context (foundation — brand voice, style guide, etc.) +- āœ… marketing-ops (orchestration router) + +**Cross-reference in marketing-ops routing matrix:** +The marketing-ops router should know about and route to these business-growth/product-team skills when relevant, just like C-Suite's Chief of Staff routes across domains. + +### Revised Totals + +| Category | Existing (import/upgrade) | New (build) | Total | +|----------|--------------------------|-------------|-------| +| Context | 0 | 1 | 1 | +| Orchestration | 0 | 1 | 1 | +| Content | 5 + 1 upgrade | 2 | 8 | +| SEO | 2 | 3 | 5 | +| CRO | 6 | 0 | 6 | +| Channels | 2 + 1 upgrade | 2 | 5 | +| Growth | 1 | 2 (referral, free-tool) | 3 | +| Intelligence | 2 + 1 upgrade | 1 | 4 | +| Sales & GTM | 1 | 1 (pricing-strategy) | 2 | +| Standalone | 4 (keep as-is) | 0 | 4 | +| **TOTAL** | **24** | **13** | **39** | + +Down from 41 to 39 — removed 3 duplicates, cleaner architecture. + +--- + +## Part 9: Skills NOT Included (and why) + +| Skill | Source | Reason for exclusion | +|-------|--------|---------------------| +| WordPress publishing | SEO Machine | Platform-specific, not universal | +| DataForSEO integration | SEO Machine | Paid API, violates stdlib-only rule | +| GA4/GSC Python clients | SEO Machine | External deps (google-api-python-client) | +| revops | marketingskills | Already at `business-growth/revenue-operations/` | +| sales-enablement | marketingskills | Already at `business-growth/sales-engineer/` | +| churn-prevention | marketingskills | Already at `business-growth/customer-success-manager/` | +| product-marketing-context | marketingskills | Replaced by our marketing-context (richer) | + +--- + +*Created: 2026-03-06* +*Target: PR on `feat/marketing-expansion` branch* diff --git a/marketing-skill/SKILL.md b/marketing-skill/SKILL.md new file mode 100644 index 0000000..77c5f48 --- /dev/null +++ b/marketing-skill/SKILL.md @@ -0,0 +1,105 @@ +--- +name: marketing-skills +description: "42-skill marketing division for AI coding agents. 7 specialist pods covering content, SEO, CRO, channels, growth, intelligence, and sales. Foundation context system + orchestration router. 27 Python tools (all stdlib-only). Works with Claude Code, Codex CLI, and OpenClaw." +version: 2.0.0 +author: Alireza Rezvani +license: MIT +tags: + - marketing + - seo + - content + - copywriting + - cro + - analytics + - ai-seo +agents: + - claude-code + - codex-cli + - openclaw +--- + +# Marketing Skills Division + +42 production-ready marketing skills organized into 7 specialist pods with a context foundation and orchestration layer. + +## Quick Start + +### Claude Code +``` +/read marketing-skill/marketing-ops/SKILL.md +``` +The router will direct you to the right specialist skill. + +### Codex CLI +```bash +codex --full-auto "Read marketing-skill/marketing-ops/SKILL.md, then help me write a blog post about [topic]" +``` + +### OpenClaw +Skills are auto-discovered from the repository. Ask your agent for marketing help — it routes via `marketing-ops`. + +## Architecture + +``` +marketing-skill/ +ā”œā”€ā”€ marketing-context/ ← Foundation: brand voice, audience, goals +ā”œā”€ā”€ marketing-ops/ ← Router: dispatches to the right skill +│ +ā”œā”€ā”€ Content Pod (8) ← Strategy → Production → Editing → Social +ā”œā”€ā”€ SEO Pod (5) ← Traditional + AI SEO + Schema + Architecture +ā”œā”€ā”€ CRO Pod (6) ← Pages, Forms, Signup, Onboarding, Popups, Paywall +ā”œā”€ā”€ Channels Pod (5) ← Email, Ads, Cold Email, Ad Creative, Social Mgmt +ā”œā”€ā”€ Growth Pod (4) ← A/B Testing, Referrals, Free Tools, Churn +ā”œā”€ā”€ Intelligence Pod (4) ← Competitors, Psychology, Analytics, Campaigns +└── Sales & GTM Pod (2) ← Pricing, Launch Strategy +``` + +## First-Time Setup + +Run `marketing-context` to create your `marketing-context.md` file. Every other skill reads this for brand voice, audience personas, and competitive landscape. Do this once — it makes everything better. + +## Pod Overview + +| Pod | Skills | Python Tools | Key Capabilities | +|-----|--------|-------------|-----------------| +| **Foundation** | 2 | 2 | Brand context capture, skill routing | +| **Content** | 8 | 5 | Strategy → production → editing → humanization | +| **SEO** | 5 | 2 | Technical SEO, AI SEO (AEO/GEO), schema, architecture | +| **CRO** | 6 | 0 | Page, form, signup, onboarding, popup, paywall optimization | +| **Channels** | 5 | 2 | Email sequences, paid ads, cold email, ad creative | +| **Growth** | 4 | 2 | A/B testing, referral programs, free tools, churn prevention | +| **Intelligence** | 4 | 4 | Competitor analysis, marketing psychology, analytics, campaigns | +| **Sales & GTM** | 2 | 1 | Pricing strategy, launch planning | +| **Standalone** | 4 | 9 | ASO, brand guidelines, PMM strategy, prompt engineering | + +## Python Tools (27 scripts) + +All scripts are stdlib-only (zero pip installs), CLI-first with JSON output, and include embedded sample data for demo mode. + +```bash +# Content scoring +python3 marketing-skill/content-production/scripts/content_scorer.py article.md + +# AI writing detection +python3 marketing-skill/content-humanizer/scripts/humanizer_scorer.py draft.md + +# Brand voice analysis +python3 marketing-skill/content-production/scripts/brand_voice_analyzer.py copy.txt + +# Ad copy validation +python3 marketing-skill/ad-creative/scripts/ad_copy_validator.py ads.json + +# Pricing scenario modeling +python3 marketing-skill/pricing-strategy/scripts/pricing_modeler.py + +# Tracking plan generation +python3 marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py +``` + +## Unique Features + +- **AI SEO (AEO/GEO/LLMO)** — Optimize for AI citation, not just ranking +- **Content Humanizer** — Detect and fix AI writing patterns with scoring +- **Context Foundation** — One brand context file feeds all 42 skills +- **Orchestration Router** — Smart routing by keyword + complexity scoring +- **Zero Dependencies** — All Python tools use stdlib only diff --git a/marketing-skill/ab-test-setup/SKILL.md b/marketing-skill/ab-test-setup/SKILL.md new file mode 100644 index 0000000..816231a --- /dev/null +++ b/marketing-skill/ab-test-setup/SKILL.md @@ -0,0 +1,302 @@ +--- +name: ab-test-setup +description: When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "conversion experiment," "statistical significance," or "test this." For tracking implementation, see analytics-tracking. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# A/B Test Setup + +You are an expert in experimentation and A/B testing. Your goal is to help design tests that produce statistically valid, actionable results. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before designing a test, understand: + +1. **Test Context** - What are you trying to improve? What change are you considering? +2. **Current State** - Baseline conversion rate? Current traffic volume? +3. **Constraints** - Technical complexity? Timeline? Tools available? + +--- + +## Core Principles + +### 1. Start with a Hypothesis +- Not just "let's see what happens" +- Specific prediction of outcome +- Based on reasoning or data + +### 2. Test One Thing +- Single variable per test +- Otherwise you don't know what worked + +### 3. Statistical Rigor +- Pre-determine sample size +- Don't peek and stop early +- Commit to the methodology + +### 4. Measure What Matters +- Primary metric tied to business value +- Secondary metrics for context +- Guardrail metrics to prevent harm + +--- + +## Hypothesis Framework + +### Structure + +``` +Because [observation/data], +we believe [change] +will cause [expected outcome] +for [audience]. +We'll know this is true when [metrics]. +``` + +### Example + +**Weak**: "Changing the button color might increase clicks." + +**Strong**: "Because users report difficulty finding the CTA (per heatmaps and feedback), we believe making the button larger and using contrasting color will increase CTA clicks by 15%+ for new visitors. We'll measure click-through rate from page view to signup start." + +--- + +## Test Types + +| Type | Description | Traffic Needed | +|------|-------------|----------------| +| A/B | Two versions, single change | Moderate | +| A/B/n | Multiple variants | Higher | +| MVT | Multiple changes in combinations | Very high | +| Split URL | Different URLs for variants | Moderate | + +--- + +## Sample Size + +### Quick Reference + +| Baseline | 10% Lift | 20% Lift | 50% Lift | +|----------|----------|----------|----------| +| 1% | 150k/variant | 39k/variant | 6k/variant | +| 3% | 47k/variant | 12k/variant | 2k/variant | +| 5% | 27k/variant | 7k/variant | 1.2k/variant | +| 10% | 12k/variant | 3k/variant | 550/variant | + +**Calculators:** +- [Evan Miller's](https://www.evanmiller.org/ab-testing/sample-size.html) +- [Optimizely's](https://www.optimizely.com/sample-size-calculator/) + +**For detailed sample size tables and duration calculations**: See [references/sample-size-guide.md](references/sample-size-guide.md) + +--- + +## Metrics Selection + +### Primary Metric +- Single metric that matters most +- Directly tied to hypothesis +- What you'll use to call the test + +### Secondary Metrics +- Support primary metric interpretation +- Explain why/how the change worked + +### Guardrail Metrics +- Things that shouldn't get worse +- Stop test if significantly negative + +### Example: Pricing Page Test +- **Primary**: Plan selection rate +- **Secondary**: Time on page, plan distribution +- **Guardrail**: Support tickets, refund rate + +--- + +## Designing Variants + +### What to Vary + +| Category | Examples | +|----------|----------| +| Headlines/Copy | Message angle, value prop, specificity, tone | +| Visual Design | Layout, color, images, hierarchy | +| CTA | Button copy, size, placement, number | +| Content | Information included, order, amount, social proof | + +### Best Practices +- Single, meaningful change +- Bold enough to make a difference +- True to the hypothesis + +--- + +## Traffic Allocation + +| Approach | Split | When to Use | +|----------|-------|-------------| +| Standard | 50/50 | Default for A/B | +| Conservative | 90/10, 80/20 | Limit risk of bad variant | +| Ramping | Start small, increase | Technical risk mitigation | + +**Considerations:** +- Consistency: Users see same variant on return +- Balanced exposure across time of day/week + +--- + +## Implementation + +### Client-Side +- JavaScript modifies page after load +- Quick to implement, can cause flicker +- Tools: PostHog, Optimizely, VWO + +### Server-Side +- Variant determined before render +- No flicker, requires dev work +- Tools: PostHog, LaunchDarkly, Split + +--- + +## Running the Test + +### Pre-Launch Checklist +- [ ] Hypothesis documented +- [ ] Primary metric defined +- [ ] Sample size calculated +- [ ] Variants implemented correctly +- [ ] Tracking verified +- [ ] QA completed on all variants + +### During the Test + +**DO:** +- Monitor for technical issues +- Check segment quality +- Document external factors + +**DON'T:** +- Peek at results and stop early +- Make changes to variants +- Add traffic from new sources + +### The Peeking Problem +Looking at results before reaching sample size and stopping early leads to false positives and wrong decisions. Pre-commit to sample size and trust the process. + +--- + +## Analyzing Results + +### Statistical Significance +- 95% confidence = p-value < 0.05 +- Means <5% chance result is random +- Not a guarantee—just a threshold + +### Analysis Checklist + +1. **Reach sample size?** If not, result is preliminary +2. **Statistically significant?** Check confidence intervals +3. **Effect size meaningful?** Compare to MDE, project impact +4. **Secondary metrics consistent?** Support the primary? +5. **Guardrail concerns?** Anything get worse? +6. **Segment differences?** Mobile vs. desktop? New vs. returning? + +### Interpreting Results + +| Result | Conclusion | +|--------|------------| +| Significant winner | Implement variant | +| Significant loser | Keep control, learn why | +| No significant difference | Need more traffic or bolder test | +| Mixed signals | Dig deeper, maybe segment | + +--- + +## Documentation + +Document every test with: +- Hypothesis +- Variants (with screenshots) +- Results (sample, metrics, significance) +- Decision and learnings + +**For templates**: See [references/test-templates.md](references/test-templates.md) + +--- + +## Common Mistakes + +### Test Design +- Testing too small a change (undetectable) +- Testing too many things (can't isolate) +- No clear hypothesis + +### Execution +- Stopping early +- Changing things mid-test +- Not checking implementation + +### Analysis +- Ignoring confidence intervals +- Cherry-picking segments +- Over-interpreting inconclusive results + +--- + +## Task-Specific Questions + +1. What's your current conversion rate? +2. How much traffic does this page get? +3. What change are you considering and why? +4. What's the smallest improvement worth detecting? +5. What tools do you have for testing? +6. Have you tested this area before? + +--- + +## Proactive Triggers + +Proactively offer A/B test design when: + +1. **Conversion rate mentioned** — User shares a conversion rate and asks how to improve it; suggest designing a test rather than guessing at solutions. +2. **Copy or design decision is unclear** — When two variants of a headline, CTA, or layout are being debated, propose testing instead of opinionating. +3. **Campaign underperformance** — User reports a landing page or email performing below expectations; offer a structured test plan. +4. **Pricing page discussion** — Any mention of pricing page changes should trigger an offer to design a pricing test with guardrail metrics. +5. **Post-launch review** — After a feature or campaign goes live, propose follow-up experiments to optimize the result. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Experiment Brief | Markdown doc | Hypothesis, variants, metrics, sample size, duration, owner | +| Sample Size Calculator Input | Table | Baseline rate, MDE, confidence level, power | +| Pre-Launch QA Checklist | Checklist | Implementation, tracking, variant rendering verification | +| Results Analysis Report | Markdown doc | Statistical significance, effect size, segment breakdown, decision | +| Test Backlog | Prioritized list | Ranked experiments by expected impact and feasibility | + +--- + +## Communication + +All outputs should meet the quality standard: clear hypothesis, pre-registered metrics, and documented decisions. Avoid presenting inconclusive results as wins. Every test should produce a learning, even if the variant loses. Reference `marketing-context` for product and audience framing before designing experiments. + +--- + +## Related Skills + +- **page-cro** — USE when you need ideas for *what* to test; NOT when you already have a hypothesis and just need test design. +- **analytics-tracking** — USE to set up measurement infrastructure before running tests; NOT as a substitute for defining primary metrics upfront. +- **campaign-analytics** — USE after tests conclude to fold results into broader campaign attribution; NOT during the test itself. +- **pricing-strategy** — USE when test results affect pricing decisions; NOT to replace a controlled test with pure strategic reasoning. +- **marketing-context** — USE as foundation before any test design to ensure hypotheses align with ICP and positioning; always load first. diff --git a/marketing-skill/ab-test-setup/references/sample-size-guide.md b/marketing-skill/ab-test-setup/references/sample-size-guide.md new file mode 100644 index 0000000..c934b02 --- /dev/null +++ b/marketing-skill/ab-test-setup/references/sample-size-guide.md @@ -0,0 +1,252 @@ +# Sample Size Guide + +Reference for calculating sample sizes and test duration. + +## Sample Size Fundamentals + +### Required Inputs + +1. **Baseline conversion rate**: Your current rate +2. **Minimum detectable effect (MDE)**: Smallest change worth detecting +3. **Statistical significance level**: Usually 95% (α = 0.05) +4. **Statistical power**: Usually 80% (β = 0.20) + +### What These Mean + +**Baseline conversion rate**: If your page converts at 5%, that's your baseline. + +**MDE (Minimum Detectable Effect)**: The smallest improvement you care about detecting. Set this based on: +- Business impact (is a 5% lift meaningful?) +- Implementation cost (worth the effort?) +- Realistic expectations (what have past tests shown?) + +**Statistical significance (95%)**: Means there's less than 5% chance the observed difference is due to random chance. + +**Statistical power (80%)**: Means if there's a real effect of size MDE, you have 80% chance of detecting it. + +--- + +## Sample Size Quick Reference Tables + +### Conversion Rate: 1% + +| Lift to Detect | Sample per Variant | Total Sample | +|----------------|-------------------|--------------| +| 5% (1% → 1.05%) | 1,500,000 | 3,000,000 | +| 10% (1% → 1.1%) | 380,000 | 760,000 | +| 20% (1% → 1.2%) | 97,000 | 194,000 | +| 50% (1% → 1.5%) | 16,000 | 32,000 | +| 100% (1% → 2%) | 4,200 | 8,400 | + +### Conversion Rate: 3% + +| Lift to Detect | Sample per Variant | Total Sample | +|----------------|-------------------|--------------| +| 5% (3% → 3.15%) | 480,000 | 960,000 | +| 10% (3% → 3.3%) | 120,000 | 240,000 | +| 20% (3% → 3.6%) | 31,000 | 62,000 | +| 50% (3% → 4.5%) | 5,200 | 10,400 | +| 100% (3% → 6%) | 1,400 | 2,800 | + +### Conversion Rate: 5% + +| Lift to Detect | Sample per Variant | Total Sample | +|----------------|-------------------|--------------| +| 5% (5% → 5.25%) | 280,000 | 560,000 | +| 10% (5% → 5.5%) | 72,000 | 144,000 | +| 20% (5% → 6%) | 18,000 | 36,000 | +| 50% (5% → 7.5%) | 3,100 | 6,200 | +| 100% (5% → 10%) | 810 | 1,620 | + +### Conversion Rate: 10% + +| Lift to Detect | Sample per Variant | Total Sample | +|----------------|-------------------|--------------| +| 5% (10% → 10.5%) | 130,000 | 260,000 | +| 10% (10% → 11%) | 34,000 | 68,000 | +| 20% (10% → 12%) | 8,700 | 17,400 | +| 50% (10% → 15%) | 1,500 | 3,000 | +| 100% (10% → 20%) | 400 | 800 | + +### Conversion Rate: 20% + +| Lift to Detect | Sample per Variant | Total Sample | +|----------------|-------------------|--------------| +| 5% (20% → 21%) | 60,000 | 120,000 | +| 10% (20% → 22%) | 16,000 | 32,000 | +| 20% (20% → 24%) | 4,000 | 8,000 | +| 50% (20% → 30%) | 700 | 1,400 | +| 100% (20% → 40%) | 200 | 400 | + +--- + +## Duration Calculator + +### Formula + +``` +Duration (days) = (Sample per variant Ɨ Number of variants) / (Daily traffic Ɨ % exposed) +``` + +### Examples + +**Scenario 1: High-traffic page** +- Need: 10,000 per variant (2 variants = 20,000 total) +- Daily traffic: 5,000 visitors +- 100% exposed to test +- Duration: 20,000 / 5,000 = **4 days** + +**Scenario 2: Medium-traffic page** +- Need: 30,000 per variant (60,000 total) +- Daily traffic: 2,000 visitors +- 100% exposed +- Duration: 60,000 / 2,000 = **30 days** + +**Scenario 3: Low-traffic with partial exposure** +- Need: 15,000 per variant (30,000 total) +- Daily traffic: 500 visitors +- 50% exposed to test +- Effective daily: 250 +- Duration: 30,000 / 250 = **120 days** (too long!) + +### Minimum Duration Rules + +Even with sufficient sample size, run tests for at least: +- **1 full week**: To capture day-of-week variation +- **2 business cycles**: If B2B (weekday vs. weekend patterns) +- **Through paydays**: If e-commerce (beginning/end of month) + +### Maximum Duration Guidelines + +Avoid running tests longer than 4-8 weeks: +- Novelty effects wear off +- External factors intervene +- Opportunity cost of other tests + +--- + +## Online Calculators + +### Recommended Tools + +**Evan Miller's Calculator** +https://www.evanmiller.org/ab-testing/sample-size.html +- Simple interface +- Bookmark-worthy + +**Optimizely's Calculator** +https://www.optimizely.com/sample-size-calculator/ +- Business-friendly language +- Duration estimates + +**AB Test Guide Calculator** +https://www.abtestguide.com/calc/ +- Includes Bayesian option +- Multiple test types + +**VWO Duration Calculator** +https://vwo.com/tools/ab-test-duration-calculator/ +- Duration-focused +- Good for planning + +--- + +## Adjusting for Multiple Variants + +With more than 2 variants (A/B/n tests), you need more sample: + +| Variants | Multiplier | +|----------|------------| +| 2 (A/B) | 1x | +| 3 (A/B/C) | ~1.5x | +| 4 (A/B/C/D) | ~2x | +| 5+ | Consider reducing variants | + +**Why?** More comparisons increase chance of false positives. You're comparing: +- A vs B +- A vs C +- B vs C (sometimes) + +Apply Bonferroni correction or use tools that handle this automatically. + +--- + +## Common Sample Size Mistakes + +### 1. Underpowered tests +**Problem**: Not enough sample to detect realistic effects +**Fix**: Be realistic about MDE, get more traffic, or don't test + +### 2. Overpowered tests +**Problem**: Waiting for sample size when you already have significance +**Fix**: This is actually fine—you committed to sample size, honor it + +### 3. Wrong baseline rate +**Problem**: Using wrong conversion rate for calculation +**Fix**: Use the specific metric and page, not site-wide averages + +### 4. Ignoring segments +**Problem**: Calculating for full traffic, then analyzing segments +**Fix**: If you plan segment analysis, calculate sample for smallest segment + +### 5. Testing too many things +**Problem**: Dividing traffic too many ways +**Fix**: Prioritize ruthlessly, run fewer concurrent tests + +--- + +## When Sample Size Requirements Are Too High + +Options when you can't get enough traffic: + +1. **Increase MDE**: Accept only detecting larger effects (20%+ lift) +2. **Lower confidence**: Use 90% instead of 95% (risky, document it) +3. **Reduce variants**: Test only the most promising variant +4. **Combine traffic**: Test across multiple similar pages +5. **Test upstream**: Test earlier in funnel where traffic is higher +6. **Don't test**: Make decision based on qualitative data instead +7. **Longer test**: Accept longer duration (weeks/months) + +--- + +## Sequential Testing + +If you must check results before reaching sample size: + +### What is it? +Statistical method that adjusts for multiple looks at data. + +### When to use +- High-risk changes +- Need to stop bad variants early +- Time-sensitive decisions + +### Tools that support it +- Optimizely (Stats Accelerator) +- VWO (SmartStats) +- PostHog (Bayesian approach) + +### Tradeoff +- More flexibility to stop early +- Slightly larger sample size requirement +- More complex analysis + +--- + +## Quick Decision Framework + +### Can I run this test? + +``` +Daily traffic to page: _____ +Baseline conversion rate: _____ +MDE I care about: _____ + +Sample needed per variant: _____ (from tables above) +Days to run: Sample / Daily traffic = _____ + +If days > 60: Consider alternatives +If days > 30: Acceptable for high-impact tests +If days < 14: Likely feasible +If days < 7: Easy to run, consider running longer anyway +``` diff --git a/marketing-skill/ab-test-setup/references/test-templates.md b/marketing-skill/ab-test-setup/references/test-templates.md new file mode 100644 index 0000000..a504421 --- /dev/null +++ b/marketing-skill/ab-test-setup/references/test-templates.md @@ -0,0 +1,268 @@ +# A/B Test Templates Reference + +Templates for planning, documenting, and analyzing experiments. + +## Test Plan Template + +```markdown +# A/B Test: [Name] + +## Overview +- **Owner**: [Name] +- **Test ID**: [ID in testing tool] +- **Page/Feature**: [What's being tested] +- **Planned dates**: [Start] - [End] + +## Hypothesis + +Because [observation/data], +we believe [change] +will cause [expected outcome] +for [audience]. +We'll know this is true when [metrics]. + +## Test Design + +| Element | Details | +|---------|---------| +| Test type | A/B / A/B/n / MVT | +| Duration | X weeks | +| Sample size | X per variant | +| Traffic allocation | 50/50 | +| Tool | [Tool name] | +| Implementation | Client-side / Server-side | + +## Variants + +### Control (A) +[Screenshot] +- Current experience +- [Key details about current state] + +### Variant (B) +[Screenshot or mockup] +- [Specific change #1] +- [Specific change #2] +- Rationale: [Why we think this will win] + +## Metrics + +### Primary +- **Metric**: [metric name] +- **Definition**: [how it's calculated] +- **Current baseline**: [X%] +- **Minimum detectable effect**: [X%] + +### Secondary +- [Metric 1]: [what it tells us] +- [Metric 2]: [what it tells us] +- [Metric 3]: [what it tells us] + +### Guardrails +- [Metric that shouldn't get worse] +- [Another safety metric] + +## Segment Analysis Plan +- Mobile vs. desktop +- New vs. returning visitors +- Traffic source +- [Other relevant segments] + +## Success Criteria +- Winner: [Primary metric improves by X% with 95% confidence] +- Loser: [Primary metric decreases significantly] +- Inconclusive: [What we'll do if no significant result] + +## Pre-Launch Checklist +- [ ] Hypothesis documented and reviewed +- [ ] Primary metric defined and trackable +- [ ] Sample size calculated +- [ ] Test duration estimated +- [ ] Variants implemented correctly +- [ ] Tracking verified in all variants +- [ ] QA completed on all variants +- [ ] Stakeholders informed +- [ ] Calendar hold for analysis date +``` + +--- + +## Results Documentation Template + +```markdown +# A/B Test Results: [Name] + +## Summary +| Element | Value | +|---------|-------| +| Test ID | [ID] | +| Dates | [Start] - [End] | +| Duration | X days | +| Result | Winner / Loser / Inconclusive | +| Decision | [What we're doing] | + +## Hypothesis (Reminder) +[Copy from test plan] + +## Results + +### Sample Size +| Variant | Target | Actual | % of target | +|---------|--------|--------|-------------| +| Control | X | Y | Z% | +| Variant | X | Y | Z% | + +### Primary Metric: [Metric Name] +| Variant | Value | 95% CI | vs. Control | +|---------|-------|--------|-------------| +| Control | X% | [X%, Y%] | — | +| Variant | X% | [X%, Y%] | +X% | + +**Statistical significance**: p = X.XX (95% = sig / not sig) +**Practical significance**: [Is this lift meaningful for the business?] + +### Secondary Metrics + +| Metric | Control | Variant | Change | Significant? | +|--------|---------|---------|--------|--------------| +| [Metric 1] | X | Y | +Z% | Yes/No | +| [Metric 2] | X | Y | +Z% | Yes/No | + +### Guardrail Metrics + +| Metric | Control | Variant | Change | Concern? | +|--------|---------|---------|--------|----------| +| [Metric 1] | X | Y | +Z% | Yes/No | + +### Segment Analysis + +**Mobile vs. Desktop** +| Segment | Control | Variant | Lift | +|---------|---------|---------|------| +| Mobile | X% | Y% | +Z% | +| Desktop | X% | Y% | +Z% | + +**New vs. Returning** +| Segment | Control | Variant | Lift | +|---------|---------|---------|------| +| New | X% | Y% | +Z% | +| Returning | X% | Y% | +Z% | + +## Interpretation + +### What happened? +[Explanation of results in plain language] + +### Why do we think this happened? +[Analysis and reasoning] + +### Caveats +[Any limitations, external factors, or concerns] + +## Decision + +**Winner**: [Control / Variant] + +**Action**: [Implement variant / Keep control / Re-test] + +**Timeline**: [When changes will be implemented] + +## Learnings + +### What we learned +- [Key insight 1] +- [Key insight 2] + +### What to test next +- [Follow-up test idea 1] +- [Follow-up test idea 2] + +### Impact +- **Projected lift**: [X% improvement in Y metric] +- **Business impact**: [Revenue, conversions, etc.] +``` + +--- + +## Test Repository Entry Template + +For tracking all tests in a central location: + +```markdown +| Test ID | Name | Page | Dates | Primary Metric | Result | Lift | Link | +|---------|------|------|-------|----------------|--------|------|------| +| 001 | Hero headline test | Homepage | 1/1-1/15 | CTR | Winner | +12% | [Link] | +| 002 | Pricing table layout | Pricing | 1/10-1/31 | Plan selection | Loser | -5% | [Link] | +| 003 | Signup form fields | Signup | 2/1-2/14 | Completion | Inconclusive | +2% | [Link] | +``` + +--- + +## Quick Test Brief Template + +For simple tests that don't need full documentation: + +```markdown +## [Test Name] + +**What**: [One sentence description] +**Why**: [One sentence hypothesis] +**Metric**: [Primary metric] +**Duration**: [X weeks] +**Result**: [TBD / Winner / Loser / Inconclusive] +**Learnings**: [Key takeaway] +``` + +--- + +## Stakeholder Update Template + +```markdown +## A/B Test Update: [Name] + +**Status**: Running / Complete +**Days remaining**: X (or complete) +**Current sample**: X% of target + +### Preliminary observations +[What we're seeing - without making decisions yet] + +### Next steps +[What happens next] + +### Timeline +- [Date]: Analysis complete +- [Date]: Decision and recommendation +- [Date]: Implementation (if winner) +``` + +--- + +## Experiment Prioritization Scorecard + +For deciding which tests to run: + +| Factor | Weight | Test A | Test B | Test C | +|--------|--------|--------|--------|--------| +| Potential impact | 30% | | | | +| Confidence in hypothesis | 25% | | | | +| Ease of implementation | 20% | | | | +| Risk if wrong | 15% | | | | +| Strategic alignment | 10% | | | | +| **Total** | | | | | + +Scoring: 1-5 (5 = best) + +--- + +## Hypothesis Bank Template + +For collecting test ideas: + +```markdown +| ID | Page/Area | Observation | Hypothesis | Potential Impact | Status | +|----|-----------|-------------|------------|------------------|--------| +| H1 | Homepage | Low scroll depth | Shorter hero will increase scroll | High | Testing | +| H2 | Pricing | Users compare plans | Comparison table will help | Medium | Backlog | +| H3 | Signup | Drop-off at email | Social login will increase completion | Medium | Backlog | +``` diff --git a/marketing-skill/ab-test-setup/scripts/sample_size_calculator.py b/marketing-skill/ab-test-setup/scripts/sample_size_calculator.py new file mode 100644 index 0000000..310a089 --- /dev/null +++ b/marketing-skill/ab-test-setup/scripts/sample_size_calculator.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python3 +""" +sample_size_calculator.py — A/B Test Sample Size Calculator +100% stdlib, no pip installs required. + +Usage: + python3 sample_size_calculator.py # demo mode + python3 sample_size_calculator.py --baseline 0.05 --mde 0.20 + python3 sample_size_calculator.py --baseline 0.05 --mde 0.20 --daily-traffic 500 + python3 sample_size_calculator.py --baseline 0.05 --mde 0.20 --json +""" + +import argparse +import json +import math +import sys + + +# --------------------------------------------------------------------------- +# Z-score approximation (scipy-free, Beasley-Springer-Moro algorithm) +# --------------------------------------------------------------------------- + +def _norm_ppf(p: float) -> float: + """Percent-point function (inverse CDF) of the standard normal. + Uses rational approximation — accurate to ~1e-9. + Reference: Abramowitz & Stegun 26.2.17 / Peter Acklam's algorithm. + """ + if p <= 0 or p >= 1: + raise ValueError(f"p must be in (0, 1), got {p}") + + # Coefficients for rational approximation + a = [-3.969683028665376e+01, 2.209460984245205e+02, + -2.759285104469687e+02, 1.383577518672690e+02, + -3.066479806614716e+01, 2.506628277459239e+00] + b = [-5.447609879822406e+01, 1.615858368580409e+02, + -1.556989798598866e+02, 6.680131188771972e+01, + -1.328068155288572e+01] + c = [-7.784894002430293e-03, -3.223964580411365e-01, + -2.400758277161838e+00, -2.549732539343734e+00, + 4.374664141464968e+00, 2.938163982698783e+00] + d = [7.784695709041462e-03, 3.224671290700398e-01, + 2.445134137142996e+00, 3.754408661907416e+00] + + p_low = 0.02425 + p_high = 1 - p_low + + if p < p_low: + q = math.sqrt(-2 * math.log(p)) + return (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / \ + ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1) + elif p <= p_high: + q = p - 0.5 + r = q * q + return (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q / \ + (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1) + else: + q = math.sqrt(-2 * math.log(1 - p)) + return -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / \ + ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1) + + +# --------------------------------------------------------------------------- +# Core calculation +# --------------------------------------------------------------------------- + +def calculate_sample_size( + baseline: float, + mde: float, + alpha: float = 0.05, + power: float = 0.80, +) -> dict: + """ + Two-proportion z-test sample size formula (two-tailed). + + n = (Z_alpha/2 + Z_beta)^2 * (p1*(1-p1) + p2*(1-p2)) / (p2 - p1)^2 + + Args: + baseline : baseline conversion rate (e.g. 0.05 for 5%) + mde : minimum detectable effect as relative lift (e.g. 0.20 for +20%) + alpha : significance level (Type I error rate), default 0.05 + power : statistical power (1 - Type II error rate), default 0.80 + + Returns dict with all intermediate values and results. + """ + p1 = baseline + p2 = baseline * (1 + mde) # expected conversion with treatment + + if not (0 < p1 < 1): + raise ValueError(f"baseline must be in (0,1), got {p1}") + if not (0 < p2 < 1): + raise ValueError( + f"baseline * (1 + mde) = {p2:.4f} is outside (0,1). " + "Reduce mde or increase baseline." + ) + + z_alpha = _norm_ppf(1 - alpha / 2) # two-tailed + z_beta = _norm_ppf(power) + + pooled_var = p1 * (1 - p1) + p2 * (1 - p2) + effect_sq = (p2 - p1) ** 2 + + n_raw = ((z_alpha + z_beta) ** 2 * pooled_var) / effect_sq + n = math.ceil(n_raw) + + return { + "inputs": { + "baseline_conversion_rate": p1, + "minimum_detectable_effect_relative": mde, + "expected_variant_conversion_rate": round(p2, 6), + "significance_level_alpha": alpha, + "statistical_power": power, + }, + "z_scores": { + "z_alpha_2": round(z_alpha, 4), + "z_beta": round(z_beta, 4), + }, + "results": { + "sample_size_per_variation": n, + "total_sample_size": n * 2, + "absolute_lift": round(p2 - p1, 6), + "relative_lift_pct": round(mde * 100, 2), + }, + "formula": ( + "n = (Z_α/2 + Z_β)² Ɨ (p1(1āˆ’p1) + p2(1āˆ’p2)) / (p2āˆ’p1)² " + "[two-proportion z-test, two-tailed]" + ), + "assumptions": [ + "Two-tailed test (detecting lift in either direction)", + "Independent samples (no within-subject correlation)", + "Fixed horizon (not sequential / always-valid)", + "Binomial outcome (conversion yes/no)", + "No novelty effect correction applied", + ], + } + + +def add_duration(result: dict, daily_traffic: int) -> dict: + """Append estimated test duration given total daily traffic (both variants).""" + n_total = result["results"]["total_sample_size"] + days = math.ceil(n_total / daily_traffic) + weeks = round(days / 7, 1) + result["duration"] = { + "daily_traffic_both_variants": daily_traffic, + "estimated_days": days, + "estimated_weeks": weeks, + "note": ( + "Assumes traffic is evenly split 50/50 between control and variant. " + "Add ~10–20% buffer for weekday/weekend variance." + ), + } + return result + + +# --------------------------------------------------------------------------- +# Scoring helper (0-100) +# --------------------------------------------------------------------------- + +def score_test_design(result: dict) -> dict: + """Heuristic quality score for the A/B test design.""" + score = 100 + reasons = [] + inputs = result["inputs"] + + # Penalise very low baseline (unreliable estimates) + if inputs["baseline_conversion_rate"] < 0.01: + score -= 15 + reasons.append("Baseline <1%: high variance, consider aggregating more data first.") + + # Penalise tiny MDE (will need enormous sample) + mde = inputs["minimum_detectable_effect_relative"] + if mde < 0.05: + score -= 20 + reasons.append("MDE <5%: very small effect, experiment may take months.") + elif mde < 0.10: + score -= 10 + reasons.append("MDE <10%: moderately small effect size.") + + # Penalise overly aggressive alpha + if inputs["significance_level_alpha"] > 0.10: + score -= 15 + reasons.append("α >10%: high false-positive risk.") + + # Penalise low power + if inputs["statistical_power"] < 0.80: + score -= 20 + reasons.append("Power <80%: elevated risk of missing real effects (Type II error).") + + # Duration penalty (if available) + dur = result.get("duration") + if dur: + days = dur["estimated_days"] + if days > 90: + score -= 20 + reasons.append(f"Test duration {days}d >90 days: novelty/seasonal effects likely.") + elif days > 30: + score -= 10 + reasons.append(f"Test duration {days}d >30 days: monitor for external confounders.") + + score = max(0, score) + return { + "design_quality_score": score, + "score_interpretation": _score_label(score), + "issues": reasons if reasons else ["No major design issues detected."], + } + + +def _score_label(s: int) -> str: + if s >= 90: return "Excellent" + if s >= 75: return "Good" + if s >= 60: return "Fair" + if s >= 40: return "Poor" + return "Critical" + + +# --------------------------------------------------------------------------- +# Pretty-print +# --------------------------------------------------------------------------- + +def pretty_print(result: dict, score: dict) -> None: + inp = result["inputs"] + res = result["results"] + zs = result["z_scores"] + + print("\n" + "=" * 60) + print(" A/B TEST SAMPLE SIZE CALCULATOR") + print("=" * 60) + + print("\nšŸ“„ INPUTS") + print(f" Baseline conversion rate : {inp['baseline_conversion_rate']*100:.2f}%") + print(f" Variant conversion rate : {inp['expected_variant_conversion_rate']*100:.2f}%") + print(f" Minimum detectable effect: {inp['minimum_detectable_effect_relative']*100:.1f}% relative " + f"(+{res['absolute_lift']*100:.3f}pp absolute)") + print(f" Significance level (α) : {inp['significance_level_alpha']}") + print(f" Statistical power : {inp['statistical_power']*100:.0f}%") + + print("\nšŸ“ FORMULA") + print(f" {result['formula']}") + print(f" Z_α/2 = {zs['z_alpha_2']} Z_β = {zs['z_beta']}") + + print("\nšŸ“Š RESULTS") + print(f" āœ… Sample size per variation : {res['sample_size_per_variation']:,}") + print(f" āœ… Total sample size (both) : {res['total_sample_size']:,}") + + if "duration" in result: + d = result["duration"] + print(f"\nā±ļø DURATION ESTIMATE (traffic: {d['daily_traffic_both_variants']:,}/day)") + print(f" Estimated test duration : {d['estimated_days']} days (~{d['estimated_weeks']} weeks)") + print(f" Note: {d['note']}") + + print("\nšŸ’” ASSUMPTIONS") + for a in result["assumptions"]: + print(f" • {a}") + + print(f"\nšŸŽÆ DESIGN QUALITY SCORE: {score['design_quality_score']}/100 ({score['score_interpretation']})") + for issue in score["issues"]: + print(f" ⚠ {issue}") + + print() + + +# --------------------------------------------------------------------------- +# CLI +# --------------------------------------------------------------------------- + +def parse_args(): + parser = argparse.ArgumentParser( + description="Calculate required sample size for an A/B test (stdlib only).", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--baseline", type=float, default=None, + help="Baseline conversion rate (e.g. 0.05 for 5%%)") + parser.add_argument("--mde", type=float, default=None, + help="Minimum detectable effect as relative lift (e.g. 0.20 for +20%%)") + parser.add_argument("--alpha", type=float, default=0.05, + help="Significance level α (default: 0.05)") + parser.add_argument("--power", type=float, default=0.80, + help="Statistical power 1-β (default: 0.80)") + parser.add_argument("--daily-traffic", type=int, default=None, + help="Total daily visitors across both variants (for duration estimate)") + parser.add_argument("--json", action="store_true", + help="Output results as JSON") + return parser.parse_args() + + +DEMO_SCENARIOS = [ + {"label": "E-commerce checkout (low baseline)", + "baseline": 0.03, "mde": 0.20, "alpha": 0.05, "power": 0.80, "daily_traffic": 800}, + {"label": "SaaS free-trial signup (medium baseline)", + "baseline": 0.08, "mde": 0.15, "alpha": 0.05, "power": 0.80, "daily_traffic": 2000}, + {"label": "Button CTA (high baseline)", + "baseline": 0.25, "mde": 0.10, "alpha": 0.05, "power": 0.80, "daily_traffic": 5000}, +] + + +def main(): + args = parse_args() + demo_mode = (args.baseline is None and args.mde is None) + + if demo_mode: + print("šŸ”¬ DEMO MODE — running 3 sample scenarios\n") + all_results = [] + for sc in DEMO_SCENARIOS: + res = calculate_sample_size(sc["baseline"], sc["mde"], sc["alpha"], sc["power"]) + res = add_duration(res, sc["daily_traffic"]) + sc_score = score_test_design(res) + res["scenario"] = sc["label"] + res["score"] = sc_score + all_results.append(res) + if not args.json: + print(f"\n{'─'*60}") + print(f"SCENARIO: {sc['label']}") + pretty_print(res, sc_score) + + if args.json: + print(json.dumps(all_results, indent=2)) + return + + # Single calculation mode + if args.baseline is None or args.mde is None: + print("Error: --baseline and --mde are required (or omit both for demo mode).", file=sys.stderr) + sys.exit(1) + + result = calculate_sample_size(args.baseline, args.mde, args.alpha, args.power) + if args.daily_traffic: + result = add_duration(result, args.daily_traffic) + sc_score = score_test_design(result) + result["score"] = sc_score + + if args.json: + print(json.dumps(result, indent=2)) + else: + pretty_print(result, sc_score) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/ad-creative/SKILL.md b/marketing-skill/ad-creative/SKILL.md new file mode 100644 index 0000000..4b0c529 --- /dev/null +++ b/marketing-skill/ad-creative/SKILL.md @@ -0,0 +1,267 @@ +--- +name: ad-creative +description: "When the user needs to generate, iterate, or scale ad creative for paid advertising. Use when they say 'write ad copy,' 'generate headlines,' 'create ad variations,' 'bulk creative,' 'iterate on ads,' 'ad copy validation,' 'RSA headlines,' 'Meta ad copy,' 'LinkedIn ad,' or 'creative testing.' This is pure creative production — distinct from paid-ads (campaign strategy). Use ad-creative when you need the copy, not the campaign plan." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Ad Creative + +You are a performance creative director who has written thousands of ads. You know what converts, what gets rejected, and what looks like it should work but doesn't. Your goal is to produce ad copy that passes platform review, stops the scroll, and drives action — at scale. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered. + +Gather this context (ask if not provided): + +### 1. Product & Offer +- What are you advertising? Be specific — product, feature, free trial, lead magnet? +- What's the core value prop in one sentence? +- What does the customer get and how fast? + +### 2. Audience +- Who are you writing for? Job title, pain point, moment in their day +- What do they already believe? What objections will they have? + +### 3. Platform & Stage +- Which platform(s)? (Google, Meta, LinkedIn, Twitter/X, TikTok) +- Funnel stage? (Awareness / Consideration / Decision) +- Any existing copy to iterate from, or starting fresh? + +### 4. Performance Data (if iterating) +- What's currently running? Share current copy. +- Which ads are winning? CTR, CVR, CPA? +- What have you already tested? + +--- + +## How This Skill Works + +### Mode 1: Generate from Scratch +Starting with nothing. Build a complete creative set from brief to ready-to-upload copy. + +**Workflow:** +1. Extract the core message — what changes in the customer's life? +2. Map to funnel stage → select creative framework +3. Generate 5–10 headlines per formula type +4. Write body copy per platform (respecting character limits) +5. Apply quality checks before handing off + +### Mode 2: Iterate from Performance Data +You have something running. Now make it better. + +**Workflow:** +1. Audit current copy — what angle is each ad taking? +2. Identify the winning pattern (hook type, offer framing, emotional appeal) +3. Double down: 3–5 variations on the winning theme +4. Open new angles: 2–3 tests in unexplored territory +5. Validate all against platform specs and quality score + +### Mode 3: Scale Variations +You have a winning creative. Now multiply it for testing or for multiple audiences/platforms. + +**Workflow:** +1. Lock the core message +2. Vary one element at a time: hook, social proof, CTA, format +3. Adapt across platforms (reformat without rewriting from scratch) +4. Produce a creative matrix: rows = angles, columns = platforms + +--- + +## Platform Specs Quick Reference + +| Platform | Format | Headline Limit | Body Copy Limit | Notes | +|----------|--------|---------------|-----------------|-------| +| Google RSA | Search | 30 chars (Ɨ15) | 90 chars (Ɨ4 descriptions) | Max 3 pinned | +| Google Display | Display | 30 chars (Ɨ5) | 90 chars (Ɨ5) | Also needs 5 images | +| Meta (Facebook/Instagram) | Feed/Story | 40 chars (primary) | 125 chars primary text | Image text <20% | +| LinkedIn | Sponsored Content | 70 chars headline | 150 chars intro text | No click-bait | +| Twitter/X | Promoted | 70 chars | 280 chars total | No deceptive tactics | +| TikTok | In-Feed | No overlay headline | 80–100 chars caption | Hook in first 3s | + +See [references/platform-specs.md](references/platform-specs.md) for full specs including image sizes, video lengths, and rejection triggers. + +--- + +## Creative Framework by Funnel Stage + +### Awareness — Lead with the Problem +They don't know you yet. Meet them where they are. + +**Frame:** Problem → Amplify → Hint at Solution +- Lead with the pain, not the product +- Use the language they use when complaining to a colleague +- Don't pitch. Relate. + +**Works well:** Curiosity hooks, stat-based hooks, "you know that feeling" hooks + +### Consideration — Lead with the Solution +They know the problem. They're evaluating options. + +**Frame:** Solution → Mechanism → Proof +- Explain what you do, but through the lens of the outcome they want +- Show that you work differently (the mechanism matters here) +- Social proof starts mattering here: reviews, case studies, numbers + +**Works well:** Benefit-first headlines, comparison frames, how-it-works copy + +### Decision — Lead with Proof +They're close. Remove the last objection. + +**Frame:** Proof → Risk Removal → Urgency +- Testimonials, case studies, results with numbers +- Remove risk: free trial, money-back, no credit card +- Urgency if you have it — but only real urgency, not fake countdown timers + +**Works well:** Social proof headlines, guarantee-first, before/after + +See [references/creative-frameworks.md](references/creative-frameworks.md) for the full framework catalog with examples by platform. + +--- + +## Headline Formulas That Actually Work + +### Benefit-First +`[Verb] [specific outcome] [timeframe or qualifier]` +- "Cut your churn rate by 30% without chasing customers" +- "Ship features your team actually uses" +- "Hire senior engineers in 2 weeks, not 4 months" + +### Curiosity +`[Surprising claim or counterintuitive angle]` +- "The email sequence that gets replies when your first one fails" +- "Why your best customers leave at 90 days" +- "Most agencies won't tell you this about Meta ads" + +### Social Proof +`[Number] [people/companies] [outcome]` +- "1,200 SaaS teams use this to reduce support tickets" +- "Trusted by 40,000 developers across 80 countries" +- "How [similar company] doubled activation in 6 weeks" + +### Urgency (done right) +`[Real scarcity or time-sensitive value]` +- "Q1 pricing ends March 31 — new contracts from April 1" +- "Only 3 onboarding slots open this month" +- No: "šŸ”„ LIMITED TIME DEAL!! ACT NOW!!!" — gets rejected and looks desperate + +### Problem Agitation +`[Describe the pain vividly]` +- "Still losing 40% of signups before they see value?" +- "Your ads are probably running, your budget is definitely spending, and you're not sure what's working" + +--- + +## Iteration Methodology + +When you have performance data, don't just write new ads — learn from what's working. + +### Step 1: Diagnose the Winner +- What hook type is it? (Problem / Benefit / Curiosity / Social Proof) +- What funnel stage is it serving? +- What emotional driver is it hitting? (Fear, ambition, FOMO, frustration, relief) +- What's the CTA asking for? (Click / Sign up / Learn more / Book a call) + +### Step 2: Extract the Pattern +Look for what the winner has that others don't: +- Specific numbers vs. vague claims +- First-person customer voice vs. brand voice +- Direct benefit vs. emotional appeal + +### Step 3: Generate on Theme +Write 3–5 variations that preserve the winning pattern: +- Same hook type, different angle +- Same emotional driver, different example +- Same structure, different product feature + +### Step 4: Test a New Angle +Don't just exploit. Also explore. Pick one untested angle and generate 2–3 ads. + +### Step 5: Validate and Submit +Run all new copy through the quality checklist (see below) before uploading. + +--- + +## Quality Checklist + +Before submitting any ad copy, verify: + +**Platform Compliance** +- [ ] All character counts within limits (use `scripts/ad_copy_validator.py`) +- [ ] No ALL CAPS except acronyms (Google and Meta both flag it) +- [ ] No excessive punctuation (!!!, ???, …. all trigger rejection) +- [ ] No "click here," "buy now," or platform trademarks in copy +- [ ] No first-person platform references ("Facebook," "Insta," "Google") + +**Quality Standards** +- [ ] Headline could stand alone — doesn't require the description to make sense +- [ ] Specific claim over vague claim ("save 3 hours" > "save time") +- [ ] CTA is clear and matches the landing page offer +- [ ] No claims you can't back up (#1, best-in-class, etc.) + +**Audience Check** +- [ ] Would the ideal customer stop scrolling for this? +- [ ] Does the language match how they talk about this problem? +- [ ] Is the funnel stage right for the audience targeting? + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Generic headlines detected** ("Grow your business," "Save time and money") → Flag and replace with specific, measurable versions +- **Character count violations** → Always validate before presenting copy; mark violations clearly +- **Stage-message mismatch** → If copy is showing proof content to cold audiences, flag and adjust +- **Fake urgency** → If copy uses countdown timers or "limited time" with no real constraint, flag the risk of trust damage and platform rejection +- **No variation in hook type** → If all 10 headlines use the same formula, flag the testing gap +- **Copy lifted from landing page** → Ad copy and landing page need to feel connected but not identical; flag verbatim duplication + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Generate RSA headlines" | 15 headlines organized by formula type, all ≤30 chars, with pinning recommendations | +| "Write Meta ads for this campaign" | 3 full ad sets (primary text + headline + description) for each funnel stage | +| "Iterate on my winning ads" | Winner analysis + 5 on-theme variations + 2 new angle tests | +| "Create a creative matrix" | Table: angles Ɨ platforms with full copy per cell | +| "Validate my ad copy" | Line-by-line validation report with character counts, rejection risk flags, and quality score (0-100) | +| "Give me LinkedIn ad copy" | 3 sponsored content ads with intro text ≤150 chars, plus headlines ≤70 chars | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — lead with the copy, explain the rationale after +- **Platform specs visible** — always show character count next to each line +- **Confidence tagging** — 🟢 tested formula / 🟔 new angle / šŸ”“ high-risk claim +- **Rejection risks flagged explicitly** — don't make the user guess + +Format for presenting ad copy: + +``` +[AD SET NAME] | [Platform] | [Funnel Stage] +Headline: "..." (28 chars) 🟢 +Body: "..." (112 chars) 🟢 +CTA: "Learn More" +Notes: Benefit-first formula, tested format for consideration stage +``` + +--- + +## Related Skills + +- **paid-ads**: Use for campaign strategy, audience targeting, budget allocation, and platform selection. NOT for writing the actual copy (use ad-creative for that). +- **copywriting**: Use for landing page and long-form web copy. NOT for platform-specific character-constrained ad copy. +- **ab-test-setup**: Use when planning which ad variants to test and how to measure significance. NOT for generating the variants (use ad-creative for that). +- **content-creator**: Use for organic social content and blog content. NOT for paid ad copy (different constraints, different voice). +- **copy-editing**: Use when polishing existing copy. NOT for bulk generation or platform-specific formatting. diff --git a/marketing-skill/ad-creative/references/creative-frameworks.md b/marketing-skill/ad-creative/references/creative-frameworks.md new file mode 100644 index 0000000..601dc15 --- /dev/null +++ b/marketing-skill/ad-creative/references/creative-frameworks.md @@ -0,0 +1,253 @@ +# Creative Frameworks — Headline and Copy Formulas by Platform and Funnel Stage + +A working catalog of the copy frameworks that consistently outperform generic ads. Use these as starting points, not templates to fill in blindly. + +--- + +## The Golden Rule + +Every ad has one job: get the right person to stop, read, and take one action. If the copy is trying to do three things, it does none of them well. One message, one CTA, one next step. + +--- + +## Framework Index + +1. PAS — Problem, Agitate, Solution +2. BAB — Before, After, Bridge +3. FAB — Feature, Advantage, Benefit +4. AIDA — Attention, Interest, Desire, Action +5. Social Proof Frame +6. Contrarian Frame +7. Specificity Frame +8. How-It-Works Frame + +--- + +## 1. PAS — Problem, Agitate, Solution + +**Best for:** Awareness and consideration stage. Cold audiences who don't know your solution. + +**Structure:** +- Problem: Name the pain in their words +- Agitate: Make them feel how bad it is (don't make it worse than reality — they'll know) +- Solution: Position your product as the obvious fix + +**Example (SaaS — project management):** +``` +Primary text: "Your team is shipping, but nobody knows who owns what. Deadlines are "this week" +not "Tuesday at 3pm." By the time the stand-up is over, everyone has a different version of +the plan. [Product] replaces the chaos with a single source of truth. Try it free for 14 days." + +Headline: "Stop running projects in Slack threads" +``` + +**Length guidance:** PAS works long and short. Short for cold feed, long for warm retargeting. + +--- + +## 2. BAB — Before, After, Bridge + +**Best for:** Consideration and decision stage. Audiences who know the problem and are evaluating. + +**Structure:** +- Before: Where they are now (the frustrating state) +- After: Where they want to be (the goal) +- Bridge: How your product gets them from here to there + +**Example (B2B analytics tool):** +``` +Headline: "From data chaos to clear answers" +Body: "Before [Product]: 6 spreadsheets, 4 dashboards, nobody agrees on the numbers. +After [Product]: One source of truth, automated weekly reports, decisions in minutes. +The bridge: connect your data sources once, and [Product] does the rest." +``` + +**Note:** BAB works especially well for case studies and social proof ads where you can show a real before/after with numbers. + +--- + +## 3. FAB — Feature, Advantage, Benefit + +**Best for:** Decision stage, retargeting, people who have visited your product page. + +**Structure:** +- Feature: What it does (the thing you built) +- Advantage: How it works better than the alternative +- Benefit: What the customer actually gets in their life/work + +**Common mistake:** Stopping at the feature. "Two-factor authentication" is a feature. "Bank-level security" is an advantage. "Sleep at night knowing your customer data is protected" is the benefit. + +**Example (HR software):** +``` +Feature: "Automated payroll that syncs with your accounting software" +Advantage: "No more manual data entry between systems" +Benefit: "Close the books on time, every time — without staying late" + +Ad copy: "Payroll that closes itself. Automated payroll synced directly to QuickBooks — +no double entry, no reconciliation hell. Every month. On time. [Product] — +start your free trial." +``` + +--- + +## 4. AIDA — Attention, Interest, Desire, Action + +**Best for:** Video ads, longer copy (LinkedIn, email), awareness campaigns. + +**Structure:** +- Attention: Hook (first 3 seconds / first sentence) +- Interest: Why this matters to them specifically +- Desire: Make them want the outcome +- Action: One clear CTA + +**Example (video script outline for SaaS):** +``` +[0–3s] ATTENTION: "[Hook visual/statement]" — "Most companies spend 8 hours a week +on reports nobody reads." +[3–10s] INTEREST: "If you're a head of marketing, that's 32 hours of your team's time +each month — time they could spend on campaigns that actually drive revenue." +[10–20s] DESIRE: "[Product] automates the reporting. Your team gets that time back. +Your manager gets the data they asked for, without the nagging." +[20–25s] ACTION: "Start your 14-day free trial. No credit card." +``` + +--- + +## 5. Social Proof Frame + +**Best for:** Decision stage. Works especially well for retargeting. + +**Formulas:** + +**Customer voice:** +``` +"[Customer quote that speaks to the exact result — specific numbers preferred]" +— [Name, Title, Company] +[Product name] — [CTA] +``` + +**Results-led:** +``` +Headline: "[Company] saved [X] hours per week with [Product]" +Body: "Before [Product], [Company] was manually tracking [problem]. Today, +they [specific result] — in [timeframe]. Here's how they did it." +``` + +**Volume proof:** +``` +Headline: "[Number] teams trust [Product] to [outcome]" +Body: "From 5-person startups to Fortune 500 companies. Start your free trial." +``` + +**Note:** Specificity makes social proof work. "Many customers love it" → weak. "4,200 teams use [Product] to eliminate weekly reports" → strong. + +--- + +## 6. Contrarian Frame + +**Best for:** Awareness stage on saturated topics. Breaks through category fatigue. + +**Structure:** Challenge the conventional wisdom in your category. Then reframe with your perspective. + +**Example (email marketing tool):** +``` +Headline: "More emails isn't the answer" +Body: "Everyone says send more emails. Better segmentation. More automation. More sequences. +But if your email is boring, more of it just means more unsubscribes. +[Product] helps you write emails people actually want to open — then send them +to the people most likely to act. Less volume. More revenue." +``` + +**Warning:** The contrarian frame needs substance behind it. If your product is "like everyone else but better," don't use this frame. Use it when you genuinely have a different approach. + +--- + +## 7. Specificity Frame + +**Best for:** All stages. Works everywhere. The most underused framework. + +**Principle:** Specific claims outperform vague claims on every metric. Not "save time" — "save 3 hours per week." Not "grow your business" — "increase trial-to-paid conversion by 22%." + +**Upgrade examples:** +| Vague | Specific | +|-------|---------| +| "Save time on reporting" | "Cut reporting time from 8 hours to 45 minutes" | +| "Trusted by leading companies" | "Used by 3,200+ growth teams in 60 countries" | +| "Improve your team's performance" | "Teams using [Product] ship 40% more features per quarter" | +| "Get better results" | "Average customer sees 28% higher conversion within 90 days" | +| "Easy to use" | "Set up in 15 minutes — no engineering required" | + +If you don't have specific numbers: get them. Talk to 5 customers, ask for their before/after. One real number beats 10 marketing adjectives. + +--- + +## 8. How-It-Works Frame + +**Best for:** Consideration stage. Audiences who are curious but not yet convinced. + +**Structure:** Show the mechanism — how your product produces the result. Remove mystery, reduce skepticism. + +**Example (automation tool):** +``` +Headline: "How [Product] works in 3 steps" +Body: +"1. Connect your tools (10 minutes, no coding) +2. Set your conditions ("when a lead scores over 80, do this") +3. Watch it run — 24/7, without your team touching it" + +The result? Leads followed up in minutes, not days. Teams that spend time on deals, +not on data entry. +[CTA: See it in action — free demo] +``` + +--- + +## Platform-Specific Framework Match + +| Platform | Best Frameworks | Why | +|----------|---------------|-----| +| Google RSA | Specificity, Benefit-first | Intent-driven — they searched for it | +| Meta Feed (cold) | PAS, Contrarian | Interrupt and engage fast | +| Meta Feed (retargeting) | BAB, Social Proof | They know you — sell the outcome | +| LinkedIn | AIDA, FAB, How-It-Works | Longer attention span, B2B mindset | +| TikTok | PAS (compressed), Hook-first | 3-second hook is everything | +| Twitter | Contrarian, Specificity | Opinionated content performs | + +--- + +## Funnel Stage → Framework Selector + +| Stage | Goal | Top Frameworks | +|-------|------|---------------| +| **Awareness** | Interrupt → Relevant → Curious | PAS, Contrarian, Specificity | +| **Consideration** | Educate → Differentiate → Trust | AIDA, FAB, How-It-Works, BAB | +| **Decision** | Prove → Remove risk → Action | Social Proof, BAB, Specificity + guarantee | +| **Retention/Upsell** | Remind value → Expand → Deepen | BAB, Feature highlight, milestone-based | + +--- + +## Headline Formula Quick Reference + +| Formula | Structure | Example | +|---------|-----------|---------| +| Benefit-First | [Verb] [outcome] [qualifier] | "Ship twice as fast without breaking prod" | +| Problem-Led | [Pain point they recognize] | "Still manually exporting to CSV every Monday?" | +| Number-Led | [Number] [thing] [result] | "14 days. Zero code. Full automation." | +| Curiosity | [Counterintuitive or unexpected] | "The feature nobody builds that triples retention" | +| How-To | "How [persona] [achieves outcome]" | "How growth teams cut CAC by 35% in one quarter" | +| Social Proof | "[Number] [people/teams] [do/use/trust]" | "31,000 marketers use this to skip the daily stand-up" | +| Objection-Lead | [Address the #1 reason they don't buy] | "No, you don't need an engineer to set this up" | +| Direct Comparison | "[Vs. their current approach]" | "Cheaper than Salesforce. More powerful than your spreadsheet." | + +--- + +## Anti-Patterns to Avoid + +| Anti-Pattern | Why It Fails | Fix | +|-------------|-------------|-----| +| "We are the #1 platform for..." | Unsubstantiated, overused, ignored | Lead with proof, not ranking | +| "Solutions for modern teams" | Meaningless — who isn't a modern team? | Name the specific team + specific problem | +| "Powerful yet easy to use" | Every product says this | Show the result — don't describe the product | +| "Unlock your potential" | Zero specificity, total fluff | What potential, specifically? Show it. | +| "Join thousands of happy customers" | Vague and dated | "3,400 companies use [Product] to [specific outcome]" | +| Emoji abuse | Looks desperate on LinkedIn, clutters Google | One emoji max, only if it adds meaning | diff --git a/marketing-skill/ad-creative/references/platform-specs.md b/marketing-skill/ad-creative/references/platform-specs.md new file mode 100644 index 0000000..e86ff0e --- /dev/null +++ b/marketing-skill/ad-creative/references/platform-specs.md @@ -0,0 +1,170 @@ +# Platform Specs — Ad Copy Character Limits and Format Requirements + +Full specifications for each major ad platform. Use this when generating or validating ad copy. + +--- + +## Google Ads + +### Responsive Search Ads (RSA) +| Element | Limit | Count | Notes | +|---------|-------|-------|-------| +| Headline | 30 chars | Up to 15 (min 3) | At least 3 unique, Google mixes them | +| Description | 90 chars | Up to 4 (min 2) | Google selects 2 to show | +| Display URL path | 15 chars each | 2 path fields | Auto-appended to domain | +| Final URL | No char limit | 1 | Must match domain in display URL | + +**Pinning:** You can pin headlines to position 1, 2, or 3. Only pin when critical (e.g., brand name, compliance disclaimer). Pinning reduces Google's optimization. + +**Ad Strength:** Google scores RSAs: Poor / Average / Good / Excellent. Target "Good" or "Excellent" by: +- Using all 15 headline slots +- Making headlines unique (no repeats, no same keywords) +- Including your main keyword in at least 3 headlines +- Using descriptions that complement, not repeat, headlines + +### Performance Max (PMax) +| Element | Limit | Count | +|---------|-------|-------| +| Headline | 30 chars | Up to 5 | +| Long headline | 90 chars | Up to 5 | +| Description | 90 chars | Up to 5 | +| Short description | 60 chars | 1 | + +### Display Ads (Responsive) +| Element | Limit | Count | +|---------|-------|-------| +| Short headline | 30 chars | 1 | +| Long headline | 90 chars | 1 | +| Description | 90 chars | 1 | +| Business name | 25 chars | 1 | + +--- + +## Meta (Facebook & Instagram) + +### Feed Ads (Single Image / Carousel) +| Element | Limit | Notes | +|---------|-------|-------| +| Primary text | 125 chars (preview) / 2200 max | First 125 shown before "See more" | +| Headline | 40 chars | Shown below image | +| Description | 30 chars | Optional, below headline | +| Link description | 20 chars | URL preview | + +**Image text rule:** Images with >20% text surface area get reduced distribution. Meta's tool at meta.com/ads/inspector/ checks this. Keep text minimal on images — put copy in the primary text field. + +### Story / Reel Ads +| Element | Limit | Notes | +|---------|-------|-------| +| Primary text overlay | 90 chars | Auto-placed if used | +| No traditional headline | — | Overlay text is the copy | + +### Carousel Ads +| Element | Limit | Notes | +|---------|-------|-------| +| Primary text | 125 chars (preview) | Shared across cards | +| Headline per card | 40 chars | Each card has own headline | +| Description per card | 20 chars | Optional | +| Cards | 2–10 | | + +**Rejection triggers (Meta):** +- "Facebook" or "Instagram" in ad copy +- Guarantees of specific financial outcomes ("Make $10k/month") +- Before/after comparison (health/beauty) +- Excessive use of first-person pronouns targeting users ("you," "your" in a way that implies personal attributes) +- ALL CAPS in any significant portion +- Exaggerated health claims +- Click-bait phrasing ("You won't believe...", "Click to find out...") + +--- + +## LinkedIn + +### Sponsored Content (Single Image) +| Element | Limit | Notes | +|---------|-------|-------| +| Intro text | 150 chars (preview) / 600 max | First 150 visible before "See more" | +| Headline | 70 chars | | +| Description | 100 chars | Optional | + +### Message Ads (InMail) +| Element | Limit | Notes | +|---------|-------|-------| +| Subject line | 60 chars | | +| Body | 1,500 chars | First 500 most critical | +| CTA button | 20 chars | | + +### Conversation Ads +| Element | Limit | Notes | +|---------|-------|-------| +| Intro message | 500 chars | | +| CTA per branch | 25 chars | Up to 5 buttons | +| Message body per branch | 500 chars | | + +**LinkedIn-specific rules:** +- No "Click here" as standalone CTA +- No images with more than 20% text +- No misleading job descriptions or recruitment bait +- Avoid generic corporate language — LinkedIn users are saturated with it +- B2B works better when you lead with a specific insight or stat, not a product pitch + +--- + +## Twitter/X + +### Promoted Tweets +| Element | Limit | Notes | +|---------|-------|-------| +| Tweet text | 280 chars total | URL counts as 23 chars | +| Usable copy | ~257 chars | After URL deduction | +| Image | Any ratio | 1200Ɨ628 recommended | + +**Twitter-specific notes:** +- Copy + URL + image works in the feed +- Lead with the hook — first 15 words matter most (above-the-fold on mobile) +- Hashtags are optional for paid — they distract from the CTA + +--- + +## TikTok + +### In-Feed Ads +| Element | Limit | Notes | +|---------|-------|-------| +| Ad text / caption | 100 chars | Overlaid on video | +| Video length | 5–60 seconds (optimal 15–30s) | | +| Mention/hashtag | Avoid branded hashtags | Policy restriction | + +**TikTok-specific notes:** +- Hook must land in the first 3 seconds — after that, thumb stops +- Native-feeling content outperforms polished ads (not always better to use brand assets) +- Text on screen increases time-watched +- CTA button text: "Shop Now," "Learn More," "Download," "Sign Up" are options + +--- + +## Common Rejection Triggers (All Platforms) + +| Trigger | Why It Gets Rejected | Fix | +|---------|---------------------|-----| +| ALL CAPS words | Flagged as aggressive/spam | Use title case or sentence case | +| Excessive punctuation | !!!, ???, ... — looks spammy | One at most | +| "#1" claims | Superlatives require proof | Remove or qualify | +| "Guaranteed" | Financial/result guarantees restricted | "Proven to" or show results data | +| Trademarked terms | Platform + competitor names | Remove or get written permission | +| Profanity | Obvious | Remove | +| "Click here" | Considered low-quality bait | Use specific CTA | +| Personal attributes | "You are depressed," "For single people" | Rephrase without identifying attributes | +| Misleading discounts | "90% off" without context | Substantiate or remove | + +--- + +## Platform Comparison — Which Platform for Which Creative? + +| Use case | Best platform | Why | +|----------|-------------|-----| +| High intent, search-driven | Google Search RSA | Users are already looking | +| Visual product with broad audience | Meta Feed | Best visual reach, lowest CPM for B2C | +| B2B decision-makers | LinkedIn | Job title + company size targeting | +| Young consumer audience, viral potential | TikTok | Organic-native feel, high engagement | +| Real-time relevance, news-adjacent | Twitter/X | Timely content performs | +| Retargeting across the web | Google Display | Broad reach, cheap retargeting | diff --git a/marketing-skill/ad-creative/scripts/ad_copy_validator.py b/marketing-skill/ad-creative/scripts/ad_copy_validator.py new file mode 100644 index 0000000..a6c7485 --- /dev/null +++ b/marketing-skill/ad-creative/scripts/ad_copy_validator.py @@ -0,0 +1,477 @@ +#!/usr/bin/env python3 +""" +ad_copy_validator.py — Validates ad copy against platform specs. + +Checks: character counts, rejection triggers (ALL CAPS, excessive punctuation, +trademarked terms), and scores each ad 0-100. + +Usage: + python3 ad_copy_validator.py # runs embedded sample + python3 ad_copy_validator.py ads.json # validates a JSON file + echo '{"platform":"google_rsa","headlines":["My headline"]}' | python3 ad_copy_validator.py + +JSON input format: + { + "platform": "google_rsa" | "meta_feed" | "linkedin" | "twitter" | "tiktok", + "headlines": ["...", ...], + "descriptions": ["...", ...], # for google + "primary_text": "...", # for meta, linkedin, twitter, tiktok + "headline": "...", # for meta headline field + "intro_text": "..." # for linkedin + } +""" + +import json +import re +import sys +from collections import defaultdict + +# --------------------------------------------------------------------------- +# Platform specifications +# --------------------------------------------------------------------------- +PLATFORM_SPECS = { + "google_rsa": { + "name": "Google RSA", + "headline_max": 30, + "headline_count_max": 15, + "headline_count_min": 3, + "description_max": 90, + "description_count_max": 4, + "description_count_min": 2, + }, + "google_display": { + "name": "Google Display", + "headline_max": 30, + "description_max": 90, + }, + "meta_feed": { + "name": "Meta (Facebook/Instagram) Feed", + "primary_text_max": 125, # preview limit; 2200 absolute max + "headline_max": 40, + "description_max": 30, + }, + "linkedin": { + "name": "LinkedIn Sponsored Content", + "intro_text_max": 150, # preview limit; 600 absolute max + "headline_max": 70, + "description_max": 100, + }, + "twitter": { + "name": "Twitter/X Promoted", + "primary_text_max": 257, # 280 - 23 chars for URL + }, + "tiktok": { + "name": "TikTok In-Feed", + "primary_text_max": 100, + }, +} + +# --------------------------------------------------------------------------- +# Rejection triggers +# --------------------------------------------------------------------------- +TRADEMARKED_TERMS = [ + "facebook", "instagram", "google", "youtube", "tiktok", "twitter", + "linkedin", "snapchat", "whatsapp", "amazon", "apple", "microsoft", +] + +PROHIBITED_PHRASES = [ + "click here", + "limited time offer", # allowed if real — flagged for review + "guaranteed", + "100% free", + "act now", + "best in class", + "world's best", + "#1 rated", + "number one", +] + +# Financial / health claim patterns +SUSPICIOUS_PATTERNS = [ + r"\$\d{3,}[k+]?\s*per\s*(day|week|month)", # "make $1,000 per day" + r"\d{3,}%\s*(return|roi|profit|gain)", # "300% return" + r"(cure|treat|heal|eliminate)\s+\w+", # health claims + r"lose\s+\d+\s*(pound|lb|kg)", # weight loss claims +] + +# --------------------------------------------------------------------------- +# Validation logic +# --------------------------------------------------------------------------- + +def count_chars(text): + return len(text.strip()) + + +def check_all_caps(text): + """Returns True if more than 30% of alpha chars are uppercase — not counting acronyms.""" + words = text.split() + violations = [] + for word in words: + alpha = re.sub(r'[^a-zA-Z]', '', word) + if len(alpha) > 3 and alpha.isupper(): + violations.append(word) + return violations + + +def check_excessive_punctuation(text): + """Flags repeated punctuation (!!!, ???, ...).""" + return re.findall(r'[!?\.]{2,}', text) + + +def check_trademark_mentions(text): + lowered = text.lower() + return [term for term in TRADEMARKED_TERMS if re.search(r'\b' + term + r'\b', lowered)] + + +def check_prohibited_phrases(text): + lowered = text.lower() + return [phrase for phrase in PROHIBITED_PHRASES if phrase in lowered] + + +def check_suspicious_claims(text): + hits = [] + for pattern in SUSPICIOUS_PATTERNS: + if re.search(pattern, text, re.IGNORECASE): + hits.append(pattern) + return hits + + +def score_ad(issues): + """ + Score 0-100. Start at 100, deduct per issue category. + """ + score = 100 + deductions = { + "char_over_limit": 20, + "all_caps": 15, + "excessive_punctuation": 10, + "trademark_mention": 25, + "prohibited_phrase": 15, + "suspicious_claim": 30, + "count_too_few": 10, + "count_too_many": 5, + } + for category, items in issues.items(): + if items: + score -= deductions.get(category, 5) * (1 if isinstance(items, bool) else min(len(items), 3)) + return max(0, score) + + +def validate_google_rsa(ad): + spec = PLATFORM_SPECS["google_rsa"] + issues = defaultdict(list) + report = [] + + headlines = ad.get("headlines", []) + descriptions = ad.get("descriptions", []) + + # Count checks + if len(headlines) < spec["headline_count_min"]: + issues["count_too_few"].append(f"Need ≄{spec['headline_count_min']} headlines, got {len(headlines)}") + if len(headlines) > spec["headline_count_max"]: + issues["count_too_many"].append(f"Max {spec['headline_count_max']} headlines, got {len(headlines)}") + if len(descriptions) < spec["description_count_min"]: + issues["count_too_few"].append(f"Need ≄{spec['description_count_min']} descriptions, got {len(descriptions)}") + + # Character checks per headline + for i, h in enumerate(headlines): + length = count_chars(h) + status = "āœ…" if length <= spec["headline_max"] else "āŒ" + if length > spec["headline_max"]: + issues["char_over_limit"].append(f"Headline {i+1}: {length} chars (max {spec['headline_max']})") + report.append(f" Headline {i+1}: {status} '{h}' ({length}/{spec['headline_max']} chars)") + + # Rejection trigger checks on each headline + caps = check_all_caps(h) + if caps: + issues["all_caps"].extend(caps) + punct = check_excessive_punctuation(h) + if punct: + issues["excessive_punctuation"].extend(punct) + trademarks = check_trademark_mentions(h) + if trademarks: + issues["trademark_mention"].extend(trademarks) + prohibited = check_prohibited_phrases(h) + if prohibited: + issues["prohibited_phrase"].extend(prohibited) + + for i, d in enumerate(descriptions): + length = count_chars(d) + status = "āœ…" if length <= spec["description_max"] else "āŒ" + if length > spec["description_max"]: + issues["char_over_limit"].append(f"Description {i+1}: {length} chars (max {spec['description_max']})") + report.append(f" Description {i+1}: {status} '{d}' ({length}/{spec['description_max']} chars)") + + suspicious = check_suspicious_claims(d) + if suspicious: + issues["suspicious_claim"].extend(suspicious) + + return report, dict(issues) + + +def validate_meta_feed(ad): + spec = PLATFORM_SPECS["meta_feed"] + issues = defaultdict(list) + report = [] + + primary = ad.get("primary_text", "") + headline = ad.get("headline", "") + + if primary: + length = count_chars(primary) + status = "āœ…" if length <= spec["primary_text_max"] else "āš ļø (preview truncated)" + report.append(f" Primary text: {status} ({length}/{spec['primary_text_max']} preview chars)") + if length > spec["primary_text_max"]: + issues["char_over_limit"].append(f"Primary text {length} chars exceeds {spec['primary_text_max']}-char preview") + + for check_fn, key in [ + (check_all_caps, "all_caps"), + (check_excessive_punctuation, "excessive_punctuation"), + (check_trademark_mentions, "trademark_mention"), + (check_prohibited_phrases, "prohibited_phrase"), + (check_suspicious_claims, "suspicious_claim"), + ]: + result = check_fn(primary) + if result: + issues[key].extend(result if isinstance(result, list) else [str(result)]) + + if headline: + length = count_chars(headline) + status = "āœ…" if length <= spec["headline_max"] else "āŒ" + if length > spec["headline_max"]: + issues["char_over_limit"].append(f"Headline {length} chars (max {spec['headline_max']})") + report.append(f" Headline: {status} '{headline}' ({length}/{spec['headline_max']} chars)") + + return report, dict(issues) + + +def validate_linkedin(ad): + spec = PLATFORM_SPECS["linkedin"] + issues = defaultdict(list) + report = [] + + intro = ad.get("intro_text", ad.get("primary_text", "")) + headline = ad.get("headline", "") + + if intro: + length = count_chars(intro) + status = "āœ…" if length <= spec["intro_text_max"] else "āš ļø (preview truncated)" + report.append(f" Intro text: {status} ({length}/{spec['intro_text_max']} preview chars)") + if length > spec["intro_text_max"]: + issues["char_over_limit"].append(f"Intro text {length} chars exceeds {spec['intro_text_max']}-char preview") + + for check_fn, key in [ + (check_all_caps, "all_caps"), + (check_excessive_punctuation, "excessive_punctuation"), + (check_trademark_mentions, "trademark_mention"), + ]: + result = check_fn(intro) + if result: + issues[key].extend(result if isinstance(result, list) else [str(result)]) + + if headline: + length = count_chars(headline) + status = "āœ…" if length <= spec["headline_max"] else "āŒ" + if length > spec["headline_max"]: + issues["char_over_limit"].append(f"Headline {length} chars (max {spec['headline_max']})") + report.append(f" Headline: {status} '{headline}' ({length}/{spec['headline_max']} chars)") + + return report, dict(issues) + + +def validate_generic(ad, platform_key): + spec = PLATFORM_SPECS.get(platform_key, {}) + issues = defaultdict(list) + report = [] + + text = ad.get("primary_text", ad.get("text", "")) + max_chars = spec.get("primary_text_max", 280) + + if text: + length = count_chars(text) + status = "āœ…" if length <= max_chars else "āŒ" + if length > max_chars: + issues["char_over_limit"].append(f"Text {length} chars (max {max_chars})") + report.append(f" Text: {status} ({length}/{max_chars} chars)") + + for check_fn, key in [ + (check_all_caps, "all_caps"), + (check_excessive_punctuation, "excessive_punctuation"), + (check_trademark_mentions, "trademark_mention"), + (check_prohibited_phrases, "prohibited_phrase"), + ]: + result = check_fn(text) + if result: + issues[key].extend(result if isinstance(result, list) else [str(result)]) + + return report, dict(issues) + + +def validate_ad(ad): + platform = ad.get("platform", "").lower() + + if platform == "google_rsa": + return validate_google_rsa(ad) + elif platform == "meta_feed": + return validate_meta_feed(ad) + elif platform == "linkedin": + return validate_linkedin(ad) + elif platform in ("twitter", "tiktok"): + return validate_generic(ad, platform) + else: + return [f" āš ļø Unknown platform '{platform}' — using generic validation"], {} + + +# --------------------------------------------------------------------------- +# Reporting +# --------------------------------------------------------------------------- + +def format_report(ad, char_lines, issues): + platform = ad.get("platform", "unknown") + spec = PLATFORM_SPECS.get(platform, {}) + platform_name = spec.get("name", platform.upper()) + + score = score_ad(issues) + grade = "🟢 Excellent" if score >= 85 else "🟔 Needs Work" if score >= 60 else "šŸ”“ High Risk" + + lines = [] + lines.append(f"\n{'='*60}") + lines.append(f"Platform: {platform_name}") + lines.append(f"Quality Score: {score}/100 {grade}") + lines.append(f"{'='*60}") + + lines.append("\nCharacter Counts:") + lines.extend(char_lines) + + if issues: + lines.append("\nIssues Found:") + category_labels = { + "char_over_limit": "āŒ Over character limit", + "all_caps": "āš ļø ALL CAPS words", + "excessive_punctuation": "āš ļø Excessive punctuation", + "trademark_mention": "🚫 Trademarked term", + "prohibited_phrase": "🚫 Prohibited phrase", + "suspicious_claim": "🚨 Suspicious claim (review required)", + "count_too_few": "āš ļø Too few elements", + "count_too_many": "āš ļø Too many elements", + } + for category, items in issues.items(): + label = category_labels.get(category, category) + lines.append(f" {label}: {', '.join(str(i) for i in items)}") + else: + lines.append("\nāœ… No rejection triggers found.") + + lines.append("") + return "\n".join(lines) + + +# --------------------------------------------------------------------------- +# Sample data (embedded — runs with zero config) +# --------------------------------------------------------------------------- + +SAMPLE_ADS = [ + { + "platform": "google_rsa", + "headlines": [ + "Cut Reporting Time by 80%", # 26 chars āœ… + "Automated Reports, Zero Effort", # 31 chars āŒ over limit + "Your Data. Your Way. Every Week.", # 33 chars āŒ over limit + "Save 8 Hours Per Week on Reports", # 32 chars āŒ over limit + "Try Free for 14 Days", # 21 chars āœ… + "No Code. No Complexity. Just Results.", # 38 chars āŒ + "5,000 Teams Use This", # 21 chars āœ… + "Replace Your Weekly Standup Deck", # 32 chars āŒ + "Connect Your Tools in 15 Minutes", # 32 chars āŒ + "Instant Dashboards for Your Team", # 32 chars āŒ + "Start Free — No Credit Card", # 28 chars āœ… + "Built for Growth Teams", # 22 chars āœ… + "See Your KPIs at a Glance", # 25 chars āœ… + "Data-Driven Decisions, Made Easy", # 32 chars āŒ + "GUARANTEED Results — Try Now!!!", # 31 chars āŒ + ALL CAPS + excessive punct + ], + "descriptions": [ + "Connect your tools, set your KPIs, and let the platform handle the weekly reporting. Free 14-day trial.", # 103 chars āŒ + "Stop wasting Monday mornings on spreadsheets. Automated reports your whole team actually reads.", # 94 chars āŒ + ], + }, + { + "platform": "meta_feed", + "primary_text": "Your team is shipping features, but nobody can see the impact. [Product] connects your tools and shows you exactly what's working — in one dashboard, updated automatically. Start free today.", + "headline": "See Your Impact, Automatically", + }, + { + "platform": "linkedin", + "intro_text": "Growth teams at 3,200+ companies use [Product] to replace their manual weekly reports with automated dashboards.", + "headline": "Automated Reporting for Growth Teams", + }, + { + "platform": "twitter", + "primary_text": "Stop spending 8 hours on a report nobody reads. [Product] automates it — connect your tools, set your KPIs, and it runs itself. Free trial → [link]", + }, +] + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + # Load from file or stdin, else use sample + ads = None + + if len(sys.argv) > 1: + try: + with open(sys.argv[1]) as f: + data = json.load(f) + ads = data if isinstance(data, list) else [data] + except Exception as e: + print(f"Error reading file: {e}", file=sys.stderr) + sys.exit(1) + elif not sys.stdin.isatty(): + raw = sys.stdin.read().strip() + if raw: + try: + data = json.loads(raw) + ads = data if isinstance(data, list) else [data] + except Exception as e: + print(f"Error reading stdin: {e}", file=sys.stderr) + sys.exit(1) + else: + print("No input provided — running embedded sample ads.\n") + ads = SAMPLE_ADS + else: + print("No input provided — running embedded sample ads.\n") + ads = SAMPLE_ADS + + # Aggregate results for JSON output + results = [] + all_output = [] + + for ad in ads: + char_lines, issues = validate_ad(ad) + score = score_ad(issues) + report_text = format_report(ad, char_lines, issues) + all_output.append(report_text) + results.append({ + "platform": ad.get("platform"), + "score": score, + "issues": {k: v for k, v in issues.items()}, + "passed": score >= 70, + }) + + # Human-readable output + for block in all_output: + print(block) + + # Summary + avg_score = sum(r["score"] for r in results) / len(results) if results else 0 + passed = sum(1 for r in results if r["passed"]) + print(f"\nSUMMARY: {passed}/{len(results)} ads passed (avg score: {avg_score:.0f}/100)") + + # JSON output to stdout (for programmatic use) — write to separate section + print("\n--- JSON Output ---") + print(json.dumps(results, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/ai-seo/SKILL.md b/marketing-skill/ai-seo/SKILL.md new file mode 100644 index 0000000..08beb24 --- /dev/null +++ b/marketing-skill/ai-seo/SKILL.md @@ -0,0 +1,331 @@ +--- +name: ai-seo +description: "Optimize content to get cited by AI search engines — ChatGPT, Perplexity, Google AI Overviews, Claude, Gemini, Copilot. Use when you want your content to appear in AI-generated answers, not just ranked in blue links. Triggers: 'optimize for AI search', 'get cited by ChatGPT', 'AI Overviews', 'Perplexity citations', 'AI SEO', 'generative search', 'LLM visibility', 'GEO' (generative engine optimization). NOT for traditional SEO ranking (use seo-audit). NOT for content creation (use content-production)." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# AI SEO + +You are an expert in generative engine optimization (GEO) — the discipline of making content citeable by AI search platforms. Your goal is to help content get extracted, quoted, and cited by ChatGPT, Perplexity, Google AI Overviews, Claude, Gemini, and Microsoft Copilot. + +This is not traditional SEO. Traditional SEO gets you ranked. AI SEO gets you cited. Those are different games with different rules. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it. It contains existing keyword targets, content inventory, and competitor information — all of which inform where to start. + +Gather what you need: + +### What you need +- **URL or content to audit** — specific page, or a topic area to assess +- **Target queries** — what questions do you want AI systems to answer using your content? +- **Current visibility** — are you already appearing in any AI search results for your targets? +- **Content inventory** — do you have existing pieces to optimize, or are you starting from scratch? + +If the user doesn't know their target queries: "What questions would your ideal customer ask an AI assistant that you'd want your brand to answer?" + +## How This Skill Works + +Three modes. Each builds on the previous, but you can start anywhere: + +### Mode 1: AI Visibility Audit +Map your current presence (or absence) across AI search platforms. Understand what's getting cited, what's getting ignored, and why. + +### Mode 2: Content Optimization +Restructure and enhance content to match what AI systems extract. This is the execution mode — specific patterns, specific changes. + +### Mode 3: Monitoring +Set up systems to track AI citations over time — so you know when you appear, when you disappear, and when a competitor takes your spot. + +--- + +## How AI Search Works (and Why It's Different) + +Traditional SEO: Google ranks your page. User clicks through. You get traffic. + +AI search: The AI reads your page (or has already indexed it), extracts the answer, and presents it to the user — often without a click. You get cited, not ranked. + +**The fundamental shift:** +- Ranked = user sees your link and decides whether to click +- Cited = AI decides your content answers the question; user may never visit your site + +This changes everything: +- **Keyword density** matters less than **answer clarity** +- **Page authority** matters less than **answer extractability** +- **Click-through rate** is irrelevant — the AI has already decided you're the answer +- **Structured content** (definitions, lists, tables, steps) outperforms flowing narrative + +But here's what traditional SEO and AI SEO share: **authority still matters**. AI systems prefer sources they consider credible — established domains, cited works, expert authorship. You still need backlinks and domain trust. You just also need structure. + +See [references/ai-search-landscape.md](references/ai-search-landscape.md) for how each platform (Google AI Overviews, ChatGPT, Perplexity, Claude, Gemini, Copilot) selects and cites sources. + +--- + +## The 3 Pillars of AI Citability + +Every AI SEO decision flows from these three: + +### Pillar 1: Structure (Extractable) + +AI systems pull content in chunks. They don't read your whole article and then paraphrase it — they find the paragraph, list, or definition that directly answers the query and lift it. + +Your content needs to be structured so that answers are self-contained and extractable: +- Definition block for "what is X" +- Numbered steps for "how to do X" +- Comparison table for "X vs Y" +- FAQ block for "questions about X" +- Statistics with attribution for "data on X" + +Content that buries the answer in page 3 of a 4,000-word essay is not extractable. The AI won't find it. + +### Pillar 2: Authority (Citable) + +AI systems don't just pull the most relevant answer — they pull the most credible one. Authority signals in the AI era: + +- **Domain authority**: High-DA domains get preferential treatment (traditional SEO signal still applies) +- **Author attribution**: Named authors with credentials beat anonymous pages +- **Citation chain**: Your content cites credible sources → you're seen as credible in turn +- **Recency**: AI systems prefer current information for time-sensitive queries +- **Original data**: Pages with proprietary research, surveys, or studies get cited more — AI systems value unique data they can't get elsewhere + +### Pillar 3: Presence (Discoverable) + +AI systems need to be able to find and index your content. This is the technical layer: + +- **Bot access**: AI crawlers must be allowed in robots.txt (GPTBot, PerplexityBot, ClaudeBot, etc.) +- **Crawlability**: Fast page load, clean HTML, no JavaScript-only content +- **Schema markup**: Structured data (Article, FAQPage, HowTo, Product) helps AI systems understand your content type +- **Canonical signals**: Duplicate content confuses AI systems even more than traditional search +- **HTTPS and security**: AI crawlers won't index pages with security warnings + +--- + +## Mode 1: AI Visibility Audit + +### Step 1 — Bot Access Check + +First: confirm AI crawlers can access your site. + +**Check robots.txt** at `yourdomain.com/robots.txt`. Verify these bots are NOT blocked: + +``` +# Should NOT be blocked (allow AI indexing): +GPTBot # OpenAI / ChatGPT +PerplexityBot # Perplexity +ClaudeBot # Anthropic / Claude +Google-Extended # Google AI Overviews +anthropic-ai # Anthropic (alternate identifier) +Applebot-Extended # Apple Intelligence +cohere-ai # Cohere +``` + +If any AI bot is blocked, flag it. That's an immediate visibility killer for that platform. + +**robots.txt to allow all AI bots:** +``` +User-agent: GPTBot +Allow: / + +User-agent: PerplexityBot +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: Google-Extended +Allow: / +``` + +To block specific AI training while allowing search: use `Disallow:` selectively, but understand that blocking training ≠ blocking citation — they're often the same crawl. + +### Step 2 — Current Citation Audit + +Manually test your target queries on each platform: + +| Platform | How to test | +|---|---| +| Perplexity | Search your target query at perplexity.ai — check Sources panel | +| ChatGPT | Search with web browsing enabled — check citations | +| Google AI Overviews | Google your query — check if AI Overview appears, who's cited | +| Microsoft Copilot | Search at copilot.microsoft.com — check source cards | + +For each query, document: +- Are you cited? (yes/no) +- Which competitors are cited? +- What content type gets cited? (definition? list? stats?) +- How is the answer structured? + +This tells you the pattern that's currently winning. Build toward it. + +### Step 3 — Content Structure Audit + +Review your key pages against the Extractability Checklist: + +- [ ] Does the page have a clear, answerable definition of its core concept in the first 200 words? +- [ ] Are there numbered lists or step-by-step sections for process-oriented queries? +- [ ] Does the page have a FAQ section with direct Q&A pairs? +- [ ] Are statistics and data points cited with source name and year? +- [ ] Are comparisons done in table format (not narrative)? +- [ ] Is the page's H1 phrased as the answer to a question, or as a statement? +- [ ] Does schema markup exist? (FAQPage, HowTo, Article, etc.) + +Score: 0-3 checks = needs major restructuring. 4-5 = good baseline. 6-7 = strong. + +--- + +## Mode 2: Content Optimization + +### The Content Patterns That Get Cited + +These are the block types AI systems reliably extract. Add at least 2-3 per key page. + +See [references/content-patterns.md](references/content-patterns.md) for ready-to-use templates for each pattern. + +**Pattern 1: Definition Block** +The AI's answer to "what is X" almost always comes from a tight, self-contained definition. Format: + +> **[Term]** is [concise definition in 1-2 sentences]. [One sentence of context or why it matters]. + +Placed within the first 300 words of the page. No hedging, no preamble. Just the definition. + +**Pattern 2: Numbered Steps (How-To)** +For process queries ("how do I X"), AI systems pull numbered steps almost universally. Requirements: +- Steps are numbered +- Each step is actionable (verb-first) +- Each step is self-contained (could be quoted alone and still make sense) +- 5-10 steps maximum (AI truncates longer lists) + +**Pattern 3: Comparison Table** +"X vs Y" queries almost always result in table citations. Two-column tables comparing features, costs, pros/cons — these get extracted verbatim. Format matters: clean markdown table with headers wins. + +**Pattern 4: FAQ Block** +Explicit Q&A pairs signal to AI: "this is the question, this is the answer." Mark up with FAQPage schema. Questions should exactly match how people phrase queries (voice search, question-style). + +**Pattern 5: Statistics With Attribution** +"According to [Source Name] ([Year]), X% of [population] [finding]." This format is extractable because it has a complete citation. Naked statistics without attribution get deprioritized — the AI can't verify the source. + +**Pattern 6: Expert Quote Block** +Attributed quotes from named experts get cited. The AI picks up: "According to [Name], [Role at Organization]: '[quote]'" as a citable unit. Build in a few of these per key piece. + +### Rewriting for Extractability + +When optimizing existing content: + +1. **Lead with the answer** — The first paragraph should contain the core answer to the target query. Don't save it for the conclusion. + +2. **Self-contained sections** — Every H2 section should be answerable as a standalone excerpt. If you have to read the introduction to understand a section, it's not self-contained. + +3. **Specific over vague** — "Response time improved by 40%" beats "significant improvement." AI systems prefer citable specifics. + +4. **Plain language summaries** — After complex explanations, add a 1-2 sentence plain language summary. This is what AI often lifts. + +5. **Named sources** — Replace "experts say" with "[Researcher Name], [Year]." Replace "studies show" with "[Organization] found in their [Year] survey." + +### Schema Markup for AI Discoverability + +Schema doesn't directly make you appear in AI results — but it helps AI systems understand your content type and structure. Priority schemas: + +| Schema Type | Use When | Impact | +|---|---|---| +| `Article` | Any editorial content | Establishes content as authoritative information | +| `FAQPage` | You have FAQ section | High — AI extracts Q&A pairs directly | +| `HowTo` | Step-by-step guides | High — AI uses step structure for process queries | +| `Product` | Product pages | Medium — appears in product comparison queries | +| `Organization` | Company pages | Medium — establishes entity authority | +| `Person` | Author pages | Medium — author credibility signal | + +Implement via JSON-LD in the page ``. Validate at schema.org/validator. + +--- + +## Mode 3: Monitoring + +AI search is volatile. Citations change. Track them. + +### Manual Citation Tracking + +Weekly: test your top 10 target queries on Perplexity and ChatGPT. Log: +- Were you cited? (yes/no) +- Rank in citations (1st source, 2nd, etc.) +- What text was used? + +This takes ~20 minutes/week. Do it before automated solutions exist (they don't yet, not reliably). + +### Google Search Console for AI Overviews + +Google Search Console now shows impressions in AI Overviews under "Search type: AI Overviews" filter. Check: +- Which queries trigger AI Overview impressions for your site +- Click-through rate from AI Overviews (typically 50-70% lower than organic) +- Which pages get cited + +### Visibility Signals to Track + +| Signal | Tool | Frequency | +|---|---|---| +| Perplexity citations | Manual query testing | Weekly | +| ChatGPT citations | Manual query testing | Weekly | +| Google AI Overviews | Google Search Console | Weekly | +| Copilot citations | Manual query testing | Monthly | +| AI bot crawl activity | Server logs or Cloudflare | Monthly | +| Competitor AI citations | Manual query testing | Monthly | + +See [references/monitoring-guide.md](references/monitoring-guide.md) for the full tracking setup and templates. + +### When Your Citations Drop + +If you were cited and suddenly aren't: +1. Check if competitors published something more extractable on the same topic +2. Check if your robots.txt changed (block AI bots = instant disappearance) +3. Check if your page structure changed significantly (restructuring can break citation patterns) +4. Check if your domain authority dropped (backlink loss affects AI citation too) + +--- + +## Proactive Triggers + +Flag these without being asked: + +- **AI bots blocked in robots.txt** — If GPTBot, PerplexityBot, or ClaudeBot are blocked, flag it immediately. Zero AI visibility is possible until fixed, and it's a 5-minute fix. This trumps everything else. +- **No definition block on target pages** — If the page targets informational queries but has no self-contained definition in the first 300 words, it won't win definitional AI Overviews. Flag before doing anything else. +- **Unattributed statistics** — If key pages contain statistics without named sources and years, they're less citable than competitor pages that do. Flag all naked stats. +- **Schema markup absent** — If the site has no FAQPage or HowTo schema on relevant pages, flag it as a quick structural win with asymmetric impact for process and FAQ queries. +- **JavaScript-rendered content** — If important content only appears after JavaScript execution, AI crawlers may not see it at all. Flag content that's hidden behind JS rendering. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---|---| +| AI visibility audit | Platform-by-platform citation test results + robots.txt check + content structure scorecard | +| Page optimization | Rewritten page with definition block, extractable patterns, schema markup spec, and comparison to original | +| robots.txt fix | Updated robots.txt with correct AI bot allow rules + explanation of what each bot is | +| Schema markup | JSON-LD implementation code for FAQPage, HowTo, or Article — ready to paste | +| Monitoring setup | Weekly tracking template + Google Search Console filter guide + citation log spreadsheet structure | + +--- + +## Communication + +All output follows the structured standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding includes all three +- **Actions have owners and deadlines** — no "consider reviewing..." +- **Confidence tagging** — 🟢 verified (confirmed by citation test) / 🟔 medium (pattern-based) / šŸ”“ assumed (extrapolated from limited data) + +AI SEO is still a young field. Be honest about confidence levels. What gets cited can change as platforms evolve. State what's proven vs. what's pattern-matching. + +--- + +## Related Skills + +- **content-production**: Use to create the underlying content before optimizing for AI citation. Good AI SEO requires good content first. +- **content-humanizer**: Use after writing for AI SEO. AI-sounding content ironically performs worse in AI citation — AI systems prefer content that reads credibly, which usually means human-sounding. +- **seo-audit**: Use for traditional search ranking optimization. Run both — AI SEO and traditional SEO are complementary, not competing. Many signals overlap. +- **content-strategy**: Use when deciding which topics and queries to target for AI visibility. Strategy first, then optimize. diff --git a/marketing-skill/ai-seo/references/ai-search-landscape.md b/marketing-skill/ai-seo/references/ai-search-landscape.md new file mode 100644 index 0000000..4fe376a --- /dev/null +++ b/marketing-skill/ai-seo/references/ai-search-landscape.md @@ -0,0 +1,191 @@ +# AI Search Landscape + +How each major AI search platform selects, weights, and cites sources. Use this to calibrate your optimization strategy per platform. + +Last updated: 2026-03 — this landscape changes fast. Verify platform behavior with manual testing before making major decisions. + +--- + +## The Fundamental Model + +Every AI search platform follows the same broad pipeline: + +1. **Index** — Crawl and store web content (or use a third-party index) +2. **Retrieve** — For a given query, retrieve candidate documents +3. **Extract** — Pull the most relevant passages from those documents +4. **Generate** — Synthesize an answer, often citing the sources +5. **Present** — Show the answer to the user, with or without sources visible + +Your leverage points are steps 1-3. By the time generation happens, you've either been selected or you haven't. + +--- + +## Platform-by-Platform Breakdown + +### Google AI Overviews + +**What it is:** AI-generated answer boxes appearing above organic search results. Rollout expanded globally in 2024-2025. + +**How it selects sources:** +- Uses Google's own index (you must rank in traditional Google search first — this is NOT optional) +- Strongly prefers pages that already rank in the top 10 for the query +- Favors content with structured data (FAQPage, HowTo schemas) +- The featured passage is typically lifted from a page's most extractable paragraph — usually a definition or a direct answer near the top +- Recency matters more here than elsewhere for news-adjacent queries + +**Citation behavior:** +- Shows 3-7 source links typically +- Cited sources don't always correlate with position 1-3 in organic results +- Pages that had featured snippets before AI Overviews launched tend to appear in AI Overviews + +**What to prioritize for Google AI Overviews:** +1. Rank in traditional search first (prerequisite) +2. Add FAQPage schema +3. Put a direct answer in the first 200 words +4. Get backlinks from high-authority sites (still matters) +5. Set `Google-Extended` to Allow in robots.txt + +**Monitoring:** Google Search Console → Performance → Search type: AI Overviews + +--- + +### ChatGPT (with Browsing / Search) + +**What it is:** OpenAI's ChatGPT has web browsing capability (via Bing) plus its own live search product. When users ask factual questions or enable browsing, it retrieves and cites web sources. + +**How it selects sources:** +- Uses Bing's index (Microsoft partnership) — Bing crawl and indexing quality matters +- GPTBot also crawls independently for training data (distinct from search citations) +- For search-backed answers: pulls several sources, synthesizes, cites inline +- Prefers authoritative domains — news outlets, Wikipedia, academic sources, established company blogs +- Content with clear, extractable answers wins over dense narrative + +**Citation behavior:** +- Inline citations in the answer ("according to [Source]") +- Sources panel at the bottom +- Not all cited sources get equal weight in the synthesis + +**What to prioritize for ChatGPT:** +1. Ensure Bing has indexed your pages (submit to Bing Webmaster Tools) +2. Allow `GPTBot` in robots.txt +3. Structure content with explicit definition and step patterns +4. Author attribution with credentials helps — include author bylines +5. Original data and research get preferential citation + +**Bing indexing check:** Bing Webmaster Tools → URL Inspection + +--- + +### Perplexity + +**What it is:** AI-native search engine built on real-time web retrieval. Every answer cites sources with a numbered reference panel. Among the most transparent about citation. + +**How it selects sources:** +- Has its own crawler (PerplexityBot) plus access to third-party indexes +- Real-time retrieval for every query — very current +- Strongly rewards structural clarity: numbered lists, definition blocks, tables +- Tends to pull from multiple perspectives on a query (shows variety in citations) +- Recency bias is strong — old content competes poorly against recent content on current topics + +**Citation behavior:** +- Numbers every cited source +- Shows the exact passage it pulled from (if you inspect carefully) +- Citations appear inline and in a source panel + +**What to prioritize for Perplexity:** +1. Allow `PerplexityBot` in robots.txt (critical) +2. Use numbered lists, definition blocks, and tables extensively +3. Keep content current — update pages when information changes +4. For competitive topics, publish comprehensive pieces that cover the query more completely than alternatives +5. Include specific data with dates ("In Q1 2025, X% of...") — Perplexity responds strongly to timestamped specifics + +**Tracking:** Perplexity doesn't offer a publisher dashboard. Manual testing is the only method currently. + +--- + +### Claude (Anthropic) + +**What it is:** Claude.ai now has web search capability. When users ask questions that require current information, Claude retrieves and cites sources. + +**How it selects sources:** +- Uses a third-party search index (search partnership) +- ClaudeBot crawls for training purposes — separate from search citations +- Prefers clearly structured, credible content +- High-authority domains get preference +- Technical and expert-authored content performs well given Claude's user base + +**Citation behavior:** +- Inline citations in responses +- Source list at end of response +- Tends toward fewer, higher-quality citations vs. showing many sources + +**What to prioritize for Claude:** +1. Allow `ClaudeBot` and `anthropic-ai` in robots.txt +2. Focus on content quality and accuracy — Claude's users are often technical and will notice errors +3. Expert authorship and institutional credibility matter here +4. Long-form, well-researched pieces tend to perform better than thin listicles + +--- + +### Google Gemini + +**What it is:** Google's AI assistant, separate from Google Search but increasingly integrated. Uses Google's web index. + +**How it selects sources:** +- Full access to Google's index +- Similar selection criteria to Google AI Overviews but different interface +- Schema markup influences what Gemini can understand about your content type +- Prefers content that directly answers conversational queries + +**What to prioritize for Gemini:** +- Same fundamentals as Google AI Overviews (they share the index) +- Conversational phrasing in your content helps — Gemini handles voice/chat-style queries +- Allow `Google-Extended` in robots.txt (covers both AI Overviews and Gemini) + +--- + +### Microsoft Copilot + +**What it is:** Microsoft's AI assistant integrated into Bing, Windows, Office 365, and Edge. Uses Bing's index. + +**How it selects sources:** +- Bing index (same as ChatGPT browsing) +- Integrated into productivity contexts — Office documents, business queries +- B2B and professional content performs particularly well +- Bing's relevance signals apply + +**Citation behavior:** +- Source cards in the Copilot interface +- Inline citations in longer answers + +**What to prioritize for Copilot:** +- Ensure strong Bing indexing (submit to Bing Webmaster Tools, build Bing-friendly signals) +- For B2B companies: professional tone and industry-specific expertise matters more here +- FAQ and definition patterns work well for business query types + +--- + +## Cross-Platform Summary + +| Signal | Google AI Overviews | ChatGPT | Perplexity | Claude | Copilot | +|---|---|---|---|---|---| +| Must rank in traditional search | āœ… Yes | Bing only | No | No | Bing only | +| Bot to allow | Google-Extended | GPTBot | PerplexityBot | ClaudeBot | (via Bing) | +| Schema markup impact | High | Medium | Low | Medium | Medium | +| Content recency weight | High | Medium | Very high | Medium | Medium | +| Original data advantage | High | High | High | High | High | +| FAQ pattern extraction | Very high | High | High | Medium | High | +| Numbered steps extraction | High | High | Very high | High | High | +| Author attribution impact | Medium | High | Low | High | Medium | + +--- + +## What No Platform Does (Yet) + +Things that are widely assumed but not confirmed: + +- **Direct "opt-in to citations" programs**: None of the major platforms have a verified publisher program that guarantees citation +- **Predictable citation ranking**: Even with perfect structure, citations are non-deterministic — the same query on the same platform can produce different citations on consecutive days +- **Real-time citation tracking**: No platform offers publishers a dashboard showing when they're cited and for which queries (Google Search Console for AI Overviews is the closest, and it's limited) + +Plan your AI SEO strategy for influence, not for guaranteed outcomes. Maximize your signal quality, then track and iterate. diff --git a/marketing-skill/ai-seo/references/content-patterns.md b/marketing-skill/ai-seo/references/content-patterns.md new file mode 100644 index 0000000..c644fbf --- /dev/null +++ b/marketing-skill/ai-seo/references/content-patterns.md @@ -0,0 +1,276 @@ +# Content Patterns for AI Citability + +Ready-to-use block templates for each content pattern that AI search engines reliably extract and cite. Copy, adapt, and embed in your pages. + +--- + +## Why Patterns Matter + +AI systems don't read pages the way humans do. They scan for extractable chunks — self-contained passages that can be pulled out and quoted without losing meaning. + +The patterns below are structured to be self-contained by design. If the AI pulls paragraph 3 without paragraph 2, the citation should still make sense. + +--- + +## Pattern 1: Definition Block + +**Used for:** "What is X" queries — the most common AI Overview trigger. + +**Requirements:** +- First sentence: direct definition +- Second sentence: why it matters or how it works +- Third sentence (optional): example or context +- Placed in first 300 words of the page + +**Template:** +```markdown +**[Term]** is [precise definition — what it is, what it does, who uses it]. +[One sentence on why it matters or what problem it solves]. +[Optional: one sentence example — "For example, a SaaS company might use X to..."]. +``` + +**Example:** +```markdown +**Churn rate** is the percentage of customers who cancel or stop using a service within a given period, typically measured monthly or annually. It directly impacts recurring revenue — a 5% monthly churn means losing over half your customer base each year. For subscription SaaS, a healthy monthly churn rate is typically below 2%. +``` + +**Tips:** +- Bold the term on its first use +- Don't start with "In the world of..." or "When it comes to..." +- The definition should work even if the reader knows nothing about the topic + +--- + +## Pattern 2: Numbered Steps (How-To) + +**Used for:** "How to X" and "How do I X" queries. + +**Requirements:** +- Numbered list (not bulleted) +- Each step starts with an action verb +- Each step is self-contained (can be cited alone) +- 5-10 steps maximum +- Pair with HowTo schema markup + +**Template:** +```markdown +## How to [Task] + +1. **[Verb phrase]** — [1-2 sentence explanation of this specific step] +2. **[Verb phrase]** — [1-2 sentence explanation] +3. **[Verb phrase]** — [1-2 sentence explanation] +4. **[Verb phrase]** — [1-2 sentence explanation] +5. **[Verb phrase]** — [1-2 sentence explanation] +``` + +**Example:** +```markdown +## How to Reduce SaaS Churn + +1. **Define your activation event** — Identify the specific action that signals a user has experienced core product value. For Slack, it's 2,000 messages sent. For Dropbox, it's saving the first file. +2. **Instrument the activation funnel** — Add event tracking from signup to activation. Find the step where most users drop off — that's your highest-leverage point. +3. **Build a customer health score** — Combine login frequency, feature adoption, and support ticket volume into a single score. Customers below 40 get proactive outreach. +4. **Segment churn by cohort** — Not all churn looks the same. Compare churn rates by acquisition channel, onboarding path, and company size to find patterns. +5. **Interview churned customers** — The customers who left quietly are more valuable than the ones who complained. Call 10 churned accounts per month and ask what they were trying to accomplish. +``` + +**Schema markup (JSON-LD):** +```json +{ + "@context": "https://schema.org", + "@type": "HowTo", + "name": "How to [Task]", + "step": [ + {"@type": "HowToStep", "name": "Step 1 name", "text": "Step 1 explanation"}, + {"@type": "HowToStep", "name": "Step 2 name", "text": "Step 2 explanation"} + ] +} +``` + +--- + +## Pattern 3: Comparison Table + +**Used for:** "X vs Y" and "best X for Y" queries. + +**Requirements:** +- Header row with category names +- First column: feature or criterion +- Remaining columns: the things being compared +- Keep it focused — 5-10 rows maximum +- Don't try to cover everything; cover what matters most + +**Template:** +```markdown +| Feature | [Option A] | [Option B] | [Option C] | +|---|---|---|---| +| [Criterion 1] | [Value] | [Value] | [Value] | +| [Criterion 2] | [Value] | [Value] | [Value] | +| [Criterion 3] | [Value] | [Value] | [Value] | +| Best for | [Audience A] | [Audience B] | [Audience C] | +| Pricing | [Range] | [Range] | [Range] | +``` + +**Tips:** +- Put the most important criteria first +- Use simple values — "Yes / No / Partial" beats long prose in cells +- Include a "Best for" row — AI systems use this for recommendation queries +- Add a sentence below the table summarizing the verdict: "X is best for teams that need A; Y is better when B matters more." + +--- + +## Pattern 4: FAQ Block + +**Used for:** Question-style queries, People Also Ask queries, voice search. + +**Requirements:** +- Question phrased exactly as someone would ask it (natural language) +- Answer is complete in 2-4 sentences (no "read more in section 3") +- 5-10 FAQs per block +- Pair with FAQPage schema markup + +**Template:** +```markdown +## Frequently Asked Questions + +**What is [X]?** +[2-4 sentence complete answer] + +**How does [X] work?** +[2-4 sentence complete answer] + +**What's the difference between [X] and [Y]?** +[2-4 sentence complete answer] + +**How much does [X] cost?** +[2-4 sentence complete answer] + +**Is [X] right for [audience]?** +[2-4 sentence complete answer] +``` + +**Schema markup (JSON-LD):** +```json +{ + "@context": "https://schema.org", + "@type": "FAQPage", + "mainEntity": [ + { + "@type": "Question", + "name": "What is [X]?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Complete answer text here" + } + } + ] +} +``` + +**Tips:** +- Write questions the way users actually type or speak them — use Google's "People Also Ask" as a source +- Answers should be complete without needing context from anywhere else on the page +- Don't start answers with "Great question" or "That's a common question" — just answer + +--- + +## Pattern 5: Statistic with Attribution + +**Used for:** Data queries, "how many" queries, research-backed claims. + +**Requirements:** +- Named source (not "a study" — the actual organization name) +- Year of the data +- Specific number (not "many" or "most") +- Context (what the number means) + +**Template:** +```markdown +According to [Organization Name]'s [Report Name] ([Year]), [specific statistic with units]. [One sentence on what this means or why it matters]. +``` + +**Example:** +```markdown +According to the Baymard Institute's 2024 UX benchmarking study, 69.8% of online shopping carts are abandoned before purchase. For a $1M/month ecommerce store, recovering just 5% of abandoned carts represents $35,000 in monthly revenue. +``` + +**Tips:** +- Link to the original source (AI systems and readers both benefit) +- If data is from your own research, say so: "In our 2025 survey of 500 SaaS founders..." +- Proprietary data is the highest-value citation target — AI systems actively seek original research + +--- + +## Pattern 6: Expert Quote Block + +**Used for:** Authority building, "what do experts say" queries. + +**Requirements:** +- Full name of the person quoted +- Their title and organization +- A quote that's substantive (not a generic endorsement) +- Brief context sentence before the quote + +**Template:** +```markdown +[Context sentence explaining why this person's view matters.] + +"[Direct quote — specific, substantive, something only they would say]," says [Full Name], [Title] at [Organization]. +``` + +**Example:** +```markdown +Patrick Campbell, founder of ProfitWell (acquired by Paddle), studied pricing data from over 30,000 SaaS companies before reaching a counterintuitive conclusion about churn. + +"Most churn that looks like pricing dissatisfaction is actually failed onboarding," says Campbell. "The customer never saw the value that justified the price. That's a different problem than being too expensive." +``` + +**Tips:** +- Don't use generic quotes ("innovation is key to success") — they add nothing +- Quotes should contain a specific claim, data point, or perspective +- If quoting your own team: "[Name], [Title] at [Company Name]" is still valid +- Live quotes (from interviews or primary research) outperform secondary quotes from other articles + +--- + +## Pattern 7: Quick-Scan Summary Box + +**Used for:** Queries where users want the TL;DR before committing to the full article. + +**Requirements:** +- Placed near the top of the article (after the intro) +- 3-7 key takeaways +- Each bullet stands alone — no context required +- Labeled clearly ("Key Takeaways" or "Quick Summary") + +**Template:** +```markdown +**Key Takeaways** +- [Specific, complete takeaway — could be read as a tweet] +- [Specific, complete takeaway] +- [Specific, complete takeaway] +- [Specific, complete takeaway] +- [Specific, complete takeaway] +``` + +**Tips:** +- This is often the block AI systems extract for "summary" type queries +- Make each bullet specific: "Monthly churn below 2% is considered healthy for most SaaS" beats "Churn should be low" +- Don't repeat the article intro verbatim — these should be the most actionable insights + +--- + +## Combining Patterns + +The most citable pages combine multiple patterns throughout the piece: + +**Recommended page structure for maximum AI extractability:** +1. Definition block (first 300 words) +2. Quick summary box (right after intro) +3. Body sections with numbered steps or subsections +4. Data points with full attribution throughout +5. Comparison table (if competitive topic) +6. FAQ block (before conclusion) +7. Expert quote (to add authority) + +A page with all 7 patterns has significantly more extractable surface area than a page with prose only. The AI has more options to pull from and a higher probability of finding something that perfectly matches the query. diff --git a/marketing-skill/ai-seo/references/monitoring-guide.md b/marketing-skill/ai-seo/references/monitoring-guide.md new file mode 100644 index 0000000..f0f6928 --- /dev/null +++ b/marketing-skill/ai-seo/references/monitoring-guide.md @@ -0,0 +1,208 @@ +# AI Visibility Monitoring Guide + +How to track whether your content is getting cited by AI search engines — and what to do when citations change. + +The honest truth: AI citation monitoring is immature. There's no Google Search Console equivalent for Perplexity or ChatGPT. Most tracking is manual today. This guide covers what works now and what to watch for as tooling matures. + +--- + +## What You're Tracking + +**Goal:** Know when you appear in AI answers, for which queries, on which platforms — and detect changes before your traffic is affected. + +**The challenge:** Most AI search platforms don't give publishers visibility into their citation data. You're reverse-engineering your presence through manual testing and indirect signals. + +**Four things to track:** +1. Citation presence — are you appearing at all? +2. Citation consistency — do you appear most of the time or occasionally? +3. Competitor citations — who else is cited for your target queries? +4. Traffic signals — is AI-driven traffic changing? + +--- + +## Platform-by-Platform Monitoring + +### Google AI Overviews — Best Current Tooling + +Google Search Console is the best data source available for any AI platform: + +**Setup:** +1. Open Google Search Console → Performance → Search results +2. Add filter: "Search type" → "AI Overviews" +3. Set date range to last 90 days minimum + +**What you see:** +- Queries where your pages appeared in AI Overviews +- Impressions from AI Overviews +- Clicks from AI Overviews (usually much lower than organic — users get the answer in the AI box) +- CTR from AI Overviews + +**What to do with it:** +- Sort by impressions: these are your current AI Overview presences +- Sort by clicks: these are the queries where users still clicked through (high-value) +- Identify queries where you have impressions but zero clicks — consider whether that's acceptable or if you need to gate more value behind the click +- Watch for queries where impressions drop sharply — you may have lost an AI Overview position + +**Frequency:** Weekly check. Pull a CSV monthly for trend analysis. + +--- + +### Perplexity — Manual Testing Protocol + +Perplexity has no publisher dashboard. Manual testing is the only reliable method. + +**Weekly test protocol:** +1. Identify your 10-20 highest-priority target queries +2. Search each query on perplexity.ai in an incognito window +3. Check the Sources panel on the right side +4. Record: cited (yes/no), position in sources (1st, 2nd, 3rd...), which page was cited + +**What to record in your tracking log:** + +| Date | Query | Cited? | Position | Cited URL | Top Competitor | +|---|---|---|---|---|---| +| 2026-03-06 | "how to reduce SaaS churn" | Yes | 2 | /blog/churn-reduction | competitor.com | +| 2026-03-06 | "SaaS churn rate benchmark" | No | — | — | competitor.com | + +**Patterns to watch for:** +- Same query cited 4/4 weeks → stable citation (protect it) +- Citation appearing intermittently (2 out of 4 weeks) → fragile position (strengthen the page) +- Consistent non-citation → gap to fill (page missing extractable patterns) + +**Frequency:** Weekly for top 10 queries. Monthly for the full list. + +--- + +### ChatGPT — Manual Testing Protocol + +**Requirements:** ChatGPT Plus (for web browsing) or ChatGPT with Search enabled. + +**Test protocol:** +1. Start a new conversation (fresh context window) +2. Enable browsing / search mode +3. Ask your target query as a natural question +4. Check citations in the response +5. Click through to verify which pages are cited + +**Note:** ChatGPT citations vary by session. The same query may cite different sources on consecutive days. This is by design — treat it as probabilistic. Your goal is to appear in the citation set, not to appear every time. + +**What to test:** +- Exact keyword queries ("best email marketing software") +- Natural question queries ("what's the best email marketing software for small teams?") +- Comparison queries ("mailchimp vs klaviyo") + +**Frequency:** Monthly (due to variability, weekly is too noisy to be useful). + +--- + +### Microsoft Copilot — Manual Testing Protocol + +Access at copilot.microsoft.com or via Edge sidebar. + +Same protocol as ChatGPT. Look for source cards that appear with citations. Copilot integrates Bing's index, so if your Bing presence is strong, Copilot citations follow. + +**Bing indexing check:** +- Submit sitemap to Bing Webmaster Tools +- Run URL inspection to verify pages are indexed +- Check Bing Webmaster Tools for crawl errors on key pages + +**Frequency:** Monthly. + +--- + +## Traffic Analysis for AI Citation Signals + +Even without direct citation data, traffic patterns can signal AI search activity: + +### Zero-Click Traffic Signals + +When AI answers queries, fewer users click through. Watch for: + +**Impression growth + traffic decline:** If Google Search Console shows impressions growing for a keyword but organic clicks dropping, an AI Overview may be answering the query. You're being cited but not visited. + +**Query pattern in GSC:** If informational queries show impression growth but navigational/commercial queries stay flat, AI Overviews are likely answering the informational queries. + +### Direct Traffic Anomalies + +Some AI platforms (Claude, Gemini) show traffic as "direct" since users often copy/paste URLs rather than clicking. An increase in direct traffic to specific content pages (not your homepage) can signal AI-driven attention. + +### Referral Traffic from AI Platforms + +Perplexity, ChatGPT, and Claude all send some referral traffic when users click cited sources. Set up in Google Analytics 4: + +1. Create a custom dimension tracking referral source +2. Filter for: `perplexity.ai`, `chat.openai.com`, `claude.ai`, `copilot.microsoft.com` +3. Track monthly — expect low absolute numbers but high engagement (these visitors are already pre-qualified) + +--- + +## Tracking Template + +**Weekly AI Citation Tracker (copy this structure):** + +``` +Week of: [DATE] + +GOOGLE AI OVERVIEWS (from Search Console): +- New queries with AI Overview impressions: [list] +- Queries that dropped out: [list] +- Top performing query: [query] — [# impressions] impressions + +PERPLEXITY (manual tests): +Query: [query 1] → Cited: Y/N → Position: [#] → Competitor: [domain] +Query: [query 2] → Cited: Y/N → Position: [#] → Competitor: [domain] +Query: [query 3] → Cited: Y/N → Position: [#] → Competitor: [domain] + +NOTABLE CHANGES: +- [Describe any significant wins or losses] + +ACTIONS FROM LAST WEEK: +- [What we optimized] → [Result this week] + +ACTIONS FOR NEXT WEEK: +- [Page to optimize]: [Specific change to make] +``` + +--- + +## When Citations Drop + +### Immediate Diagnostic + +If you notice a citation you had has disappeared: + +1. **Check robots.txt** — Did someone accidentally block an AI crawler? Check `yourdomain.com/robots.txt` and test each bot. + +2. **Check the page itself** — Did the page structure change? Was the definition block moved? Was the FAQ section deleted in an edit? + +3. **Check competitor pages** — Did a competitor publish a more extractable version of the same content? Search the query and see who now appears. + +4. **Check page performance** — Is the page load slower? Did it get added to a noindex? Did canonical tags change? + +5. **Check domain authority signals** — Did you lose significant backlinks? Authority drops can affect AI citations on competitive queries. + +### Response Playbook + +| Root cause | Fix | +|---|---| +| AI bot blocked | Update robots.txt — typically resolves in 1-4 weeks | +| Page restructured (patterns removed) | Restore extractable patterns (definition block, FAQ, steps) | +| Competitor outranked you | Strengthen the page: more specific data, better structure, schema markup | +| Authority drop | Rebuild backlinks; also check for manual penalty in Google Search Console | +| Page went slow | Fix Core Web Vitals — AI crawlers deprioritize slow pages | +| Content became outdated | Update with current data and year | + +--- + +## Emerging Tools to Watch + +The AI citation monitoring space is early-stage. Tools being developed as of early 2026: + +- **Semrush AI toolkit** — Testing AI Overview tracking features +- **Ahrefs AI Overviews** — Added to their rank tracker +- **Perplexity publisher analytics** — Announced but not launched at time of writing +- **OpenAI publisher program** — Rumored; no confirmed release date + +Track announcements from these vendors. First-mover advantage on publisher analytics will be significant. + +**Until then:** Manual testing + Google Search Console is the most reliable stack available. Don't let perfect be the enemy of done — weekly manual testing surfaces 80% of what you need to know. diff --git a/marketing-skill/analytics-tracking/SKILL.md b/marketing-skill/analytics-tracking/SKILL.md new file mode 100644 index 0000000..45fd92b --- /dev/null +++ b/marketing-skill/analytics-tracking/SKILL.md @@ -0,0 +1,371 @@ +--- +name: analytics-tracking +description: "Set up, audit, and debug analytics tracking implementation — GA4, Google Tag Manager, event taxonomy, conversion tracking, and data quality. Use when building a tracking plan from scratch, auditing existing analytics for gaps or errors, debugging missing events, or setting up GTM. Trigger keywords: GA4 setup, Google Tag Manager, GTM, event tracking, analytics implementation, conversion tracking, tracking plan, event taxonomy, custom dimensions, UTM tracking, analytics audit, missing events, tracking broken. NOT for analyzing marketing campaign data — use campaign-analytics for that. NOT for BI dashboards — use product-analytics for in-product event analysis." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Analytics Tracking + +You are an expert in analytics implementation. Your goal is to make sure every meaningful action in the customer journey is captured accurately, consistently, and in a way that can actually be used for decisions — not just for the sake of having data. + +Bad tracking is worse than no tracking. Duplicate events, missing parameters, unconsented data, and broken conversions lead to decisions made on bad data. This skill is about building it right the first time, or finding what's broken and fixing it. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for what's missing. + +Gather this context: + +### 1. Current State +- Do you have GA4 and/or GTM already set up? If so, what's broken or missing? +- What's your tech stack? (React SPA, Next.js, WordPress, custom, etc.) +- Do you have a consent management platform (CMP)? Which one? +- What events are you currently tracking (if any)? + +### 2. Business Context +- What are your primary conversion actions? (signup, purchase, lead form, free trial start) +- What are your key micro-conversions? (pricing page view, feature discovery, demo request) +- Do you run paid campaigns? (Google Ads, Meta, LinkedIn — affects conversion tracking needs) + +### 3. Goals +- Building from scratch, auditing existing, or debugging a specific issue? +- Do you need cross-domain tracking? Multiple properties or subdomains? +- Server-side tagging requirement? (GDPR-sensitive markets, performance concerns) + +## How This Skill Works + +### Mode 1: Set Up From Scratch +No analytics in place — we'll build the tracking plan, implement GA4 and GTM, define the event taxonomy, and configure conversions. + +### Mode 2: Audit Existing Tracking +Tracking exists but you don't trust the data, coverage is incomplete, or you're adding new goals. We'll audit what's there, gap-fill, and clean up. + +### Mode 3: Debug Tracking Issues +Specific events are missing, conversion numbers don't add up, or GTM preview shows events firing but GA4 isn't recording them. Structured debugging workflow. + +--- + +## Event Taxonomy Design + +Get this right before touching GA4 or GTM. Retrofitting taxonomy is painful. + +### Naming Convention + +**Format:** `object_action` (snake_case, verb at the end) + +| āœ… Good | āŒ Bad | +|--------|--------| +| `form_submit` | `submitForm`, `FormSubmitted`, `form-submit` | +| `plan_selected` | `clickPricingPlan`, `selected_plan`, `PlanClick` | +| `video_started` | `videoPlay`, `StartVideo`, `VideoStart` | +| `checkout_completed` | `purchase`, `buy_complete`, `checkoutDone` | + +**Rules:** +- Always `noun_verb` not `verb_noun` +- Lowercase + underscores only — no camelCase, no hyphens +- Be specific enough to be unambiguous, not so verbose it's a sentence +- Consistent tense: `_started`, `_completed`, `_failed` (not mix of past/present) + +### Standard Parameters + +Every event should include these where applicable: + +| Parameter | Type | Example | Purpose | +|-----------|------|---------|---------| +| `page_location` | string | `https://app.co/pricing` | Auto-captured by GA4 | +| `page_title` | string | `Pricing - Acme` | Auto-captured by GA4 | +| `user_id` | string | `usr_abc123` | Link to your CRM/DB | +| `plan_name` | string | `Professional` | Segment by plan | +| `value` | number | `99` | Revenue/order value | +| `currency` | string | `USD` | Required with value | +| `content_group` | string | `onboarding` | Group pages/flows | +| `method` | string | `google_oauth` | How (signup method, etc.) | + +### Event Taxonomy for SaaS + +**Core funnel events:** +``` +visitor_arrived (page view — automatic in GA4) +signup_started (user clicked "Sign up") +signup_completed (account created successfully) +trial_started (free trial began) +onboarding_step_completed (param: step_name, step_number) +feature_activated (param: feature_name) +plan_selected (param: plan_name, billing_period) +checkout_started (param: value, currency, plan_name) +checkout_completed (param: value, currency, transaction_id) +subscription_cancelled (param: cancel_reason, plan_name) +``` + +**Micro-conversion events:** +``` +pricing_viewed +demo_requested (param: source) +form_submitted (param: form_name, form_location) +content_downloaded (param: content_name, content_type) +video_started (param: video_title) +video_completed (param: video_title, percent_watched) +chat_opened +help_article_viewed (param: article_name) +``` + +See [references/event-taxonomy-guide.md](references/event-taxonomy-guide.md) for the full taxonomy catalog with custom dimension recommendations. + +--- + +## GA4 Setup + +### Data Stream Configuration + +1. **Create property** in GA4 → Admin → Properties → Create +2. **Add web data stream** with your domain +3. **Enhanced Measurement** — enable all, then review: + - āœ… Page views (keep) + - āœ… Scrolls (keep) + - āœ… Outbound clicks (keep) + - āœ… Site search (keep if you have search) + - āš ļø Video engagement (disable if you'll track videos manually — avoid duplicates) + - āš ļø File downloads (disable if you'll track these in GTM for better parameters) +4. **Configure domains** — add all subdomains used in your funnel + +### Custom Events in GA4 + +For any event not auto-collected, create it in GTM (preferred) or via gtag directly: + +**Via gtag:** +```javascript +gtag('event', 'signup_completed', { + method: 'email', + user_id: 'usr_abc123', + plan_name: 'trial' +}); +``` + +**Via GTM data layer (preferred — see GTM section):** +```javascript +window.dataLayer.push({ + event: 'signup_completed', + signup_method: 'email', + user_id: 'usr_abc123' +}); +``` + +### Conversions Configuration + +Mark these events as conversions in GA4 → Admin → Conversions: +- `signup_completed` +- `checkout_completed` +- `demo_requested` +- `trial_started` (if separate from signup) + +**Rules:** +- Max 30 conversion events per property — curate, don't mark everything +- Conversions are retroactive in GA4 — turning one on applies to 6 months of history +- Don't mark micro-conversions as conversions unless you're optimizing ad campaigns for them + +--- + +## Google Tag Manager Setup + +### Container Structure + +``` +GTM Container +ā”œā”€ā”€ Tags +│ ā”œā”€ā”€ GA4 Configuration (fires on all pages) +│ ā”œā”€ā”€ GA4 Event — [event_name] (one tag per event) +│ ā”œā”€ā”€ Google Ads Conversion (per conversion action) +│ └── Meta Pixel (if running Meta ads) +ā”œā”€ā”€ Triggers +│ ā”œā”€ā”€ All Pages +│ ā”œā”€ā”€ DOM Ready +│ ā”œā”€ā”€ Data Layer Event — [event_name] +│ └── Custom Element Click — [selector] +└── Variables + ā”œā”€ā”€ Data Layer Variables (dlv — for each dL key) + ā”œā”€ā”€ Constant — GA4 Measurement ID + └── JavaScript Variables (computed values) +``` + +### Tag Patterns for SaaS + +**Pattern 1: Data Layer Push (most reliable)** + +Your app pushes to dataLayer → GTM picks it up → sends to GA4. + +```javascript +// In your app code (on event): +window.dataLayer = window.dataLayer || []; +window.dataLayer.push({ + event: 'signup_completed', + signup_method: 'email', + user_id: userId, + plan_name: 'trial' +}); +``` + +``` +GTM Tag: GA4 Event + Event Name: {{DLV - event}} OR hardcode "signup_completed" + Parameters: + signup_method: {{DLV - signup_method}} + user_id: {{DLV - user_id}} + plan_name: {{DLV - plan_name}} +Trigger: Custom Event - "signup_completed" +``` + +**Pattern 2: CSS Selector Click** + +For events triggered by UI elements without app-level hooks. + +``` +GTM Trigger: + Type: Click - All Elements + Conditions: Click Element matches CSS selector [data-track="demo-cta"] + +GTM Tag: GA4 Event + Event Name: demo_requested + Parameters: + page_location: {{Page URL}} +``` + +See [references/gtm-patterns.md](references/gtm-patterns.md) for full configuration templates. + +--- + +## Conversion Tracking: Platform-Specific + +### Google Ads + +1. Create conversion action in Google Ads → Tools → Conversions +2. Import GA4 conversions (recommended — single source of truth) OR use the Google Ads tag +3. Set attribution model: **Data-driven** (if >50 conversions/month), otherwise **Last click** +4. Conversion window: 30 days for lead gen, 90 days for high-consideration purchases + +### Meta (Facebook/Instagram) Pixel + +1. Install Meta Pixel base code via GTM +2. Standard events: `PageView`, `Lead`, `CompleteRegistration`, `Purchase` +3. Conversions API (CAPI) strongly recommended — client-side pixel loses ~30% of conversions due to ad blockers and iOS +4. CAPI requires server-side implementation (Meta's docs or GTM server-side) + +--- + +## Cross-Platform Tracking + +### UTM Strategy + +Enforce strict UTM conventions or your channel data becomes noise. + +| Parameter | Convention | Example | +|-----------|-----------|---------| +| `utm_source` | Platform name (lowercase) | `google`, `linkedin`, `newsletter` | +| `utm_medium` | Traffic type | `cpc`, `email`, `social`, `organic` | +| `utm_campaign` | Campaign ID or name | `q1-trial-push`, `brand-awareness` | +| `utm_content` | Ad/creative variant | `hero-cta-blue`, `text-link` | +| `utm_term` | Paid keyword | `saas-analytics` | + +**Rule:** Never tag organic or direct traffic with UTMs. UTMs override GA4's automatic source/medium attribution. + +### Attribution Windows + +| Platform | Default Window | Recommended for SaaS | +|---------|---------------|---------------------| +| GA4 | 30 days | 30-90 days depending on sales cycle | +| Google Ads | 30 days | 30 days (trial), 90 days (enterprise) | +| Meta | 7-day click, 1-day view | 7-day click only | +| LinkedIn | 30 days | 30 days | + +### Cross-Domain Tracking + +For funnels that cross domains (e.g., `acme.com` → `app.acme.com`): + +1. In GA4 → Admin → Data Streams → Configure tag settings → List unwanted referrals → Add both domains +2. In GTM → GA4 Configuration tag → Cross-domain measurement → Add both domains +3. Test: visit domain A, click link to domain B, check GA4 DebugView — session should not restart + +--- + +## Data Quality + +### Deduplication + +**Events firing twice?** Common causes: +- GTM tag + hardcoded gtag both firing +- Enhanced Measurement + custom GTM tag for same event +- SPA router firing pageview on every route change AND GTM page view tag + +Fix: Audit GTM Preview for double-fires. Check Network tab in DevTools for duplicate hits. + +### Bot Filtering + +GA4 filters known bots automatically. For internal traffic: +1. GA4 → Admin → Data Filters → Internal Traffic +2. Add your office IPs and developer IPs +3. Enable filter (starts as testing mode — activate it) + +### Consent Management Impact + +Under GDPR/ePrivacy, analytics may require consent. Plan for this: + +| Consent Mode setting | Impact | +|---------------------|--------| +| **No consent mode** | Visitors who decline cookies → zero data | +| **Basic consent mode** | Visitors who decline → zero data | +| **Advanced consent mode** | Visitors who decline → modeled data (GA4 estimates using consented users) | + +**Recommendation:** Implement Advanced Consent Mode via GTM. Requires CMP integration (Cookiebot, OneTrust, Usercentrics, etc.). + +Expected consent rate by region: 60-75% EU, 85-95% US. + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Events firing on every page load** → Symptom of misconfigured trigger. Flag: duplicate data inflation. +- **No user_id being passed** → You can't connect analytics to your CRM or understand cohorts. Flag for fix. +- **Conversions not matching GA4 vs Ads** → Attribution window mismatch or pixel duplication. Flag for audit. +- **No consent mode configured in EU markets** → Legal exposure and underreported data. Flag immediately. +- **All pages showing as "/(not set)" or generic paths** → SPA routing not handled. GA4 is recording wrong pages. +- **UTM source showing as "direct" for paid campaigns** → UTMs missing or being stripped. Traffic attribution is broken. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|--------------------|-----------| +| "Build a tracking plan" | Event taxonomy table (events + parameters + triggers), GA4 configuration checklist, GTM container structure | +| "Audit my tracking" | Gap analysis vs. standard SaaS funnel, data quality scorecard (0-100), prioritized fix list | +| "Set up GTM" | Tag/trigger/variable configuration for each event, container setup checklist | +| "Debug missing events" | Structured debugging steps using GTM Preview + GA4 DebugView + Network tab | +| "Set up conversion tracking" | Conversion action configuration for GA4 + Google Ads + Meta | +| "Generate tracking plan" | Run `scripts/tracking_plan_generator.py` with your inputs | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — what's broken or what needs building before methodology +- **What + Why + How** — every finding has all three +- **Actions have owners and deadlines** — no vague "consider implementing" +- **Confidence tagging** — 🟢 verified / 🟔 estimated / šŸ”“ assumed + +--- + +## Related Skills + +- **campaign-analytics**: Use for analyzing marketing performance and channel ROI. NOT for implementation — use this skill for tracking setup. +- **ab-test-setup**: Use when designing experiments. NOT for event tracking setup (though this skill's events feed A/B tests). +- **analytics-tracking** (this skill): covers setup only. For dashboards and reporting, use campaign-analytics. +- **seo-audit**: Use for technical SEO. NOT for analytics tracking (though both use GA4 data). +- **gdpr-dsgvo-expert**: Use for GDPR compliance posture. This skill covers consent mode implementation; that skill covers the full compliance framework. diff --git a/marketing-skill/analytics-tracking/references/debugging-playbook.md b/marketing-skill/analytics-tracking/references/debugging-playbook.md new file mode 100644 index 0000000..9b6d5c7 --- /dev/null +++ b/marketing-skill/analytics-tracking/references/debugging-playbook.md @@ -0,0 +1,224 @@ +# Tracking Debug Playbook + +Step-by-step methodology for diagnosing and fixing analytics tracking issues. + +--- + +## The Debug Mindset + +Analytics bugs are harder than code bugs because: +1. They fail silently — no error thrown, just missing data +2. They often only appear in production +3. They can be caused by timing, consent, ad blockers, or just configuration + +Work systematically. Don't guess. Verify at each layer before moving to the next. + +--- + +## The Debug Stack (Bottom-Up) + +``` +Layer 5: GA4 Reports / DebugView ← what you see +Layer 4: GA4 Data Processing ← where it lands +Layer 3: Network Request ← what was sent +Layer 2: GTM / Tag firing ← what GTM did +Layer 1: dataLayer / App code ← what your app pushed +``` + +When something's missing at Layer 5, start at Layer 1 and verify each layer before going up. + +--- + +## Tool Setup + +### GTM Preview Mode + +1. GTM → Preview (top right) +2. Enter your site URL → Connect +3. A blue bar appears at the bottom of your site: "Google Tag Manager" +4. GTM Preview panel opens in a separate tab +5. Perform the action you're debugging +6. Check: did the expected tag fire? + +**Reading GTM Preview:** +- Left panel: events as they occur (Page View, Click, Custom Event, etc.) +- Middle panel: Tags fired / Tags NOT fired for selected event +- Right panel: Variables values at the time of the event + +### GA4 DebugView + +1. GA4 → Admin → DebugView +2. Enable debug mode via: + - GTM: add `debug_mode: true` to your GA4 Event tag parameters + - Extension: install "GA Debugger" Chrome extension + - URL parameter: add `?_gl=` or use GA4 debug parameter +3. Perform actions on your site +4. Watch events appear in real-time (10-15 second delay) + +### Chrome DevTools — Network Tab + +1. Open DevTools → Network +2. Filter by: `collect` or `google-analytics` or `analytics` +3. Perform the action +4. Look for requests to `https://www.google-analytics.com/g/collect` +5. Click the request → Payload tab → view parameters + +--- + +## Common Issues and Fixes + +### Issue: Event fires in GTM Preview but not in GA4 + +**Possible causes:** + +1. **Consent mode blocking** — user is in denied state + - Check: In GTM Preview, look at Variables → `Analytics Storage` — is it `denied`? + - Fix: Test with consent granted, or implement Advanced Consent Mode + +2. **Filters blocking data** — internal traffic filter is active + - Check: GA4 → Admin → Data Filters — is "Internal Traffic" filter active? + - Fix: Disable filter temporarily, test, then re-enable and exclude your IP correctly + +3. **Debug mode not enabled** — DebugView only shows debug-mode traffic + - Check: Is `debug_mode: true` parameter on the GA4 Event tag? + - Fix: Add it, or use the GA4 Debugger Chrome extension + +4. **Wrong property** — you're looking at a different GA4 property + - Check: Confirm Measurement ID in GTM matches the GA4 property you're viewing + - Fix: Compare `G-XXXXXXXXXX` in GTM vs. GA4 Data Stream settings + +5. **Duplicate GA4 configuration tags** — two config tags = double sessions + weird data + - Check: GTM → Tags → filter by "GA4 Configuration" — more than one? + - Fix: Delete duplicates, keep one with All Pages trigger + +--- + +### Issue: Event not firing in GTM Preview at all + +**Diagnosis path:** + +**Step 1:** Check the trigger +- Is the trigger for this tag listed under the action in GTM Preview? +- If not: the trigger didn't fire + +**Step 2:** Check trigger conditions +- Open the trigger in GTM +- Reproduce the exact scenario step by step +- In GTM Preview, check Variables at the moment the action happened +- Do the variable values match your trigger conditions? + +**Step 3:** dataLayer issue (for Custom Event triggers) +- In GTM Preview → select the relevant event in left panel → Variables tab +- Scroll to find `event` — what's the value? +- If event name doesn't match trigger exactly: it won't fire (case-sensitive, exact match) + +**Step 4:** Timing issue +- If using "Page View" trigger and element doesn't exist yet: switch to "DOM Ready" or "Window Loaded" +- If SPA: route changes may not trigger "Page View" — use History Change instead + +--- + +### Issue: Parameters showing as (not set) or undefined in GA4 + +**Step 1:** Verify parameter is in the network request +- DevTools → Network → find GA4 collect request → Payload +- Search for the parameter name (e.g., `plan_name`) +- If not there: GTM variable isn't resolving correctly + +**Step 2:** Check the GTM variable +- GTM Preview → find the event → Variables tab +- Find the variable for this parameter (e.g., `DLV - plan_name`) +- What's its value? If `undefined`: the dataLayer push didn't include this key, or key name is wrong + +**Step 3:** Check dataLayer push in your app code +- DevTools → Console → type: `dataLayer.filter(e => e.event === 'your_event_name')` +- Inspect the object — is the parameter key present and spelled correctly? + +**Step 4:** Check GA4 custom dimension registration +- Some parameters require a registered custom dimension in GA4 to appear in reports +- GA4 → Admin → Custom Definitions → Custom Dimensions +- If parameter isn't registered here: it'll exist in raw data but won't show in Explore reports + +--- + +### Issue: Duplicate events (event fires 2x per action) + +**Find the duplicates:** +- GTM Preview → find the action → how many tags with the same name fired? +- DevTools → Network → filter by `collect` → count hits for the action + +**Common causes:** + +1. **Enhanced Measurement + manual GTM tag** + - e.g., Enhanced Measurement tracks outbound clicks, GTM also has an outbound click tag + - Fix: disable the Enhanced Measurement setting OR remove the GTM tag + +2. **Two GTM Configuration tags** + - Each sends its own hits + - Fix: delete one, keep one + +3. **SPA router fires pageview + History Change trigger also fires** + - Fix: disable Enhanced Measurement pageview, use only History Change tag + +4. **Event fires on multiple triggers that both match** + - Fix: make triggers more specific — add exclusion conditions + +--- + +### Issue: Sessions/users look wrong (too high or too low) + +**Too many sessions:** +- Multiple GA4 Configuration tags +- History Change trigger firing + Enhanced Measurement pageview on SPA +- Client ID not persisting (cookie being blocked or cleared) + +**Too few sessions / users:** +- Consent blocking analytics for non-consenting users (expected under strict consent mode) +- Bot filtering too aggressive +- GA4 tags firing on wrong pages only + +**Sessions reset unexpectedly (user shows as new on every page):** +- Cross-domain tracking not configured +- Cookie domain mismatch +- GTM cookie settings incorrect + +--- + +### Issue: Conversions not matching between GA4 and Google Ads + +**Check 1: Attribution window mismatch** +- GA4 default: 30-day last click +- Google Ads: check conversion action settings for window +- These legitimately produce different numbers + +**Check 2: Conversion event names** +- In Google Ads → Tools → Conversions → imported from GA4 +- Does the linked event name exactly match the GA4 event? + +**Check 3: Import is linked** +- Google Ads → Tools → Linked Accounts → Google Analytics 4 +- Is the correct GA4 property linked and synced? +- Sync can take 24-48 hours after changes + +**Check 4: Enhanced Conversions** +- If GA4 uses a user_id or email parameter, Enhanced Conversions can improve matching +- Google Ads → Conversions → Enhanced Conversions for Web → Enable + +--- + +## Debug Checklist Template + +Use this for any new tracking issue: + +``` +[ ] Confirmed exact event name and parameters expected +[ ] Verified app code is pushing to dataLayer (console: dataLayer) +[ ] GTM Preview: trigger fires at correct moment +[ ] GTM Preview: parameters resolve to correct values (not undefined) +[ ] Network: GA4 collect request appears with correct payload +[ ] GA4 DebugView: event appears within 30 seconds +[ ] GA4 DebugView: parameters present and correct +[ ] GA4 Reports: event appears (24-48h delay for standard reports) +[ ] Consent check: tested with analytics consent granted +[ ] Filter check: internal traffic filter not blocking test traffic +``` diff --git a/marketing-skill/analytics-tracking/references/event-taxonomy-guide.md b/marketing-skill/analytics-tracking/references/event-taxonomy-guide.md new file mode 100644 index 0000000..d6c03c6 --- /dev/null +++ b/marketing-skill/analytics-tracking/references/event-taxonomy-guide.md @@ -0,0 +1,203 @@ +# Event Taxonomy Guide + +Complete reference for naming conventions, event structure, and parameter standards. + +--- + +## Why Taxonomy Matters + +Analytics data is only as good as its naming consistency. A tracking system with `FormSubmit`, `form_submit`, `form-submitted`, and `formSubmitted` as four separate "events" is useless for aggregation. One naming standard, enforced from day one, avoids months of cleanup later. + +This guide is the reference for that standard. + +--- + +## Naming Convention: Full Specification + +### Format + +``` +[object]_[action] +``` + +**Object** = the thing being acted upon (noun) +**Action** = what happened (verb, past tense or gerund) + +### Casing & Characters + +| Rule | āœ… Correct | āŒ Wrong | +|------|-----------|---------| +| Lowercase only | `video_started` | `Video_Started`, `VIDEO_STARTED` | +| Underscores only | `form_submit` | `form-submit`, `formSubmit` | +| Noun before verb | `plan_selected` | `selected_plan` | +| Past tense or clear state | `checkout_completed` | `checkout_complete`, `checkoutDone` | +| Specific > generic | `trial_started` | `event_triggered` | +| Max 4 words | `onboarding_step_completed` | `user_completed_an_onboarding_step_in_the_flow` | + +### Action Vocabulary (Standard Verbs) + +Use these verbs consistently — don't invent synonyms: + +| Verb | Use for | +|------|---------| +| `_started` | Beginning of a multi-step process | +| `_completed` | Successful completion of a process | +| `_failed` | An attempt that errored out | +| `_submitted` | Form or data submission | +| `_viewed` | Passive view of a page, modal, or content | +| `_clicked` | Direct click on a specific element | +| `_selected` | Choosing from options (plan, variant, filter) | +| `_opened` | Modal, drawer, chat window opened | +| `_closed` | Modal, drawer, chat window closed | +| `_downloaded` | File download | +| `_activated` | Feature turned on for first time | +| `_upgraded` | Plan or feature upgrade | +| `_cancelled` | Intentional termination | +| `_dismissed` | User explicitly closed/ignored a prompt | +| `_searched` | Search query submitted | + +--- + +## Complete SaaS Event Catalog + +### Acquisition Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `ad_clicked` | `utm_source`, `utm_campaign` | `utm_content`, `utm_term` | +| `landing_page_viewed` | `page_location`, `utm_source` | `variant` (A/B) | +| `pricing_viewed` | `page_location` | `referrer_page` | +| `demo_requested` | `source` (page slug or section) | `plan_interest` | +| `content_downloaded` | `content_name`, `content_type` | `gated` (boolean) | + +### Acquisition → Registration + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `signup_started` | — | `plan_name`, `method` | +| `signup_completed` | `method` | `user_id`, `plan_name` | +| `email_verified` | — | `method` | +| `trial_started` | `plan_name` | `trial_length_days` | +| `invitation_accepted` | `inviter_user_id` | `plan_name` | + +### Onboarding Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `onboarding_started` | — | `onboarding_variant` | +| `onboarding_step_completed` | `step_name`, `step_number` | `time_spent_seconds` | +| `onboarding_completed` | `steps_total` | `time_to_complete_seconds` | +| `onboarding_skipped` | `step_name` | `step_number` | +| `feature_activated` | `feature_name` | `activation_method` | +| `integration_connected` | `integration_name` | `integration_type` | +| `team_member_invited` | — | `invite_method` | + +### Conversion Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `plan_selected` | `plan_name`, `billing_period` | `previous_plan` | +| `checkout_started` | `plan_name`, `value`, `currency` | `billing_period` | +| `checkout_completed` | `plan_name`, `value`, `currency`, `transaction_id` | `billing_period`, `coupon_code` | +| `checkout_failed` | `plan_name`, `error_reason` | `value`, `currency` | +| `upgrade_completed` | `from_plan`, `to_plan`, `value`, `currency` | `trigger` | +| `coupon_applied` | `coupon_code`, `discount_value` | `plan_name` | + +### Engagement Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `feature_used` | `feature_name` | `feature_area`, `usage_count` | +| `search_performed` | `search_term` | `results_count`, `search_area` | +| `filter_applied` | `filter_name`, `filter_value` | `result_count` | +| `export_completed` | `export_type`, `export_format` | `record_count` | +| `report_generated` | `report_name` | `date_range` | +| `notification_clicked` | `notification_type` | `notification_id` | + +### Retention Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `subscription_cancelled` | `cancel_reason` | `plan_name`, `save_offer_shown`, `save_offer_accepted` | +| `save_offer_accepted` | `offer_type` | `plan_name`, `discount_pct` | +| `subscription_paused` | `pause_duration_days` | `pause_reason` | +| `subscription_reactivated` | — | `plan_name`, `days_since_cancel` | +| `churn_risk_detected` | — | `risk_score`, `risk_signals` | + +### Support / Help Events + +| Event | Required Parameters | Optional Parameters | +|-------|-------------------|-------------------| +| `help_article_viewed` | `article_name` | `article_id`, `source` | +| `chat_opened` | — | `page_location`, `trigger` | +| `support_ticket_submitted` | `ticket_category` | `severity` | +| `error_encountered` | `error_type`, `error_message` | `page_location`, `feature_name` | + +--- + +## Custom Dimensions & Metrics + +GA4 limits: 50 custom dimensions (event-scoped), 25 user-scoped, 50 item-scoped. +Prioritize the ones that matter for segmentation. + +### Recommended User-Scoped Dimensions + +| Dimension Name | Parameter | Example Values | +|---------------|-----------|---------------| +| User ID | `user_id` | `usr_abc123` | +| Plan Name | `plan_name` | `starter`, `professional`, `enterprise` | +| Billing Period | `billing_period` | `monthly`, `annual` | +| Account Created Date | `account_created_date` | `2024-03-15` | +| Onboarding Completed | `onboarding_completed` | `true`, `false` | +| Company Size | `company_size` | `1-10`, `11-50`, `51-200` | + +### Recommended Event-Scoped Dimensions + +| Dimension Name | Parameter | Used In | +|---------------|-----------|---------| +| Cancel Reason | `cancel_reason` | `subscription_cancelled` | +| Feature Name | `feature_name` | `feature_used`, `feature_activated` | +| Content Name | `content_name` | `content_downloaded` | +| Signup Method | `method` | `signup_completed` | +| Error Type | `error_type` | `error_encountered` | + +--- + +## Taxonomy Governance + +### The Tracking Plan Document + +Maintain a single tracking plan document (Google Sheet or Notion table) with: + +| Column | Values | +|--------|--------| +| Event Name | e.g., `checkout_completed` | +| Trigger | "User completes Stripe checkout" | +| Parameters | `{value, currency, plan_name, transaction_id}` | +| Implemented In | GTM / App code / server | +| Status | Draft / Implemented / Verified | +| Owner | Engineering / Marketing / Product | + +### Change Protocol + +1. New events → add to tracking plan first, get sign-off before implementing +2. Rename events → use a deprecation period (keep old + add new for 30 days, then remove old) +3. Remove events → archive in tracking plan, don't delete — historical data reference +4. Add parameters → non-breaking, implement immediately and update tracking plan +5. Remove parameters → treat as rename (deprecation period) + +### Versioning + +Include `schema_version` as a parameter on critical events if your taxonomy evolves rapidly: + +```javascript +window.dataLayer.push({ + event: 'checkout_completed', + schema_version: 'v2', + value: 99, + currency: 'USD', + // ... +}); +``` + +This allows filtering old vs. new schema during migrations. diff --git a/marketing-skill/analytics-tracking/references/gtm-patterns.md b/marketing-skill/analytics-tracking/references/gtm-patterns.md new file mode 100644 index 0000000..bdbafa4 --- /dev/null +++ b/marketing-skill/analytics-tracking/references/gtm-patterns.md @@ -0,0 +1,298 @@ +# GTM Patterns for SaaS + +Common Google Tag Manager configurations for SaaS applications. + +--- + +## Container Architecture + +### Naming Convention + +Use consistent naming or GTM becomes a black box within 6 months. + +``` +Tags: [Platform] - [Event Name] e.g., "GA4 - signup_completed" +Triggers: [Type] - [Description] e.g., "DL Event - signup_completed" +Variables: [Type] - [Parameter Name] e.g., "DLV - plan_name" +``` + +### Required Variables (Create These First) + +| Variable Name | Type | Value | +|--------------|------|-------| +| `CON - GA4 Measurement ID` | Constant | `G-XXXXXXXXXX` | +| `CON - Environment` | Constant | `production` | +| `JS - Page Path` | Custom JavaScript | `function() { return window.location.pathname; }` | +| `JS - User ID` | Custom JavaScript | `function() { return window.currentUserId || undefined; }` | + +### GA4 Configuration Tag + +**One tag, fires on All Pages:** + +``` +Tag Type: Google Analytics: GA4 Configuration +Measurement ID: {{CON - GA4 Measurement ID}} +Fields to Set: + - user_id: {{JS - User ID}} +Trigger: All Pages +``` + +--- + +## Pattern Library + +### Pattern 1: Data Layer Push Event + +The most reliable pattern. Your app pushes structured data; GTM listens. + +**In your application code:** +```javascript +// Call this function on any trackable event +function trackEvent(eventName, parameters) { + window.dataLayer = window.dataLayer || []; + window.dataLayer.push({ + event: eventName, + ...parameters + }); +} + +// Example: after successful signup +trackEvent('signup_completed', { + signup_method: 'email', + user_id: newUser.id, + plan_name: 'trial' +}); +``` + +**In GTM:** + +1. Create Data Layer Variables for each parameter: + - `DLV - signup_method` → Data Layer Variable → `signup_method` + - `DLV - user_id` → Data Layer Variable → `user_id` + - `DLV - plan_name` → Data Layer Variable → `plan_name` + +2. Create Trigger: + - Type: Custom Event + - Event Name: `signup_completed` + - Name: `DL Event - signup_completed` + +3. Create Tag: + - Type: Google Analytics: GA4 Event + - Configuration Tag: GA4 Config tag + - Event Name: `signup_completed` + - Event Parameters: + - `method`: `{{DLV - signup_method}}` + - `user_id`: `{{DLV - user_id}}` + - `plan_name`: `{{DLV - plan_name}}` + - Trigger: `DL Event - signup_completed` + +--- + +### Pattern 2: Click Event on Specific Element + +Use when you can't modify app code and need to track a specific CTA. + +**GTM Setup:** + +1. Enable `Click - All Elements` built-in variables (if not enabled): + - GTM → Variables → Configure → Enable: Click Element, Click ID, Click Classes, Click Text + +2. Create Trigger: + - Type: Click - All Elements + - Fire On: Some Clicks + - Conditions: + - Click Element matches CSS selector: `[data-track="demo-cta"]` + OR + - Click Text equals "Request a Demo" + - Name: `Click - Demo CTA` + +3. Create Tag: + - Type: GA4 Event + - Event Name: `demo_requested` + - Event Parameters: + - `page_location`: `{{Page URL}}` + - `click_text`: `{{Click Text}}` + - Trigger: `Click - Demo CTA` + +**Best practice:** Add `data-track` attributes to important elements in your HTML rather than relying on brittle CSS selectors or text matching. + +```html + +``` + +--- + +### Pattern 3: Form Submission Tracking + +Two approaches depending on whether the form submits via JavaScript or full page reload. + +**For JavaScript-handled forms (AJAX/fetch):** +- Use Pattern 1 (dataLayer push) after successful form submission callback + +**For traditional form submit:** + +1. Create Trigger: + - Type: Form Submission + - Check Validation: āœ… (only fires if form passes HTML5 validation) + - Enable History Change: āœ… (for SPAs) + - Fire On: Some Forms + - Conditions: Form ID equals `contact-form` OR Form Classes contains `js-track-form` + - Name: `Form Submit - Contact` + +2. Create Tag: + - Type: GA4 Event + - Event Name: `form_submitted` + - Parameters: + - `form_name`: `contact` + - `page_location`: `{{Page URL}}` + - Trigger: `Form Submit - Contact` + +--- + +### Pattern 4: SPA Page View Tracking + +Single-page apps often don't trigger standard page view events on route changes. + +**Approach A: History Change trigger (simplest)** + +1. Create Trigger: + - Type: History Change + - Name: `History Change - Route` + +2. Create Tag: + - Type: GA4 Event + - Event Name: `page_view` + - Parameters: + - `page_location`: `{{Page URL}}` + - `page_title`: `{{Page Title}}` + - Trigger: `History Change - Route` + +**Important:** Disable the default pageview in your GA4 Configuration tag if using this, or you'll get duplicates on initial load. + +**Approach B: dataLayer push from router (more reliable)** + +```javascript +// In your router's navigation handler: +router.afterEach((to, from) => { + window.dataLayer.push({ + event: 'page_view', + page_path: to.path, + page_title: document.title + }); +}); +``` + +--- + +### Pattern 5: Scroll Depth Tracking + +For content engagement measurement: + +**Option A: Use GA4 Enhanced Measurement (90% depth only)** +- Enable in GA4 → Data Streams → Enhanced Measurement → Scrolls +- Fires when user scrolls 90% down the page +- No GTM configuration needed + +**Option B: Custom milestones via GTM** + +1. Create Trigger for each depth: + - Type: Scroll Depth + - Vertical Scroll Depths: 25, 50, 75, 100 (percent) + - Enable for: Some Pages → Page Path contains `/blog/` + - Name: `Scroll Depth - Blog` + +2. Create Tag: + - Type: GA4 Event + - Event Name: `content_scrolled` + - Parameters: + - `scroll_depth_pct`: `{{Scroll Depth Threshold}}` + - `page_location`: `{{Page URL}}` + - Trigger: `Scroll Depth - Blog` + +--- + +### Pattern 6: Consent Mode Integration + +For GDPR compliance — connect your CMP to GTM. + +**Basic Consent Mode (blocks all when declined):** + +```javascript +// In your CMP callback: +window.dataLayer.push({ + event: 'cookie_consent_update', + ad_storage: 'denied', // or 'granted' + analytics_storage: 'denied', // or 'granted' + functionality_storage: 'denied', + personalization_storage: 'denied', + security_storage: 'granted' // always granted +}); +``` + +**Advanced Consent Mode (modeled data for declined users):** + +Add to `` BEFORE GTM loads: +```javascript +window.dataLayer = window.dataLayer || []; +function gtag(){dataLayer.push(arguments);} + +// Default all to denied +gtag('consent', 'default', { + ad_storage: 'denied', + analytics_storage: 'denied', + wait_for_update: 500 // ms to wait for CMP to initialize +}); +``` + +Then update when user consents: +```javascript +gtag('consent', 'update', { + analytics_storage: 'granted' +}); +``` + +--- + +## GTM Version Control + +### Version Naming Convention + +``` +v1.0 - Initial setup: GA4 + core events +v1.1 - Add: checkout tracking +v1.2 - Fix: duplicate pageview on SPA +v2.0 - Overhaul: new event taxonomy + Meta Pixel +``` + +### Publishing Protocol + +1. Test in GTM Preview mode — verify events fire correctly +2. Test in GA4 DebugView — confirm parameters are captured +3. Test with GTM's "What changed?" diff view +4. Add version notes (what changed + why) +5. Publish to production +6. Verify in GA4 Realtime view post-publish + +### Environments + +Create a staging environment in GTM (Admin → Environments): +- Development: test changes without affecting production +- Staging: validate before publish +- Production: live + +Share staging GTM snippet with your dev team so they test against the same container. + +--- + +## Common GTM Mistakes + +| Mistake | Symptom | Fix | +|---------|---------|-----| +| Tag fires on "All Pages" when it should be scoped | Inflated event counts | Add page conditions to trigger | +| Data Layer Variable path is wrong | Parameter shows as `undefined` | Use GTM Preview to inspect dataLayer structure | +| GA4 Configuration tag fires multiple times | Duplicate sessions/users | Check all triggers — should be one trigger, "All Pages" | +| Enhanced Measurement conflicts with custom tags | Duplicate outbound click events | Disable conflicting Enhanced Measurement settings | +| Trigger fires before DOM ready | Element not found errors | Change trigger type from "Page View" to "DOM Ready" or "Window Loaded" | +| Form trigger doesn't fire | Form uses AJAX or custom submit | Switch to dataLayer push after submit callback | diff --git a/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py b/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py new file mode 100644 index 0000000..7bb6994 --- /dev/null +++ b/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py @@ -0,0 +1,371 @@ +#!/usr/bin/env python3 +"""Tracking plan generator — produces event taxonomy, GTM config, and GA4 dimension recommendations.""" + +import json +import sys +from collections import defaultdict + +SAMPLE_INPUT = { + "business_type": "saas", + "key_pages": [ + {"name": "Homepage", "path": "/"}, + {"name": "Pricing", "path": "/pricing"}, + {"name": "Signup", "path": "/signup"}, + {"name": "Dashboard", "path": "/app/dashboard"}, + {"name": "Onboarding", "path": "/app/onboarding"} + ], + "conversion_actions": [ + {"name": "Signup", "type": "registration", "value": 0}, + {"name": "Trial Start", "type": "trial", "value": 0}, + {"name": "Subscription Purchase", "type": "purchase", "value": 99}, + {"name": "Demo Request", "type": "lead", "value": 0} + ], + "paid_channels": ["google_ads", "meta"], + "consent_required": True +} + + +EVENT_TEMPLATES = { + "saas": { + "acquisition": [ + { + "event": "pricing_viewed", + "trigger": "User navigates to /pricing", + "parameters": ["page_location", "utm_source", "referrer_page"], + "priority": "high" + }, + { + "event": "demo_requested", + "trigger": "User submits demo request form", + "parameters": ["source", "page_location", "form_name"], + "priority": "high", + "is_conversion": True + }, + { + "event": "content_downloaded", + "trigger": "User downloads gated content", + "parameters": ["content_name", "content_type", "gated"], + "priority": "medium" + } + ], + "registration": [ + { + "event": "signup_started", + "trigger": "User clicks primary signup CTA", + "parameters": ["page_location", "cta_text", "plan_name"], + "priority": "high" + }, + { + "event": "signup_completed", + "trigger": "User account successfully created", + "parameters": ["method", "user_id", "plan_name"], + "priority": "critical", + "is_conversion": True + }, + { + "event": "trial_started", + "trigger": "Free trial begins", + "parameters": ["plan_name", "trial_length_days", "user_id"], + "priority": "critical", + "is_conversion": True + } + ], + "onboarding": [ + { + "event": "onboarding_started", + "trigger": "User enters onboarding flow", + "parameters": ["user_id", "onboarding_variant"], + "priority": "high" + }, + { + "event": "onboarding_step_completed", + "trigger": "User completes each onboarding step", + "parameters": ["step_name", "step_number", "user_id", "time_spent_seconds"], + "priority": "high" + }, + { + "event": "onboarding_completed", + "trigger": "User completes full onboarding", + "parameters": ["steps_total", "user_id", "time_to_complete_seconds"], + "priority": "high" + }, + { + "event": "feature_activated", + "trigger": "User activates a key feature for first time", + "parameters": ["feature_name", "user_id", "activation_method"], + "priority": "medium" + } + ], + "conversion": [ + { + "event": "plan_selected", + "trigger": "User clicks on a pricing plan", + "parameters": ["plan_name", "billing_period", "value"], + "priority": "critical" + }, + { + "event": "checkout_started", + "trigger": "User enters checkout flow", + "parameters": ["plan_name", "value", "currency", "billing_period"], + "priority": "critical" + }, + { + "event": "checkout_completed", + "trigger": "Payment successfully processed", + "parameters": ["plan_name", "value", "currency", "transaction_id", "billing_period"], + "priority": "critical", + "is_conversion": True + } + ], + "retention": [ + { + "event": "subscription_cancelled", + "trigger": "User confirms cancellation", + "parameters": ["cancel_reason", "plan_name", "save_offer_shown", "save_offer_accepted"], + "priority": "high" + }, + { + "event": "subscription_reactivated", + "trigger": "Cancelled user reactivates", + "parameters": ["plan_name", "days_since_cancel"], + "priority": "high" + } + ] + }, + "ecommerce": { + "acquisition": [ + { + "event": "product_viewed", + "trigger": "User views a product page", + "parameters": ["item_id", "item_name", "item_category", "value"], + "priority": "high" + }, + { + "event": "search_performed", + "trigger": "User submits a search query", + "parameters": ["search_term", "results_count"], + "priority": "medium" + } + ], + "conversion": [ + { + "event": "add_to_cart", + "trigger": "User adds item to cart", + "parameters": ["item_id", "item_name", "value", "currency", "quantity"], + "priority": "critical" + }, + { + "event": "checkout_started", + "trigger": "User begins checkout", + "parameters": ["value", "currency", "num_items"], + "priority": "critical" + }, + { + "event": "checkout_completed", + "trigger": "Order placed successfully", + "parameters": ["transaction_id", "value", "currency", "tax", "shipping"], + "priority": "critical", + "is_conversion": True + } + ] + } +} + +CUSTOM_DIMENSIONS = { + "user_scoped": [ + {"name": "User ID", "parameter": "user_id", "description": "Internal user identifier"}, + {"name": "Plan Name", "parameter": "plan_name", "description": "Current subscription plan"}, + {"name": "Billing Period", "parameter": "billing_period", "description": "Monthly or annual"}, + {"name": "Signup Method", "parameter": "signup_method", "description": "Email, Google, SSO"}, + {"name": "Onboarding Status", "parameter": "onboarding_completed", "description": "Boolean: completed onboarding?"} + ], + "event_scoped": [ + {"name": "Cancel Reason", "parameter": "cancel_reason", "description": "Exit survey selection"}, + {"name": "Feature Name", "parameter": "feature_name", "description": "Feature being used/activated"}, + {"name": "Form Name", "parameter": "form_name", "description": "Which form was submitted"}, + {"name": "Content Name", "parameter": "content_name", "description": "Downloaded/viewed content"}, + {"name": "Error Type", "parameter": "error_type", "description": "Type of error encountered"} + ] +} + + +def generate_tracking_plan(inputs): + biz_type = inputs.get("business_type", "saas") + templates = EVENT_TEMPLATES.get(biz_type, EVENT_TEMPLATES["saas"]) + paid = inputs.get("paid_channels", []) + consent = inputs.get("consent_required", False) + conversions = inputs.get("conversion_actions", []) + + # Build event taxonomy + all_events = [] + for category, events in templates.items(): + for ev in events: + all_events.append({**ev, "category": category}) + + # Add conversion-specific events from input + conversion_events = [] + for ca in conversions: + if ca["type"] == "purchase": + for ev in all_events: + if ev["event"] == "checkout_completed": + ev["value_hint"] = ca["value"] + conversion_events.append("checkout_completed") + elif ca["type"] == "registration": + conversion_events.append("signup_completed") + elif ca["type"] == "lead": + conversion_events.append("demo_requested") + elif ca["type"] == "trial": + conversion_events.append("trial_started") + + # GTM tag configuration + gtm_tags = [] + for ev in all_events: + gtm_tags.append({ + "tag_name": f"GA4 - {ev['event']}", + "tag_type": "ga4_event", + "event_name": ev["event"], + "trigger": f"DL Event - {ev['event']}", + "parameters": ev["parameters"], + "priority": ev.get("priority", "medium") + }) + + # Add platform-specific tags + if "google_ads" in paid: + for ev in all_events: + if ev.get("is_conversion"): + gtm_tags.append({ + "tag_name": f"Google Ads - {ev['event']}", + "tag_type": "google_ads_conversion", + "event_name": ev["event"], + "trigger": f"DL Event - {ev['event']}", + "note": "Import from GA4 conversions (preferred) or configure conversion ID" + }) + + if "meta" in paid: + gtm_tags.append({ + "tag_name": "Meta Pixel - Base", + "tag_type": "html_tag", + "trigger": "All Pages", + "note": "Meta base pixel — fires on all pages. Add Standard Events separately." + }) + + # Consent configuration + consent_config = None + if consent: + consent_config = { + "mode": "advanced", + "defaults": { + "analytics_storage": "denied", + "ad_storage": "denied", + "functionality_storage": "denied" + }, + "update_trigger": "cookie_consent_update", + "note": "Implement before GTM loads. Requires CMP integration (Cookiebot, OneTrust, etc.)." + } + + return { + "event_taxonomy": [ + { + "category": ev["category"], + "event": ev["event"], + "trigger": ev["trigger"], + "parameters": ev["parameters"], + "priority": ev.get("priority", "medium"), + "is_conversion": ev.get("is_conversion", False) + } + for ev in all_events + ], + "conversion_events": list(set(conversion_events)), + "gtm_configuration": { + "tags": gtm_tags, + "variable_count": len(set(p for ev in all_events for p in ev["parameters"])), + "trigger_count": len(all_events) + }, + "ga4_custom_dimensions": CUSTOM_DIMENSIONS, + "consent_mode": consent_config, + "implementation_order": [ + "1. Register custom dimensions in GA4 (Admin > Custom Definitions)", + "2. Set up GTM container structure (variables first, then triggers, then tags)", + "3. Implement dataLayer pushes in application code", + "4. Test each event in GTM Preview + GA4 DebugView", + "5. Mark conversion events in GA4 (Admin > Conversions)", + "6. Link GA4 to Google Ads if running paid search", + "7. Enable internal traffic filter", + "8. Implement consent mode if required" + ] + } + + +def print_report(result, inputs): + print("\n" + "="*65) + print(" TRACKING PLAN GENERATOR") + print("="*65) + + print(f"\nšŸ“‹ BUSINESS TYPE: {inputs.get('business_type', 'saas').upper()}") + + events = result["event_taxonomy"] + by_priority = defaultdict(list) + for ev in events: + by_priority[ev["priority"]].append(ev) + + print(f"\nšŸ“Š EVENT TAXONOMY ({len(events)} events)") + for priority in ["critical", "high", "medium", "low"]: + evs = by_priority.get(priority, []) + if evs: + marker = "šŸ”“" if priority == "critical" else "🟔" if priority == "high" else "⚪" + print(f"\n {marker} {priority.upper()} ({len(evs)} events)") + for ev in evs: + conv = " ← CONVERSION" if ev["is_conversion"] else "" + print(f" {ev['event']}{conv}") + print(f" Params: {', '.join(ev['parameters'][:4])}" + + (f"... +{len(ev['parameters'])-4} more" if len(ev['parameters']) > 4 else "")) + + conversions = result["conversion_events"] + print(f"\nšŸŽÆ CONVERSION EVENTS ({len(conversions)})") + for ev in conversions: + print(f" • {ev}") + + dims = result["ga4_custom_dimensions"] + print(f"\nšŸ“ CUSTOM DIMENSIONS") + print(f" User-scoped ({len(dims['user_scoped'])}): " + + ", ".join(d["parameter"] for d in dims["user_scoped"])) + print(f" Event-scoped ({len(dims['event_scoped'])}): " + + ", ".join(d["parameter"] for d in dims["event_scoped"])) + + gtm = result["gtm_configuration"] + print(f"\nšŸ·ļø GTM CONFIGURATION") + print(f" Tags to create: {len(gtm['tags'])}") + print(f" Triggers to create: {gtm['trigger_count']}") + print(f" Variables to create:{gtm['variable_count']}") + + if result["consent_mode"]: + print(f"\nšŸ”’ CONSENT MODE: Advanced (required)") + print(f" Default state: analytics_storage=denied, ad_storage=denied") + + print(f"\nšŸ“‹ IMPLEMENTATION ORDER") + for step in result["implementation_order"]: + print(f" {step}") + + print("\n" + "="*65) + print(" Run with --json flag to output full config as JSON") + print("="*65 + "\n") + + +def main(): + if len(sys.argv) > 1 and sys.argv[1] != "--json": + with open(sys.argv[1]) as f: + inputs = json.load(f) + else: + if "--json" not in sys.argv: + print("No input file provided. Running with sample data...\n") + inputs = SAMPLE_INPUT + + result = generate_tracking_plan(inputs) + print_report(result, inputs) + + if "--json" in sys.argv: + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/app-store-optimization/SKILL.md b/marketing-skill/app-store-optimization/SKILL.md index 4eaa765..678f3a9 100644 --- a/marketing-skill/app-store-optimization/SKILL.md +++ b/marketing-skill/app-store-optimization/SKILL.md @@ -493,3 +493,25 @@ Trusted by 500,000+ professionals. | [content-creator](../content-creator/) | App description copywriting | | [marketing-demand-acquisition](../marketing-demand-acquisition/) | Launch promotion campaigns | | [marketing-strategy-pmm](../marketing-strategy-pmm/) | Go-to-market planning | + +## Proactive Triggers + +- **No keyword optimization in title** → App title is the #1 ranking factor. Include top keyword. +- **Screenshots don't show value** → Screenshots should tell a story, not show UI. +- **No ratings strategy** → Below 4.0 stars kills conversion. Implement in-app rating prompts. +- **Description keyword-stuffed** → Natural language with keywords beats keyword stuffing. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "ASO audit" | Full app store listing audit with prioritized fixes | +| "Keyword research" | Keyword list with search volume and difficulty scores | +| "Optimize my listing" | Rewritten title, subtitle, description, keyword field | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. diff --git a/marketing-skill/brand-guidelines/SKILL.md b/marketing-skill/brand-guidelines/SKILL.md new file mode 100644 index 0000000..8ca605e --- /dev/null +++ b/marketing-skill/brand-guidelines/SKILL.md @@ -0,0 +1,351 @@ +--- +name: brand-guidelines +description: "When the user wants to apply, document, or enforce brand guidelines for any product or company. Also use when the user mentions 'brand guidelines,' 'brand colors,' 'typography,' 'logo usage,' 'brand voice,' 'visual identity,' 'tone of voice,' 'brand standards,' 'style guide,' 'brand consistency,' or 'company design standards.' Covers color systems, typography, logo rules, imagery guidelines, and tone matrix for any brand — including Anthropic's official identity." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Brand Guidelines + +You are an expert in brand identity and visual design standards. Your goal is to help teams apply brand guidelines consistently across all marketing materials, products, and communications — whether working with an established brand system or building one from scratch. + +## How to Use This Skill + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before applying brand standards. Use that context to tailor recommendations to the specific brand. + +When helping users: +1. Identify whether they need to *apply* existing guidelines or *create* new ones +2. For Anthropic artifacts, use the Anthropic identity system below +3. For other brands, use the framework sections to assess and document their system +4. Always check for consistency before creativity + +--- + +## Anthropic Brand Identity + +### Overview + +Anthropic's brand identity is clean, precise, and intellectually grounded. It communicates trustworthiness and technical sophistication without feeling cold or corporate. + +### Color System + +**Primary Palette:** + +| Name | Hex | RGB | Use | +|------|-----|-----|-----| +| Dark | `#141413` | 20, 20, 19 | Primary text, dark backgrounds | +| Light | `#faf9f5` | 250, 249, 245 | Light backgrounds, text on dark | +| Mid Gray | `#b0aea5` | 176, 174, 165 | Secondary elements, dividers | +| Light Gray | `#e8e6dc` | 232, 230, 220 | Subtle backgrounds, borders | + +**Accent Palette:** + +| Name | Hex | RGB | Use | +|------|-----|-----|-----| +| Orange | `#d97757` | 217, 119, 87 | Primary accent, CTAs | +| Blue | `#6a9bcc` | 106, 155, 204 | Secondary accent, links | +| Green | `#788c5d` | 120, 140, 93 | Tertiary accent, success states | + +**Color Application Rules:** +- Never use accent colors as large background fills — use them for emphasis only +- Dark on Light or Light on Dark — avoid mixing Dark on Mid Gray for body text +- Accent colors cycle: Orange (primary CTA) → Blue (supporting) → Green (tertiary) +- When in doubt, default to Dark + Light with one accent + +### Typography + +**Type Scale:** + +| Role | Font | Fallback | Weight | Size Range | +|------|------|----------|--------|------------| +| Display / H1 | Poppins | Arial | 600–700 | 32pt+ | +| Headings H2–H4 | Poppins | Arial | 500–600 | 20–31pt | +| Body | Lora | Georgia | 400 | 14–18pt | +| Caption / Label | Poppins | Arial | 400–500 | 10–13pt | +| Code / Mono | Courier New | monospace | 400 | 12–14pt | + +**Typography Rules:** +- Never set body copy in Poppins — it's a display/heading font +- Minimum body size: 14pt for print, 16px for web +- Line height: 1.5–1.6 for body, 1.1–1.2 for headings +- Letter spacing: -0.5px to -1px for large headings; 0 for body + +**Font Installation:** +- Poppins: Available on Google Fonts (`fonts.google.com/specimen/Poppins`) +- Lora: Available on Google Fonts (`fonts.google.com/specimen/Lora`) +- Both should be pre-installed in design environments for best results + +### Logo Usage + +**Clear Space:** +Maintain minimum clear space equal to the cap-height of the wordmark on all sides. No other elements should intrude on this zone. + +**Minimum Size:** +- Digital: 120px wide minimum +- Print: 25mm wide minimum + +**Approved Variations:** +- Dark logo on Light background (primary) +- Light logo on Dark background (inverted) +- Single-color Dark on any light neutral +- Single-color Light on any dark surface + +**Prohibited Uses:** +- Do not stretch or distort the logo +- Do not apply drop shadows, gradients, or outlines +- Do not place on busy photographic backgrounds without a color block +- Do not use accent colors as the logo fill +- Do not rotate the logo + +### Imagery Guidelines + +**Photography Style:** +- Clean, well-lit, minimal post-processing +- Subjects: people at work, abstract technical concepts, precise objects +- Avoid: stock photo clichĆ©s, overly emotive poses, heavy filters +- Color treatment: neutral tones preferred; desaturate if needed to match palette + +**Illustration Style:** +- Geometric, precise line work +- Limited palette: use brand colors only +- Avoid: cartoonish characters, heavy gradients, 3D renders + +**Iconography:** +- Stroke-based, consistent weight (2px at 24px size) +- Rounded caps preferred; sharp corners acceptable for technical contexts +- Use Mid Gray or Dark; accent color only for active/selected states + +--- + +## Universal Brand Guidelines Framework + +Use this section when building or auditing guidelines for *any* brand (not Anthropic-specific). + +### 1. Brand Foundation + +Before any visual decisions, the brand foundation must exist: + +| Element | Definition | +|---------|-----------| +| **Mission** | Why the company exists beyond making money | +| **Vision** | The future state the brand is working toward | +| **Values** | 3–5 core principles that drive decisions | +| **Positioning** | What you are, for whom, against what alternative | +| **Personality** | How the brand behaves — adjectives that guide tone | + +A visual identity without a foundation is decoration. The foundation drives every downstream decision. + +--- + +### 2. Color System + +#### Primary Palette (2–3 colors) +- One dominant neutral (background or text) +- One strong brand color (most recognition, hero elements) +- One supporting color (secondary backgrounds, dividers) + +#### Accent Palette (2–4 colors) +- Used sparingly for emphasis, CTAs, states +- Must pass WCAG AA contrast against backgrounds they appear on + +#### Color Rules to Document: +- Which color for CTAs vs. informational links +- Background color combinations that are approved +- Colors that should never appear together +- Dark mode equivalents + +#### Accessibility Requirements: +- Normal text (< 18pt): minimum 4.5:1 contrast ratio (WCAG AA) +- Large text (≄ 18pt): minimum 3:1 contrast ratio +- UI components: minimum 3:1 against adjacent colors +- Test: `webaim.org/resources/contrastchecker` + +--- + +### 3. Typography System + +#### Type Roles to Define: + +| Role | Font | Size Range | Weight | Line Height | +|------|------|-----------|--------|-------------| +| Display | — | 40pt+ | Bold | 1.1 | +| H1 | — | 28–40pt | SemiBold | 1.15 | +| H2 | — | 22–28pt | SemiBold | 1.2 | +| H3 | — | 18–22pt | Medium | 1.25 | +| Body | — | 15–18pt | Regular | 1.5–1.6 | +| Small / Caption | — | 12–14pt | Regular | 1.4 | +| Label / UI | — | 11–13pt | Medium | 1.2 | + +#### Font Selection Criteria: +- Max 2 typeface families (one serif or slab, one sans-serif) +- Both must be available in all required weights +- Must render well at small sizes on screen +- Licensing must cover all intended uses (web, print, app) + +--- + +### 4. Logo System + +#### Variations Required: +- **Primary**: full color on white/light +- **Inverted**: light version on dark backgrounds +- **Monochrome**: single color for single-color applications +- **Mark only**: icon/symbol without wordmark (for small sizes) +- **Horizontal + Stacked**: where layout demands both + +#### Usage Rules to Document: +- Minimum size (px for digital, mm for print) +- Clear space formula +- Approved background colors +- Prohibited modifications (distortion, recoloring, shadows) +- Co-branding rules (partner logo sizing, spacing) + +--- + +### 5. Imagery Guidelines + +#### Photography Criteria: +| Dimension | Guideline | +|-----------|-----------| +| **People** | Authentic, diverse, action-oriented — not posed stock | +| **Lighting** | Clean and directional; avoid heavy shadows or blown highlights | +| **Color treatment** | Align to brand palette; desaturate or tint if necessary | +| **Subjects** | Match brand values — avoid anything that conflicts with positioning | + +#### Illustration Style: +- Define: flat vs. 3D, line vs. filled, abstract vs. representational +- Set a palette limit: brand colors only, or approved expanded set +- Define stroke weight and corner radius standards + +#### Do / Don't Matrix (customize per brand): + +| āœ… Do | āŒ Don't | +|-------|---------| +| Show real customers and use cases | Use generic multicultural stock | +| Use natural lighting | Use heavy vignettes or HDR | +| Keep backgrounds clean | Place subjects on clashing colors | +| Match brand palette tones | Use heavy Instagram-style filters | + +--- + +### 6. Tone of Voice & Tone Matrix + +Brand voice is consistent; tone adapts to context. + +#### Voice Attributes (define 4–6): + +| Attribute | What It Means | What It's Not | +|-----------|---------------|---------------| +| Example: **Direct** | Say what you mean; no filler | Blunt or dismissive | +| Example: **Curious** | Ask questions, show genuine interest | Condescending or know-it-all | +| Example: **Precise** | Specific language, no vague claims | Technical jargon that excludes | +| Example: **Warm** | Human and approachable | Overly casual or unprofessional | + +#### Tone Matrix by Context: + +| Context | Tone Dial | Example Shift | +|---------|-----------|--------------| +| Error messages | Calm, helpful, matter-of-fact | Less formal than marketing | +| Marketing headlines | Confident, energetic | More punchy than support | +| Legal / compliance | Precise, neutral | Less personality | +| Support / help content | Patient, empathetic | More warmth than ads | +| Social media | Conversational, light | More informal than web | +| Executive communications | Authoritative, measured | More formal than blog | + +#### Words to Use / Avoid (document per brand): + +| āœ… Use | āŒ Avoid | +|-------|---------| +| "We" (inclusive) | "Leverage" (jargon) | +| Specific numbers | "Best-in-class" (vague) | +| Active voice | Passive constructions | +| Short sentences | Run-on complexity | + +--- + +### 7. Application Examples + +#### Digital +- **Web**: Primary palette for backgrounds; accent for CTAs; Poppins/brand heading font for H1–H3 +- **Email**: Inline styles only; web-safe font fallbacks always specified; logo as linked image +- **Social**: Platform-specific safe zones; brand colors dominant; minimal text on images + +#### Print +- Always use CMYK values for print production (never RGB or hex) +- Bleed: 3mm on all sides; keep critical content 5mm from trim +- Proof against Pantone reference before bulk print runs + +#### Presentations +- Cover slide: brand dark + brand light with single accent +- Body slides: white backgrounds with brand accent headers +- No custom fonts in share files — embed or substitute + +--- + +## Quick Audit Checklist + +Use this to rapidly assess brand consistency across any asset: + +- [ ] Colors match approved palette (no off-brand variations) +- [ ] Fonts are correct typeface and weight +- [ ] Logo has proper clear space and is an approved variation +- [ ] Body text meets minimum size and contrast requirements +- [ ] Imagery style matches brand guidelines +- [ ] Tone matches brand voice attributes +- [ ] No prohibited uses present (gradients on logo, wrong accent color, etc.) +- [ ] Co-branding (if any) follows partner logo rules + +--- + +## Task-Specific Questions + +1. Are you applying existing guidelines or creating new ones? +2. What's the output format? (Digital, print, presentation, social) +3. Do you have existing brand assets? (Logo files, color codes, fonts) +4. Is there a brand foundation document? (Mission, values, positioning) +5. What's the specific inconsistency or gap you're trying to fix? + +--- + +## Proactive Triggers + +Proactively apply brand guidelines when: + +1. **Any visual asset requested** — Before creating any poster, slide, email, or social graphic, check if brand guidelines exist; if not, offer to establish a minimal system first. +2. **Copy review touches tone** — When reviewing copy, cross-check against voice attributes and tone matrix, not just grammar. +3. **New channel launch** — When a new marketing channel (TikTok, newsletter, podcast) is being set up, offer to apply the brand guidelines to that channel's specific format requirements. +4. **Design feedback session** — When a user shares a design for feedback, run through the quick audit checklist before giving subjective opinions. +5. **Partner or co-branded material** — Any co-branding situation should immediately trigger a review of logo clear space, sizing ratios, and color dominance rules. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Brand Audit Report | Markdown doc | Asset-by-asset compliance check against all brand dimensions | +| Color System Reference | Table | Full palette with hex, RGB, CMYK, Pantone, and usage rules | +| Tone Matrix | Table | Voice attributes Ɨ context combinations with example phrases | +| Typography Scale | Table | All type roles with font, size, weight, and line-height specifications | +| Brand Guidelines Mini-Doc | Markdown doc | Condensed brand guide covering all 7 dimensions, ready to share with contractors | + +--- + +## Communication + +Brand consistency is not a design preference — it's a trust signal. Every deviation from guidelines erodes recognition. When auditing or creating brand materials, be specific: name the exact color code, font weight, and pixel measurement rather than giving subjective feedback. Reference `marketing-context` to ensure brand voice recommendations align with the ICP and product positioning. Quality bar: brand outputs should be specific enough that a contractor who has never worked with the brand could produce on-brand work from the artifact alone. + +--- + +## Related Skills + +- **marketing-context** — USE as the brand foundation layer; brand voice and visual decisions must align with ICP, positioning, and messaging; always load first. +- **copywriting** — USE when brand voice guidelines need to be applied to specific page or campaign copy; NOT as a substitute for defining voice attributes. +- **content-humanizer** — USE when existing content needs to be rewritten to match brand tone without losing information; NOT for structural content work. +- **social-content** — USE when applying brand guidelines to social-specific formats and platform constraints; NOT for cross-channel brand system design. +- **canvas-design** — USE when brand guidelines need to be applied to visual design artifacts (posters, PDFs, graphics); NOT for copy-only brand work. diff --git a/marketing-skill/campaign-analytics/SKILL.md b/marketing-skill/campaign-analytics/SKILL.md index bcf336c..d22057e 100644 --- a/marketing-skill/campaign-analytics/SKILL.md +++ b/marketing-skill/campaign-analytics/SKILL.md @@ -214,3 +214,32 @@ Calculates comprehensive ROI metrics with industry benchmarking: - **Single-currency** -- All monetary values assumed to be in the same currency. No currency conversion support. - **Simplified time-decay** -- Uses exponential decay based on configurable half-life. Does not account for weekday/weekend or seasonal patterns. - **No cross-device tracking** -- Attribution operates on provided journey data as-is. Cross-device identity resolution must be handled upstream. + +## Proactive Triggers + +- **Attribution model not set** → Last-click attribution misses 60%+ of the journey. Use multi-touch. +- **No baseline metrics documented** → Can't measure improvement without baselines. +- **Data discrepancy between tools** → GA4 and ad platform numbers rarely match. Document the gap. +- **Vanity metrics dominating reports** → Pageviews don't matter. Focus on conversion metrics. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Campaign report" | Cross-channel performance report with attribution analysis | +| "Channel comparison" | Channel-by-channel ROI with budget reallocation recommendations | +| "What's working?" | Top 5 performers + bottom 5 drains with specific actions | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **analytics-tracking**: For setting up tracking. NOT for analyzing data (that's this skill). +- **ab-test-setup**: For designing experiments to test what analytics reveals. +- **marketing-ops**: For routing insights to the right execution skill. +- **paid-ads**: For optimizing ad spend based on analytics findings. diff --git a/marketing-skill/churn-prevention/SKILL.md b/marketing-skill/churn-prevention/SKILL.md new file mode 100644 index 0000000..d90aa2b --- /dev/null +++ b/marketing-skill/churn-prevention/SKILL.md @@ -0,0 +1,240 @@ +--- +name: churn-prevention +description: "Reduce voluntary and involuntary churn through cancel flow design, save offers, exit surveys, and dunning sequences. Use when designing or optimizing a cancel flow, building save offers, setting up dunning emails, or reducing failed-payment churn. Trigger keywords: cancel flow, churn reduction, save offers, dunning, exit survey, payment recovery, win-back, involuntary churn, failed payments, cancel page. NOT for customer health scoring or expansion revenue — use customer-success-manager for that." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Churn Prevention + +You are an expert in SaaS retention and churn prevention. Your goal is to reduce both voluntary churn (customers who decide to leave) and involuntary churn (customers who leave because their payment failed) through smart flow design, targeted save offers, and systematic payment recovery. + +Churn is a revenue leak you can plug. A 20% save rate on voluntary churners and a 30% recovery rate on involuntary churners can recover 5-8% of lost MRR monthly. That compounds. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for what's missing. + +Gather this context (ask if not provided): + +### 1. Current State +- Do you have a cancel flow today, or is cancellation instant/via support? +- What's your current monthly churn rate? (voluntary vs. involuntary split if known) +- What payment processor are you on? (Stripe, Braintree, Paddle, etc.) +- Do you collect exit reasons today? + +### 2. Business Context +- SaaS model: self-serve or sales-assisted? +- Price points and plan structure +- Average contract length and billing cycle (monthly/annual) +- Current MRR + +### 3. Goals +- Which problem is primary: too many cancellations, or failed payment churn? +- Do you have a save offer budget (discounts, extensions)? +- Any constraints on cancel flow friction? (some platforms penalize dark patterns) + +## How This Skill Works + +### Mode 1: Build Cancel Flow +Starting from scratch — no cancel flow exists, or cancellation is immediate. We'll design the full flow from trigger to post-cancel. + +### Mode 2: Optimize Existing Flow +You have a cancel flow but save rates are low or you're not capturing good exit data. We'll audit what's there, identify the gaps, and rebuild what's underperforming. + +### Mode 3: Set Up Dunning +Involuntary churn from failed payments is your priority. We'll build the retry logic, notification sequence, and recovery emails. + +--- + +## Cancel Flow Design + +A cancel flow is not a dark pattern — it's a structured conversation. The goal is to understand why they're leaving and offer something genuinely useful. If they still want to cancel, let them. + +### The 5-Stage Flow + +``` +[Cancel Trigger] → [Exit Survey] → [Dynamic Save Offer] → [Confirmation] → [Post-Cancel] +``` + +**Stage 1 — Cancel Trigger** +- Show cancel option clearly (no hiding it — dark patterns burn trust) +- At the moment they click cancel, begin the flow — don't take them to a dead-end form +- Mobile: make this work on touch + +**Stage 2 — Exit Survey (1 question, required)** +- Ask ONE question: "What's the main reason you're cancelling?" +- Keep it multiple choice (6-8 reasons max) — open text is optional, not required +- This answer drives the save offer — it must be collected before showing the offer + +**Stage 3 — Dynamic Save Offer** +- Match the offer to the reason (see Exit Survey → Save Offer Mapping below) +- Don't show a generic discount — it signals your pricing was fake +- One offer per attempt. If they decline, let them cancel. + +**Stage 4 — Confirmation** +- Clear summary of what happens when they cancel (access, data, billing) +- Explicit confirmation button — "Yes, cancel my account" +- No pre-checked boxes, no confusing language + +**Stage 5 — Post-Cancel** +- Immediate confirmation email with: cancellation date, data retention policy, reactivation link +- 7-day re-engagement email: single CTA, no pressure, reactivation link +- 30-day win-back if warranted (product update or relevant offer) + +--- + +## Exit Survey Design + +The survey is your most valuable data source. Design it to generate usable intelligence, not just categories. + +### Recommended Reason Categories + +| Reason | Save Offer | Signal | +|--------|-----------|--------| +| Too expensive / price | Discount or downgrade | Price sensitivity | +| Not using it enough | Usage tips + pause option | Adoption failure | +| Missing a feature | Roadmap share + workaround | Product gap | +| Switching to competitor | Competitive comparison | Market position | +| Project ended / seasonal | Pause option | Temporary need | +| Too complicated | Onboarding help + human support | UX friction | +| Just testing / never needed | No offer — let go | Wrong fit | + +**Implementation rule:** Each reason must map to exactly one save offer type. Ambiguous mapping = generic offer = low save rate. + +--- + +## Save Offer Playbook + +Match the offer to the reason. Each offer type has a right and wrong time to use it. + +| Offer Type | When to Use | When NOT to Use | +|-----------|------------|-----------------| +| **Discount** (1-3 months) | Price objection | Adoption or feature issues | +| **Pause** (1-3 months) | Seasonal, project ended, not using | Price objection | +| **Downgrade** | Too expensive, light usage | Feature objection | +| **Extended trial** | Hasn't explored full value | Power user churning | +| **Feature unlock** | Missing feature that exists on higher plan | Wrong plan fit | +| **Human support** | Complicated, stuck, frustrated | Price objection (don't waste CS time) | + +**Offer presentation rules:** +- One clear headline: "Before you go — [offer]" +- Quantify the value: "Save $X" not "Get a discount" +- No countdown timers unless it's genuinely expiring +- Clear CTA: "Claim this offer" vs. "Continue cancelling" + +See [references/cancel-flow-playbook.md](references/cancel-flow-playbook.md) for full decision trees and flow templates. + +--- + +## Involuntary Churn: Dunning Setup + +Failed payments cause 20-40% of total churn at most SaaS companies. Most of it is recoverable. + +### Recovery Stack + +**1. Smart Retry Logic** +Don't retry immediately — failed cards often recover within 3-7 days: +- Retry 1: 3 days after failure (most recoveries happen here) +- Retry 2: 5 days after retry 1 +- Retry 3: 7 days after retry 2 +- Final: 3 days after retry 3, then cancel + +**2. Card Updater Services** +- Stripe: Account Updater (automatic, enabled by default in most plans) +- Braintree: Account Updater (must enable) +- These update expired/replaced cards before the next charge — use them + +**3. Dunning Email Sequence** + +| Day | Email | Tone | CTA | +|----|-------|------|-----| +| Day 0 | "Payment failed" | Neutral, factual | Update card | +| Day 3 | "Action needed" | Mild urgency | Update card | +| Day 7 | "Account at risk" | Higher urgency | Update card | +| Day 12 | "Final notice" | Urgent | Update card + support link | +| Day 15 | "Account paused/cancelled" | Matter-of-fact | Reactivate | + +**Email rules:** +- Subject lines: specific over vague ("Your [Product] payment failed" not "Action required") +- No guilt. No shame. Card failures happen — treat customers like adults. +- Every email links directly to the payment update page — not the dashboard + +See [references/dunning-guide.md](references/dunning-guide.md) for full email sequences and retry configuration examples. + +--- + +## Metrics & Benchmarks + +Track these weekly, review monthly: + +| Metric | Formula | Benchmark | +|--------|---------|-----------| +| **Save rate** | Customers saved / cancel attempts | 10-15% good, 20%+ excellent | +| **Voluntary churn rate** | Voluntary cancels / total customers | <2% monthly | +| **Involuntary churn rate** | Failed payment cancels / total customers | <1% monthly | +| **Recovery rate** | Failed payments recovered / total failed | 25-35% good | +| **Win-back rate** | Reactivations / post-cancel 90 days | 5-10% | +| **Exit survey completion** | Surveys completed / cancel attempts | >80% | + +**Red flags:** +- Save rate <5% → offers aren't matching reasons +- Exit survey completion <70% → survey is too long or optional +- Recovery rate <20% → retry logic or emails need work + +Use the churn impact calculator to model what improving each metric is worth: + +```bash +python3 scripts/churn_impact_calculator.py +``` + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Instant cancellation flow** → Revenue is leaking immediately. Any friction saves money — flag for priority fix. +- **Single generic save offer** → A discount shown to everyone depresses average revenue and trains customers to wait for deals. Map offers to exit reasons. +- **No dunning sequence** → If payment fails and nothing happens, that's 20-40% of churn going unaddressed. Flag immediately. +- **Exit survey is optional** → <70% completion = bad data. Make it required (one question, fast). +- **No post-cancel reactivation email** → The 7-day window is the highest win-back moment. Missing it leaves money on the table. +- **Churn rate >5% monthly** → At this rate, the company is likely contracting. Churn prevention alone won't fix it — flag for product/ICP review alongside retention work. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|--------------------|-----------| +| "Design a cancel flow" | 5-stage flow diagram (text) with copy for each stage, save offer map, and confirmation email template | +| "Audit my cancel flow" | Scorecard (0-100) with gaps, save rate benchmarks, and prioritized fixes | +| "Set up dunning" | Retry schedule, 5-email sequence with subject lines and body copy, card updater setup checklist | +| "Design an exit survey" | 6-8 reason categories with save offer mapping table | +| "Model churn impact" | Run churn_impact_calculator.py with your inputs — monthly MRR saved and annual impact | +| "Write win-back emails" | 2-email win-back sequence (7-day and 30-day) with subject lines | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — save rate estimate or recovery potential before methodology +- **What + Why + How** — every recommendation has all three +- **Actions have owners and deadlines** — no vague suggestions +- **Confidence tagging** — 🟢 verified benchmark / 🟔 estimated / šŸ”“ assumed + +--- + +## Related Skills + +- **customer-success-manager**: Use for health scoring, QBRs, and expansion revenue. NOT for cancel flow or dunning. +- **email-sequence**: Use for lifecycle nurture and onboarding emails. NOT for dunning (use this skill for dunning). +- **pricing-strategy**: Use when churn root cause is pricing or packaging mismatch. NOT for save offer design (use this skill). +- **campaign-analytics**: Use for analyzing which acquisition channels produce high-churn customers. NOT for setting up retention tracking. +- **signup-flow-cro**: Use for reducing drop-off at signup. NOT for post-signup retention. diff --git a/marketing-skill/churn-prevention/references/cancel-flow-playbook.md b/marketing-skill/churn-prevention/references/cancel-flow-playbook.md new file mode 100644 index 0000000..ece031d --- /dev/null +++ b/marketing-skill/churn-prevention/references/cancel-flow-playbook.md @@ -0,0 +1,254 @@ +# Cancel Flow Playbook + +Complete reference for designing, building, and auditing cancel flows. + +--- + +## The Cancel Flow Decision Tree + +``` +Customer clicks "Cancel" or "Cancel Subscription" + │ + ā–¼ + [Show Exit Survey] + "What's the main reason you're cancelling?" + │ + ā”Œā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” + │ │ + Price/Value Other Reasons + │ │ + ā–¼ ā–¼ +Discount offer Match to reason category +(1-3 month, 20-30%) (see mapping table) + │ │ + ā–¼ ā–¼ +[Accept?]──Yes──► Charge updated [Accept?]──Yes──► Apply offer + │ │ + No No + │ │ + ā–¼ ā–¼ +[Confirm Cancel] [Confirm Cancel] + │ │ + ā–¼ ā–¼ +[Post-cancel page + email] [Post-cancel page + email] +``` + +--- + +## Stage-by-Stage Templates + +### Stage 1: Pre-Cancel Intercept + +**When triggered:** User lands on cancel/subscription page, clicks "Cancel plan", or navigates to billing settings. + +**What to show:** Brief value reminder (not a wall of guilt) + "Tell us why" framing. + +**Copy template:** +``` +Headline: Before you go, we want to understand +Body: Your feedback helps us improve. Take 30 seconds to tell us why + you're cancelling — and we might have a solution you haven't tried. +CTA: Continue to cancellation → +``` + +**Rules:** +- Don't block the cancel path +- Don't show this more than once per session +- Mobile: single screen, no scrolling required + +--- + +### Stage 2: Exit Survey + +**Design specs:** +- Single question, required +- Radio buttons (not checkboxes) +- 6-8 options maximum +- Optional open text at bottom: "Anything else we should know?" +- Submit advances to Stage 3 — don't show offer yet + +**Copy template:** +``` +What's the main reason you're cancelling? + +ā—‹ It's too expensive for what I get +ā—‹ I'm not using it enough to justify the cost +ā—‹ It's missing a feature I need +ā—‹ I'm switching to a different tool +ā—‹ My project or need ended +ā—‹ It's too complicated or hard to use +ā—‹ I was just testing it out +ā—‹ Other: [text field] + +[Continue →] +``` + +**Data capture:** Store the reason against the customer record. This is your product feedback goldmine. + +--- + +### Stage 3: Dynamic Save Offer + +**Offer-to-reason mapping (full):** + +| Selected Reason | Primary Offer | Secondary (if declined) | Skip Offer | +|----------------|--------------|------------------------|------------| +| Too expensive | 30% off for 3 months | Downgrade plan | — | +| Not using it enough | 1-month pause | Usage coaching call | — | +| Missing a feature | Feature roadmap share + workaround | Human support call | If feature genuinely doesn't exist and won't exist soon | +| Switching to competitor | Competitive comparison one-pager | — | If they've clearly made the decision | +| Project ended | 2-month pause | — | — | +| Too complicated | Free onboarding session | 1:1 support call | — | +| Just testing | — | — | Always skip — wrong fit, let them go | +| Other | Human support call | — | — | + +**Offer presentation template:** + +``` +[For price objection:] +Headline: Keep [Product] for less +Body: We'd hate to see you go over price. Here's what we can do: + Get 30% off your next 3 months — that's [calculated dollar amount] saved. + After 3 months, your plan returns to [original price]. +CTA (accept): Claim my discount → +CTA (decline): No thanks, continue cancelling → + +[For not using it enough:] +Headline: No charge for 60 days — pause your account +Body: Life gets busy. Put [Product] on hold for up to 60 days. + Your data stays intact, and you can resume any time. No charge during pause. +CTA (accept): Pause my account → +CTA (decline): No thanks, continue cancelling → +``` + +**Offer rules:** +- One offer per cancel attempt — never show multiple +- If they decline, go straight to Stage 4 +- Don't re-show the same offer if they return to cancel within 30 days +- Track which offer was shown and whether it was accepted + +--- + +### Stage 4: Cancellation Confirmation + +**What to include:** +- Explicit confirmation of what will happen +- Access end date (specific date, not "end of billing period") +- Data retention policy (how long data is kept) +- Support contact in case they change their mind +- Confirmation button with clear copy + +**Copy template:** +``` +Your subscription will be cancelled. + +Here's what happens next: +• Access continues until [specific date] +• Your data is retained for 90 days after cancellation +• After 90 days, your account data is deleted +• You can reactivate any time before [90-day date] + +If you change your mind, contact [email] or reactivate at [reactivation URL]. + +[Confirm Cancellation] [Go back] +``` + +--- + +### Stage 5: Post-Cancel Sequence + +**Immediate: Cancellation Confirmation Email** + +``` +Subject: Your [Product] subscription has been cancelled + +Hi [Name], + +Your [Product] subscription has been cancelled as requested. + +What happens next: +- Access continues until [date] +- Your data is saved for 90 days (until [date]) +- To reactivate, visit: [reactivation link] + +If this was a mistake or you have questions, reply to this email or visit [support link]. + +[Product] Team +``` + +**Day 7: Re-engagement Email** + +``` +Subject: Your [Product] account is still here + +Hi [Name], + +It's been a week since you cancelled. Your account and data are still intact +until [date]. + +If anything changed, you can reactivate in one click — no re-setup required. + +[Reactivate my account →] + +No pressure — just wanted to make sure you knew the door's open. + +[Product] Team +``` + +**Day 30: Win-Back Email (send only if triggered by product update or relevant offer)** + +``` +Subject: [Product] update: [specific feature they mentioned or relevant improvement] + +Hi [Name], + +Since you left, we shipped [specific update relevant to their cancel reason]. +[2-3 sentence description of what changed.] + +If [their specific problem] was why you left, it might be worth another look. + +[See what's new →] or [Reactivate →] + +[Product] Team +``` + +--- + +## Cancel Flow Audit Scorecard + +Rate your existing flow on each dimension (0-10): + +| Dimension | 0 pts | 5 pts | 10 pts | +|-----------|-------|-------|--------| +| **Accessibility** | Cancel requires support ticket | Cancel in settings, but buried | Cancel clearly visible in billing settings | +| **Exit survey** | None | Optional, multi-question | Required, single question, maps to offers | +| **Save offers** | None or generic discount | Offers exist but not mapped | Offers matched to exit reasons | +| **Confirmation clarity** | Confusing terms | Mentions access end date | Clear date, data policy, reactivation path | +| **Post-cancel sequence** | Nothing | One generic email | Immediate confirmation + 7-day re-engagement | +| **Dunning** | None | Basic retry only | Retry + email sequence + card updater | +| **Analytics** | No tracking | Basic cancellation count | Reason tracking, save rate, recovery rate | + +**Score interpretation:** +- 60-70: Solid foundation. Fix the 0-5 rated dimensions. +- 40-59: Material revenue leaking. Prioritize survey + offer mapping. +- <40: Major opportunity. Build from scratch using this playbook. + +--- + +## Platform Implementation Notes + +### Stripe +- Use Customer Portal for cancel flow (customizable via Stripe Dashboard) +- Enable Stripe Billing webhooks: `customer.subscription.deleted`, `invoice.payment_failed` +- Stripe Radar helps filter bot-initiated failures from real card failures +- Account Updater: enabled by default on most plans — verify in Dashboard > Settings + +### Chargebee / Recurly +- Both have native cancel flow builders with reason collection +- Dunning sequences configurable in-product +- Connect to your email provider (Intercom, Customer.io, etc.) via webhook + +### Custom / Homegrown Billing +- Build cancel flow as a separate route (not inline in settings) +- Store `cancel_reason`, `save_offer_shown`, `save_offer_accepted` per customer +- Retry logic: implement as a background job with delay queue diff --git a/marketing-skill/churn-prevention/references/dunning-guide.md b/marketing-skill/churn-prevention/references/dunning-guide.md new file mode 100644 index 0000000..9f564db --- /dev/null +++ b/marketing-skill/churn-prevention/references/dunning-guide.md @@ -0,0 +1,276 @@ +# Dunning Guide + +Payment recovery strategies, retry logic, and email sequences for involuntary churn. + +--- + +## Why Involuntary Churn Matters + +At most SaaS companies, 20-40% of all churn comes from failed payments — not customer decisions. The customer didn't choose to leave. Their card expired, got replaced, hit a limit, or was flagged by their bank. Most of these situations are recoverable within 7-14 days. + +**The math:** +- 1,000 active customers +- 3% monthly churn rate = 30 churned per month +- If 30% of that is involuntary = 9 customers/month from failed payments +- Recovery rate of 40% = 3.6 customers saved/month +- At $100 MRR: $360/month recovered, $4,320/year — from just fixing dunning + +That's before touching voluntary churn. + +--- + +## Failure Mode Taxonomy + +Not all payment failures are equal. Categorize before deciding how to retry: + +| Failure Type | Decline Code | Recovery Approach | +|-------------|-------------|-------------------| +| **Insufficient funds** | `insufficient_funds` | Retry in 3-5 days (balance usually replenishes) | +| **Card expired** | `expired_card` | Card updater first; email to update card | +| **Card replaced** | `card_not_supported`, network updated | Card updater handles this automatically | +| **Do not honor** | `do_not_honor` | Retry once in 3 days; email to contact bank | +| **Fraud flagged** | `fraudulent` | Email immediately; don't retry — let customer resolve | +| **Card lost/stolen** | `lost_card`, `stolen_card` | Email immediately; do not retry | +| **Generic decline** | `generic_decline` | Retry 2x over 7 days; then email | + +**Rule:** Never retry fraudulent, lost, or stolen card declines. It increases chargeback risk. + +--- + +## Retry Schedule + +Optimal timing based on card network research: + +``` +Day 0: Payment fails (initial charge) +Day 3: Retry 1 — highest recovery rate (3-7 days is the sweet spot) +Day 8: Retry 2 — catches monthly paycycle refills +Day 13: Retry 3 — final automated attempt +Day 16: Cancel subscription (if not recovered) +``` + +**Stripe-specific configuration:** + +In Stripe Billing settings (Dashboard > Billing > Subscriptions and emails): +``` +Smart Retries: Enable (Stripe uses ML to pick retry timing) + OR +Manual schedule: 3 days, 5 days, 7 days +Subscription behavior after all retries: Cancel subscription +``` + +**Alternative for maximum recovery:** +If using Smart Retries (Stripe), disable manual schedule — they conflict. +Smart Retries uses real-time card network data and typically outperforms fixed schedules. + +--- + +## Card Updater Services + +These services update card details automatically when banks issue new cards: + +| Provider | Service Name | Config Required | +|---------|-------------|-----------------| +| Stripe | Account Updater | Enabled by default. Verify in Dashboard > Settings > Card account updater | +| Braintree | Account Updater | Must enable in Control Panel > Processing > Account Updater | +| Recurly | Account Updater | Available on Professional and above | +| Chargebee | Smart Dunning | Bundled with Chargebee; enable in configuration | + +**Expected impact:** 15-25% of involuntary churn prevented before dunning emails are needed. + +--- + +## Dunning Email Sequence + +Five emails. Each one escalates slightly in urgency. No guilt, no shame — these are operational communications. + +--- + +### Email 1 — Day 0: "Payment failed" + +**Goal:** Inform, make it easy to fix. + +``` +Subject: Your [Product] payment didn't go through + +Hi [Name], + +We weren't able to process your [Product] subscription payment of [amount]. + +This happens sometimes — an expired card, a temporary issue with your bank, +or a card limit. Easy to fix. + +Update your payment details here: +[Update payment method →] + +If you need help, reply to this email. + +[Product] Team + +--- +Payment amount: [amount] +Billing date: [date] +Next retry: [date + 3 days] +``` + +**Notes:** +- Send within 1 hour of failure +- Include specific amount and date — vague emails get ignored +- Mention the next retry date — some customers will wait for the retry to see if it clears + +--- + +### Email 2 — Day 3: "Retry coming up" + +**Goal:** Catch people before the retry so they can update the card first. + +``` +Subject: [Product] — we'll try your payment again tomorrow + +Hi [Name], + +We're going to attempt your [Product] payment of [amount] again tomorrow +([specific date]). + +If your card details have changed, update them now so the retry goes through: +[Update payment method →] + +If the retry fails, we'll reach out again. + +[Product] Team +``` + +**Notes:** +- Send day before the retry, not day of +- Short email — one job, one CTA +- Some payment processors let you trigger a manual retry immediately after card update — mention this if yours does + +--- + +### Email 3 — Day 7: "We tried again — still failing" + +**Goal:** Add urgency, soften tone, offer help. + +``` +Subject: [Product] payment still failing — action needed + +Hi [Name], + +We've attempted to process your [Product] subscription twice now, +and the payment hasn't gone through. + +Your account is still active, but we'll need to resolve this soon to +avoid any interruption. + +A few common fixes: +• Check if your card has expired and update it +• Contact your bank if the card is being declined unexpectedly +• Use a different card if this one is no longer working + +Update payment details: +[Update payment method →] + +Still having trouble? Reply to this email and we'll help you sort it out. + +[Product] Team +``` + +**Notes:** +- Shift from notification to problem-solving +- List common causes — helps customers self-diagnose +- Offer human help — some people have legitimate confusion + +--- + +### Email 4 — Day 12: "Final notice" + +**Goal:** Create urgency without being threatening. Be clear about what happens. + +``` +Subject: [Product] account at risk — payment needed by [specific date] + +Hi [Name], + +We've made multiple attempts to process your [Product] subscription, +and we haven't been able to reach your card. + +Your account will be cancelled on [specific date] if we don't receive payment. + +Here's what you'll lose access to: +• [Key feature / data point] +• [Key feature / data point] +• Your [X] months of [data/history/usage] + +This is our last reminder before cancellation. + +Update payment now: +[Update payment method →] + +Need to talk to someone? [Book a call] or reply here. + +[Product] Team +``` + +**Notes:** +- Use a specific date — "soon" doesn't create urgency, "March 15" does +- List what they lose — tangible is more motivating than abstract +- Offer human escalation — some churn at this stage is recoverable by a support person + +--- + +### Email 5 — Day 16: "Account cancelled" + +**Goal:** Inform, leave the door open, make reactivation easy. + +``` +Subject: Your [Product] account has been cancelled + +Hi [Name], + +We've cancelled your [Product] subscription as of today. Your card could +not be charged for [amount] after multiple attempts. + +Your data is saved for 90 days (until [date]). + +To reactivate: +[Reactivate my account →] + +You'll be able to pick up where you left off — all your data will be intact. + +If you think this was an error, reply to this email and we'll sort it out. + +[Product] Team +``` + +**Notes:** +- No blame, no guilt — this is a notification, not a scolding +- Make reactivation frictionless — one click, not a new signup flow +- Data retention timeline gives them a reason to act within 90 days + +--- + +## Dunning Metrics to Track + +| Metric | What it measures | Target | +|--------|-----------------|--------| +| **Recovery rate** | Failed payments recovered / total failed | 25-40% | +| **Recovery by email** | Which email in the sequence converts most | Track per email | +| **Recovery by retry** | Which retry attempt succeeds most | Usually retry 1 (day 3) | +| **Time to recovery** | Days from first failure to payment | <10 days is good | +| **Card updater hit rate** | Cards auto-updated before manual outreach | 15-25% of failures | + +--- + +## Third-Party Dunning Tools + +For teams who want plug-and-play dunning without building it: + +| Tool | Best For | Pricing Model | +|------|---------|--------------| +| **Churnkey** | Stripe users, full cancel flow + dunning | Revenue share | +| **ProfitWell Retain** | Stripe + Braintree, analytics-heavy | % of recovered revenue | +| **Stunning** | Stripe-native, email-focused | Flat monthly | +| **Recurly** | Already on Recurly | Built-in | +| **Chargebee Smart Dunning** | Already on Chargebee | Built-in | + +**When to use a third-party tool:** If you're <$500k MRR and don't have engineering bandwidth to build retry logic + email sequences, a tool pays for itself quickly. Above that threshold, build it in-house for more control. diff --git a/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py b/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py new file mode 100644 index 0000000..ecd64c2 --- /dev/null +++ b/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +"""Churn impact calculator — models revenue impact of churn reduction improvements.""" + +import json +import sys + + +SAMPLE_INPUT = { + "mrr": 50000, + "monthly_churn_rate_pct": 4.5, + "voluntary_churn_pct": 65, + "current_save_rate_pct": 8, + "target_save_rate_pct": 20, + "current_recovery_rate_pct": 15, + "target_recovery_rate_pct": 35, + "avg_customer_mrr": 150 +} + + +def calculate(inputs): + mrr = inputs["mrr"] + churn_rate = inputs["monthly_churn_rate_pct"] / 100 + voluntary_pct = inputs["voluntary_churn_pct"] / 100 + involuntary_pct = 1 - voluntary_pct + current_save = inputs["current_save_rate_pct"] / 100 + target_save = inputs["target_save_rate_pct"] / 100 + current_recovery = inputs["current_recovery_rate_pct"] / 100 + target_recovery = inputs["target_recovery_rate_pct"] / 100 + avg_customer_mrr = inputs["avg_customer_mrr"] + + # Total MRR churned per month + total_churned_mrr = mrr * churn_rate + voluntary_churned_mrr = total_churned_mrr * voluntary_pct + involuntary_churned_mrr = total_churned_mrr * involuntary_pct + + # Current saves/recoveries + current_saves_mrr = voluntary_churned_mrr * current_save + current_recoveries_mrr = involuntary_churned_mrr * current_recovery + current_total_saved = current_saves_mrr + current_recoveries_mrr + + # Target saves/recoveries + target_saves_mrr = voluntary_churned_mrr * target_save + target_recoveries_mrr = involuntary_churned_mrr * target_recovery + target_total_saved = target_saves_mrr + target_recoveries_mrr + + # Incremental gains + incremental_monthly = target_total_saved - current_total_saved + incremental_annual = incremental_monthly * 12 + + # Customer counts + voluntary_churned_customers = voluntary_churned_mrr / avg_customer_mrr + involuntary_churned_customers = involuntary_churned_mrr / avg_customer_mrr + additional_saves = (target_save - current_save) * voluntary_churned_customers + additional_recoveries = (target_recovery - current_recovery) * involuntary_churned_customers + total_additional_customers = additional_saves + additional_recoveries + + # LTV impact (assuming 24-month average tenure at current churn rate) + implied_ltv_months = 1 / churn_rate + ltv_per_customer = avg_customer_mrr * implied_ltv_months + ltv_impact = total_additional_customers * ltv_per_customer + + return { + "baseline": { + "mrr": mrr, + "monthly_churn_rate_pct": inputs["monthly_churn_rate_pct"], + "total_churned_mrr_monthly": round(total_churned_mrr, 0), + "voluntary_churned_mrr": round(voluntary_churned_mrr, 0), + "involuntary_churned_mrr": round(involuntary_churned_mrr, 0), + }, + "current_performance": { + "save_rate_pct": inputs["current_save_rate_pct"], + "recovery_rate_pct": inputs["current_recovery_rate_pct"], + "monthly_saved_mrr": round(current_total_saved, 0), + "annual_saved_mrr": round(current_total_saved * 12, 0), + }, + "target_performance": { + "save_rate_pct": inputs["target_save_rate_pct"], + "recovery_rate_pct": inputs["target_recovery_rate_pct"], + "monthly_saved_mrr": round(target_total_saved, 0), + "annual_saved_mrr": round(target_total_saved * 12, 0), + }, + "improvement_impact": { + "incremental_mrr_monthly": round(incremental_monthly, 0), + "incremental_mrr_annual": round(incremental_annual, 0), + "additional_customers_saved_monthly": round(total_additional_customers, 1), + "implied_ltv_per_customer": round(ltv_per_customer, 0), + "ltv_impact_of_saved_customers": round(ltv_impact, 0), + }, + "priorities": _prioritize( + voluntary_churned_mrr, involuntary_churned_mrr, + current_save, target_save, + current_recovery, target_recovery + ) + } + + +def _prioritize(vol_mrr, inv_mrr, cur_save, tgt_save, cur_rec, tgt_rec): + save_opportunity = vol_mrr * (tgt_save - cur_save) + rec_opportunity = inv_mrr * (tgt_rec - cur_rec) + + if save_opportunity > rec_opportunity * 1.5: + primary = "cancel-flow-and-save-offers" + secondary = "dunning" + elif rec_opportunity > save_opportunity * 1.5: + primary = "dunning-and-payment-recovery" + secondary = "cancel-flow" + else: + primary = "both-roughly-equal" + secondary = "start-with-dunning-easier-to-implement" + + return { + "voluntary_save_opportunity_mrr": round(save_opportunity, 0), + "involuntary_recovery_opportunity_mrr": round(rec_opportunity, 0), + "recommendation": primary, + "note": secondary + } + + +def print_report(result): + b = result["baseline"] + cur = result["current_performance"] + tgt = result["target_performance"] + imp = result["improvement_impact"] + pri = result["priorities"] + + print("\n" + "="*60) + print(" CHURN IMPACT CALCULATOR") + print("="*60) + + print(f"\nšŸ“Š BASELINE") + print(f" MRR: ${b['mrr']:,.0f}") + print(f" Monthly churn rate: {b['monthly_churn_rate_pct']}%") + print(f" Total MRR churned/mo: ${b['total_churned_mrr_monthly']:,.0f}") + print(f" └─ Voluntary: ${b['voluntary_churned_mrr']:,.0f}") + print(f" └─ Involuntary: ${b['involuntary_churned_mrr']:,.0f}") + + print(f"\nšŸ“‰ CURRENT PERFORMANCE") + print(f" Save rate: {cur['save_rate_pct']}%") + print(f" Payment recovery rate: {cur['recovery_rate_pct']}%") + print(f" MRR saved monthly: ${cur['monthly_saved_mrr']:,.0f}") + print(f" MRR saved annually: ${cur['annual_saved_mrr']:,.0f}") + + print(f"\nšŸŽÆ TARGET PERFORMANCE") + print(f" Save rate: {tgt['save_rate_pct']}%") + print(f" Payment recovery rate: {tgt['recovery_rate_pct']}%") + print(f" MRR saved monthly: ${tgt['monthly_saved_mrr']:,.0f}") + print(f" MRR saved annually: ${tgt['annual_saved_mrr']:,.0f}") + + print(f"\nšŸ’° INCREMENTAL IMPACT") + print(f" Additional MRR/month: ${imp['incremental_mrr_monthly']:,.0f}") + print(f" Additional MRR/year: ${imp['incremental_mrr_annual']:,.0f}") + print(f" Customers saved/month: {imp['additional_customers_saved_monthly']}") + print(f" Implied LTV/customer: ${imp['implied_ltv_per_customer']:,.0f}") + print(f" LTV impact: ${imp['ltv_impact_of_saved_customers']:,.0f}") + + print(f"\nšŸ” PRIORITY RECOMMENDATION") + print(f" Voluntary opportunity: ${pri['voluntary_save_opportunity_mrr']:,.0f}/mo") + print(f" Involuntary opportunity: ${pri['involuntary_recovery_opportunity_mrr']:,.0f}/mo") + print(f" Focus on: {pri['recommendation'].replace('-', ' ').title()}") + if pri['note']: + print(f" Note: {pri['note'].replace('-', ' ')}") + + print("\n" + "="*60 + "\n") + + +def main(): + if len(sys.argv) > 1: + with open(sys.argv[1]) as f: + inputs = json.load(f) + else: + print("No input file provided. Running with sample data...\n") + print("Sample input:") + print(json.dumps(SAMPLE_INPUT, indent=2)) + inputs = SAMPLE_INPUT + + result = calculate(inputs) + print_report(result) + + # Also dump JSON for programmatic use + if "--json" in sys.argv: + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/cold-email/SKILL.md b/marketing-skill/cold-email/SKILL.md new file mode 100644 index 0000000..f3c8f39 --- /dev/null +++ b/marketing-skill/cold-email/SKILL.md @@ -0,0 +1,272 @@ +--- +name: cold-email +description: "When the user wants to write, improve, or build a sequence of B2B cold outreach emails to prospects who haven't asked to hear from them. Use when the user mentions 'cold email,' 'cold outreach,' 'prospecting emails,' 'SDR emails,' 'sales emails,' 'first touch email,' 'follow-up sequence,' or 'email prospecting.' Also use when they share an email draft that sounds too sales-y and needs to be humanized. Distinct from email-sequence (lifecycle/nurture to opted-in subscribers) — this is unsolicited outreach to new prospects. NOT for lifecycle emails, newsletters, or drip campaigns (use email-sequence)." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Cold Email Outreach + +You are an expert in B2B cold email outreach. Your goal is to help write, build, and iterate on cold email sequences that sound like they came from a thoughtful human — not a sales machine — and actually get replies. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. + +Gather this context: + +### 1. The Sender +- Who are they at this company? (Role, seniority — affects how they write) +- What do they sell and who buys it? +- Do they have any real customer results or proof points they can reference? +- Are they sending as an individual or as a company? + +### 2. The Prospect +- Who is the target? (Job title, company type, company size) +- What problem does this person likely have that the sender can solve? +- Is there a specific trigger or reason to reach out now? (funding, hiring, news, tech stack signal) +- Do they have specific names and companies to personalize to, or is this a template for a segment? + +### 3. The Ask +- What's the goal of the first email? (Book a call? Get a reply? Get a referral?) +- How aggressive is the timeline? (SDR with daily send volume vs founder doing targeted outreach) + +--- + +## How This Skill Works + +### Mode 1: Write the First Email +When they need a single first-touch email or a template for a segment. + +1. Understand the ICP, the problem, and the trigger +2. Choose the right framework (see `references/frameworks.md`) +3. Draft first email: subject line, opener, body, CTA +4. Review against the principles below — cut anything that doesn't earn its place +5. Deliver: email copy + 2-3 subject line variants + brief rationale + +### Mode 2: Build a Follow-Up Sequence +When they need a multi-email sequence (typically 4-6 emails). + +1. Start with the first email (Mode 1) +2. Plan follow-up angles — each email needs a different angle, not just a nudge +3. Set the gap cadence (Day 1, Day 4, Day 9, Day 16, Day 25) +4. Write each follow-up with a standalone hook that doesn't require reading previous emails +5. End with a breakup email that closes the loop professionally +6. Deliver: full sequence with send gaps, subject lines, and brief on what each email does + +### Mode 3: Iterate from Performance Data +When they have an active sequence and want to improve it. + +1. Review their current sequence emails and performance (open rate, reply rate) +2. Diagnose: is the problem subject lines (low open rate), email body (opens but no replies), or CTA (replies but wrong outcome)? +3. Rewrite the underperforming element +4. Deliver: revised emails + diagnosis + test recommendation + +--- + +## Core Writing Principles + +### 1. Write Like a Peer, Not a Vendor + +The moment your email sounds like marketing copy, it's over. Think about how you'd actually email a smart colleague at another company who you want to have a conversation with. + +**The test:** Would a friend send this to another friend in business? If the answer is no — rewrite it. + +- āŒ "I'm reaching out because our platform helps companies like yours achieve unprecedented growth..." +- āœ… "Noticed you're scaling your SDR team — timing question: are you doing outbound email in-house or using an agency?" + +### 2. Every Sentence Earns Its Place + +Cold email is the wrong place to be thorough. Every sentence should do one of these jobs: create curiosity, establish relevance, build credibility, or drive to the ask. If a sentence doesn't do one of those — cut it. + +Read your draft aloud. The moment you hear yourself droning, stop and cut. + +### 3. Personalization Must Connect to the Problem + +Generic personalization is worse than none. "I saw you went to MIT" followed by a pitch has nothing to do with MIT. That's fake personalization. + +Real personalization: "I saw you're hiring three SDRs — usually a signal that you're trying to scale cold outreach. That's exactly the challenge we help with." + +The personalization must connect to the reason you're reaching out. + +### 4. Lead With Their World, Not Yours + +The opener should be about them — their situation, their problem, their context. Not about you or your product. + +- āŒ "We're a sales intelligence platform that..." +- āœ… "Your recent TechCrunch piece mentioned you're entering the SMB market — that transition is notoriously hard to do with an enterprise-built playbook." + +### 5. One Ask Per Email + +Don't ask them to book a call, watch a demo, read a case study, AND reply with their timeline. Pick one ask. The more you ask for, the less likely any of it happens. + +--- + +## Voice Calibration by Audience + +Adjust tone, length, and specificity based on who you're writing to: + +| Audience | Length | Tone | Subject Line Style | What Works | +|----------|--------|------|-------------------|------------| +| C-suite (CEO, CRO, CMO) | 3-4 sentences | Ultra-brief, peer-level, strategic | Short, vague, internal-looking | Big problem → relevant proof → one question | +| VP / Director | 5-7 sentences | Direct, metrics-conscious | Slightly more specific | Specific observation + clear business angle | +| Mid-level (Manager, Analyst) | 7-10 sentences | Practical, shows you did homework | Can be more descriptive | Specific problem + practical value + easy CTA | +| Technical (Engineer, Architect) | 7-10 sentences | Precise, no fluff | Technical specificity | Exact problem → precise solution → low-friction ask | + +The higher up the org chart, the shorter your email needs to be. A CEO gets 100+ emails per day. Three sentences and a clear question is a gift, not a slight. + +--- + +## Subject Lines: The Anti-Marketing Approach + +The goal of a subject line is to get the email opened — not to convey value, not to be clever, not to impress anyone. Just open it. + +The best cold email subject lines look like internal emails. They're short, slightly vague, and create just enough curiosity to click. + +### What Works + +| Pattern | Example | Why It Works | +|---------|---------|-------------| +| Two or three words | `quick question` | Looks like an actual email from a colleague | +| Specific trigger + question | `your TechCrunch piece` | Specific enough to not look like spam | +| Shared context | `re: Series B` | Feels like a follow-up, not cold | +| Observation | `your ATS setup` | Specific, relevant, not salesy | +| Referral hook | `[mutual name] suggested I reach out` | Social proof front-loaded | + +### What Kills Opens + +- ALL CAPS anything +- Emojis in subject lines (polarizing, often spam-filtered) +- Fake Re: or Fwd: (people have learned this trick — it damages trust) +- Asking a question in the subject line (e.g., "Are you struggling with X?") — sounds like an ad +- Mentioning your company name ("Acme Corp: helping you achieve...") +- Numbers that feel like blog headlines ("5 ways to improve your...") + +--- + +## Follow-Up Strategy + +Most deals happen in follow-ups. Most follow-ups are useless. The difference is whether the follow-up adds value or just creates noise. + +### Cadence + +| Email | Send Day | Gap | +|-------|----------|-----| +| Email 1 | Day 1 | — | +| Email 2 | Day 4 | +3 days | +| Email 3 | Day 9 | +5 days | +| Email 4 | Day 16 | +7 days | +| Email 5 | Day 25 | +9 days | +| Breakup | Day 35 | +10 days | + +Gaps increase over time. You're persistent but not annoying. + +### Follow-Up Rules + +**Each follow-up must have a new angle.** Rotate through: +- New piece of evidence (case study, data point, recent result) +- New angle on the problem (a different pain point in their world) +- Related insight (something you noticed about their industry, tech stack, or news) +- Direct question (just ask plainly — sometimes clarity cuts through) +- Reverse ask (ask for referral to the right person if you can't reach them) + +**Never "just check in."** "Just following up to see if you had a chance to read my last email" is a waste of both your time and theirs. If you have nothing new to add, don't send the email. + +**Don't reference all previous emails.** Each follow-up should stand alone. The prospect doesn't remember your earlier emails. Don't make them scroll. + +### The Breakup Email + +The last email in a sequence should close the loop professionally. It signals this is the last one — which paradoxically increases reply rate because people don't like loose ends. + +Example breakup: +> "I'll stop cluttering your inbox after this one. If [problem] ever becomes a priority, happy to reconnect — just reply here and I'll pick it up. +> +> If there's someone else at [Company] I should speak with, a name would go a long way. +> +> Either way — good luck with [whatever's relevant]." + +See `references/follow-up-playbook.md` for full cadence templates and angle rotation guide. + +--- + +## What to Avoid + +These are not suggestions — they're patterns that mark you as a non-human and kill reply rates: + +| āŒ Avoid | Why It Fails | +|----------|-------------| +| "I hope this email finds you well" | Instant tell that this is templated. Cut it. | +| "I wanted to reach out because..." | 3-word delay before actually saying anything | +| Feature dump in email 1 | Nobody cares about features when they don't trust you yet | +| HTML templates with logos and colors | Looks like marketing, gets spam-filtered | +| Fake Re:/Fwd: subject lines | Feels deceptive — kills trust before the first word | +| "Just checking in" follow-ups | Adds no value, removes credibility | +| Opening with "My name is X and I work at Y" | They can see your name. Start with something interesting. | +| Social proof that doesn't connect to their problem | "We work with 500 companies" means nothing without context | +| Long-form case study in email 1 | Save it for follow-up when they've shown interest | +| Passive CTAs ("Let me know if you're interested") | Weak. Ask a direct question or propose a specific next step. | + +--- + +## Deliverability Basics + +A great email sent from a flagged domain never lands. Basics you need to have in place: + +- **Dedicated sending domain** — don't send cold email from your primary domain. Use `mail.yourdomain.com` or `outreach.yourdomain.com`. +- **SPF, DKIM, DMARC** — all three must be configured and passing. Use mail-tester.com to verify. +- **Domain warmup** — new domains need 4-6 weeks of warmup (start with 20/day, ramp up over time). +- **Plain text emails** — or minimal HTML. Heavy HTML triggers spam filters. +- **Unsubscribe mechanism** — required legally (CAN-SPAM, GDPR). Include a simple opt-out. +- **Sending limits** — stay under 100-200 emails/day per domain until established reputation. +- **Bounce rate** — above 5% hurts deliverability. Verify email lists before sending. + +See `references/deliverability-guide.md` for domain warmup schedule, SPF/DKIM setup, and spam trigger word list. + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Email opens with "My name is" or "I'm reaching out because"** → rewrite the opener. These are dead-on-arrival openers. Flag and offer an alternative that leads with their world. +- **First email is longer than 150 words** → almost certainly too long. Flag word count and offer to trim. +- **No personalization beyond first name** → templated feel will hurt reply rates. Ask if there's a trigger or signal they can work with. +- **Follow-up says "just checking in" or "circling back"** → useless follow-up. Ask what new angle or value they can bring to that touchpoint. +- **HTML email template** → recommend plain text. Plain text emails have higher deliverability and look less like marketing blasts. +- **CTA asks for 30-45 minute meeting in email 1** → too high-friction for cold outreach. Recommend a lower-commitment ask (a 15-minute call, or just a question to gauge interest first). + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| Write a cold email | First-touch email + 3 subject line variants + brief rationale for structure choices | +| Build a sequence | 5-6 email sequence with send gaps, subject lines per email, and angle summary for each follow-up | +| Critique my email | Line-by-line assessment + rewrite + explanation of each change | +| Write follow-ups only | Follow-up emails 2-6 with unique angles per email + breakup email | +| Analyze sequence performance | Diagnosis of where the sequence breaks (subject/body/CTA) + specific rewrite recommendations | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding has all three +- **Actions have owners and deadlines** — no "we should consider" +- **Confidence tagging** — 🟢 verified / 🟔 medium / šŸ”“ assumed + +--- + +## Related Skills + +- **email-sequence**: For lifecycle and nurture emails to opted-in subscribers. Use email-sequence for onboarding flows, re-engagement campaigns, and automated drips. NOT for cold outreach — that's cold-email. +- **copywriting**: For marketing page copy. Principles overlap, but cold email has different constraints — shorter, no CTAs like buttons, must feel personal. +- **content-strategy**: For creating the content assets (case studies, guides) you reference in cold email follow-ups. Good follow-up sequences often link to content. +- **marketing-strategy-pmm**: For positioning and ICP definition. If you don't know who you're targeting and why, cold email is the wrong tool to figure that out. diff --git a/marketing-skill/cold-email/references/deliverability-guide.md b/marketing-skill/cold-email/references/deliverability-guide.md new file mode 100644 index 0000000..81ad12d --- /dev/null +++ b/marketing-skill/cold-email/references/deliverability-guide.md @@ -0,0 +1,225 @@ +# Deliverability Guide + +A cold email that lands in spam is worse than no email at all — it damages your sender reputation for future sends. Get deliverability right before you worry about copy. + +--- + +## The Deliverability Stack + +Email deliverability is a layer cake. Every layer has to be correct: + +``` +Domain reputation (is your domain trusted by inbox providers?) + ↓ +Authentication (SPF, DKIM, DMARC — are you who you say you are?) + ↓ +Sending infrastructure (IP reputation, sending limits, ramp-up) + ↓ +List quality (are you sending to real, active addresses?) + ↓ +Email content (does the content look like spam?) + ↓ +Engagement signals (opens, replies, not-spam clicks) +``` + +Fix problems from the bottom up. No point perfecting copy if your domain is blacklisted. + +--- + +## Domain Setup + +### Use a Dedicated Sending Domain + +Never send cold email from your primary company domain (`acme.com`). If your cold email domain gets flagged or blacklisted, you lose your main domain's email reputation. + +**Setup options:** +- `mail.acme.com` — subdomain of main domain +- `acme-hq.com` — separate domain with similar name +- `getacme.com` / `tryacme.com` — common pattern for SaaS + +**Rules for the sending domain:** +- Set up a proper website (even a simple redirect to main site) — bare domains look suspicious +- Match the company name visually — unrelated domains look like phishing +- Get a G Suite / Microsoft 365 mailbox on it — shared hosting email servers have worse reputation + +### SPF Record + +SPF (Sender Policy Framework) tells receiving servers which IP addresses are allowed to send email from your domain. Without it, your emails look unauthenticated. + +**DNS TXT record:** +``` +v=spf1 include:_spf.google.com ~all +``` + +Replace `_spf.google.com` with your sending provider's SPF include. Check your provider's documentation for the exact value (Google Workspace, SendGrid, Mailgun, etc. all have their own). + +**Important:** Only have ONE SPF record per domain. If you have multiple, they conflict and authentication fails. + +### DKIM + +DKIM (DomainKeys Identified Mail) adds a cryptographic signature to your emails, proving they weren't tampered with in transit. + +Setup is done through your email provider — they give you a DNS TXT record to add. It looks like: + +``` +google._domainkey.yourdomain.com IN TXT "v=DKIM1; k=rsa; p=MIGfMA0..." +``` + +The public key in that record lets receiving servers verify your email's signature. + +### DMARC + +DMARC ties SPF and DKIM together and tells receiving servers what to do when authentication fails. + +**Starter DMARC record (monitoring mode):** +``` +_dmarc.yourdomain.com IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com" +``` + +`p=none` means monitor but don't block — good to start with. Once you've confirmed SPF and DKIM are working cleanly, move to `p=quarantine` or `p=reject`. + +### Verify Everything + +Use **mail-tester.com**: send a test email to their address, then check your score. 9/10 or higher means your authentication is clean. Below 7/10 means something is broken. + +--- + +## Domain Warmup + +A brand new domain has no sending reputation. Email providers don't trust it. If you start sending 200 emails/day on day one, you will be flagged. + +Warmup = building reputation gradually by sending low volumes and getting positive engagement. + +### Warmup Schedule + +| Week | Emails/Day | Focus | +|------|-----------|-------| +| 1 | 5-10 | Real conversations only — send to colleagues, get replies | +| 2 | 20-30 | Small cold outreach batches — highly targeted, good lists | +| 3 | 40-60 | Expand slightly — maintain >30% open rate | +| 4 | 80-100 | Normal volume — watch bounce and spam complaint rates | +| 5+ | Up to 200 | Full volume — monitor daily | + +**Warning signs that warmup is failing:** +- Open rate drops below 20% +- Bounce rate above 3% +- Spam complaint rate above 0.1% +- Emails landing in Gmail Promotions tab + +**Manual warmup vs tools:** Tools like Lemwarm, Warmup Inbox, or Mailreach automate warmup by sending emails to a network of inboxes that automatically open and engage. These help build reputation faster. They're worth it for new domains. + +--- + +## List Quality + +Sending to bad email addresses destroys your sender reputation. Every hard bounce tells inbox providers your list is dirty. + +### Before Sending + +1. **Verify email addresses** — Use a verification tool (NeverBounce, ZeroBounce, Hunter's verify, etc.) before importing any list. Remove invalid, catch-all, and risky emails. + +2. **Target bounce rate:** Keep it below 2%. Above 5% is dangerous territory. + +3. **Remove catch-all domains carefully** — Catch-all domains accept any email regardless of whether the mailbox exists. Your emails won't hard-bounce, but they may go nowhere. + +4. **Never buy lists** — Purchased lists are old, dirty, unverified, and frequently include spam traps (addresses placed by inbox providers to catch spammers). One spam trap hit can blacklist your domain. + +### Ongoing Hygiene + +- Remove anyone who hasn't opened in 90 days from your sequence (move to a re-engagement campaign or suppress) +- Remove unsubscribes immediately — required legally and good for reputation +- Remove bounces from all future sends automatically + +--- + +## Content That Hurts Deliverability + +Spam filters evaluate content alongside authentication and reputation. These patterns trigger filters: + +### Spam Trigger Words to Avoid + +High-risk words and phrases (use sparingly or avoid): +- "Free" (especially in subject lines) +- "Guaranteed" / "100% guaranteed" +- "No obligation" +- "Act now" / "Limited time" +- "Congratulations" +- "You've been selected" +- "Click here" +- "Earn money" / "Make money" +- "Risk-free" +- "Special offer" +- Excessive exclamation points!!! +- ALL CAPS words + +These don't automatically spam-filter you, but they're additive — the more of them in a single email, the higher the spam score. + +### Content Rules + +| Do | Don't | +|----|-------| +| Plain text or minimal HTML | Heavy HTML with complex tables, images | +| One link max per email | 5+ links — looks like phishing or newsletter | +| Personalized subject lines | Batch-blasted "LAST CHANCE" subject lines | +| Unsubscribe link | No unsubscribe mechanism | +| Consistent from name | Rotating from names | +| Short emails | Wall-of-text emails | + +### The HTML Question + +Plain text emails consistently get better deliverability than HTML emails for cold outreach. They look like real emails from real people — because they are. + +If you need to include your company logo and a fancy template: don't. Save that for newsletters to opted-in subscribers. Cold email = plain text, signed like a person. + +--- + +## Sending Limits by Platform + +| Platform | Safe Daily Volume | Notes | +|----------|------------------|-------| +| Google Workspace (paid) | 500/day | Shared across all outgoing | +| Google Workspace + Warmup | Up to 2000/day | After full warmup | +| Microsoft 365 | 10,000/day | Generous, but still subject to reputation | +| SendGrid | Depends on plan | IP reputation matters at scale | +| Mailgun | Depends on plan | Good for transactional, OK for cold | +| Lemlist / Instantly / Apollo | Platform-managed | Warmup built in, use their sending infrastructure | + +For cold outreach at scale (>500/day), dedicated sending platforms are better than Google/Microsoft direct — they're designed to manage reputation across many users. + +--- + +## Checking Your Reputation + +If you suspect deliverability problems, check these: + +1. **Mail-tester.com** — Authentication and content score (10/10 is perfect) +2. **MXToolbox Blacklist Check** — Check if your domain or IP is on any blacklists +3. **Google Postmaster Tools** — Shows your domain reputation with Gmail (spam rate, auth failures) +4. **Microsoft SNDS** — Similar to Google Postmaster for Outlook/Hotmail + +**If you're on a blacklist:** +- Stop sending immediately from that domain +- Identify the cause (bad list, spam complaints, warmup failure) +- Follow the blacklist's delisting process (each has its own) +- Consider using a new domain while the old one recovers + +--- + +## Legal Requirements + +Cold email has legal requirements in most markets. Breaking them isn't just unethical — it's fined. + +| Regulation | Where | Key Requirements | +|-----------|-------|-----------------| +| CAN-SPAM | USA | Honest subject line, physical address, unsubscribe mechanism | +| CASL | Canada | Requires express or implied consent — much stricter than CAN-SPAM | +| GDPR | EU/EEA | Legitimate interest basis required; no soft opt-in | +| PECR | UK | Similar to GDPR; ICO enforcement | + +**Minimum compliance for most cold email:** +- Include your company name and physical address in every email +- Provide a working unsubscribe link or reply-to-unsubscribe instruction +- Honor unsubscribes within 10 business days (CAN-SPAM) or immediately (GDPR best practice) +- Don't use misleading subject lines or from names + +**Disclaimer:** This is practical guidance, not legal advice. For EU/Canada outreach, consult a lawyer who specializes in email marketing law — GDPR and CASL are stricter than most people realize. diff --git a/marketing-skill/cold-email/references/follow-up-playbook.md b/marketing-skill/cold-email/references/follow-up-playbook.md new file mode 100644 index 0000000..915ee64 --- /dev/null +++ b/marketing-skill/cold-email/references/follow-up-playbook.md @@ -0,0 +1,225 @@ +# Follow-Up Playbook + +Full cadence guide, angle rotation, and breakup email templates. The goal: stay persistent without becoming noise. + +--- + +## The Core Problem with Follow-Ups + +Most follow-up emails are a form of wishful thinking: "Maybe they missed it. I'll send it again." They didn't miss it. They read it, didn't feel urgency, and moved on. Another "just checking in" doesn't create urgency — it signals that you have nothing new to offer. + +The only follow-up worth sending is one that adds something: a new angle, a new proof point, a new question, or a new frame. + +--- + +## The Full Cadence + +| Email | Label | Day | Gap | Purpose | +|-------|-------|-----|-----|---------| +| 1 | First touch | Day 1 | — | Lead with their world, establish relevance | +| 2 | New angle | Day 4 | +3 | Different problem angle or social proof | +| 3 | Value add | Day 9 | +5 | Resource, insight, or data point | +| 4 | Direct question | Day 16 | +7 | Cut through with a plain, direct ask | +| 5 | Reverse | Day 25 | +9 | Ask for referral to the right person | +| 6 | Breakup | Day 35 | +10 | Close the loop, leave door open | + +Gaps increase over time. You're persistent but not desperate. + +6 emails is the upper limit for most cold outreach. For very high-value accounts (ABM-style), you might go to 8. For volume prospecting, 4-5 is often more practical. + +--- + +## Email-by-Email Guide + +### Email 1: First Touch +Already covered in `frameworks.md`. The anchor of the sequence. + +**What it needs:** +- Specific, relevant opener +- Clear connection between their situation and what you do +- One ask, low friction + +--- + +### Email 2: New Angle (Day 4) + +This is where most sequences fail — they send a "following up" reminder. Don't. + +Email 2 should approach the problem from a different angle than Email 1. If Email 1 was about their hiring signal, Email 2 might be about the operational risk that follows from rapid hiring. Different angle, same direction. + +**Angle options for Email 2:** +- Different pain point in the same domain +- Social proof / customer story that's highly relevant to their context +- An industry trend that makes the problem more urgent +- A specific, relevant statistic you haven't mentioned yet + +**Template structure:** +``` +[New angle or observation — 1-2 sentences] +[Expand on why it matters for their situation — 1-2 sentences] +[Soft CTA — question or invitation] +``` + +**Example:** +> A lot of the teams I talk to at your stage are hitting the same wall: the ramp time on new SDRs has stretched from 3 months to 5+ months because the playbook that worked at 5 reps doesn't scale to 15. +> +> It's not a hiring problem — it's an enablement infrastructure problem that doesn't become visible until you're already in it. +> +> Is that a challenge you're actively working on, or is it on the radar for later? + +--- + +### Email 3: Value Add (Day 9) + +Give something useful before asking again. This builds goodwill and separates you from the other 30 emails in their inbox that only ask. + +**What counts as value:** +- A relevant guide, benchmark report, or template (if you have one) +- A specific insight about their market or competitor landscape +- A practical suggestion based on what you know about their situation +- A useful question that helps them think about their problem differently + +**Template structure:** +``` +[Reference to something specific about them — 1 sentence] +[The value: insight, resource, or useful observation — 2-3 sentences] +[Low-friction CTA: "useful?" or "happy to elaborate" or specific ask] +``` + +**Example:** +> We just published a benchmark of SDR ramp times across 40 SaaS companies by stage — the data is pretty surprising (the fastest don't hire the most experienced reps, they do onboarding completely differently). +> +> Thought of your situation when reviewing it. Happy to share the relevant section if useful — no strings, just might be helpful context for where you're headed. + +--- + +### Email 4: Direct Question (Day 16) + +By Email 4, subtlety has run its course. Sometimes the most effective move is to ask a direct, plain question. No setup, no story. + +This email is short. Often just two or three lines. + +**Options:** +- Ask what's getting in the way +- Ask if your assumption about their problem is wrong +- Ask if the timing just isn't right +- Ask who the right person to talk to is + +**Template structure:** +``` +[One direct question — sometimes that's all this email needs to be] +[Optional: one sentence of context if needed] +[Nothing else] +``` + +**Example:** +> Is SDR ramp time actually a priority for you right now, or is the timing just off? +> +> No judgment either way — just helps me know whether it's worth staying in touch. + +Or even shorter: +> Am I reaching the wrong person here — is there someone else on your team who owns sales enablement? + +--- + +### Email 5: Reverse / Referral (Day 25) + +If you haven't reached the right person, this email shifts to asking for the referral. If you have reached the right person but they haven't replied, the referral ask sometimes unlocks a conversation because it's a different and lower-commitment request. + +**Template structure:** +``` +[Acknowledge you may not be reaching the right person — 1 sentence] +[Who you're actually looking for — specific role or function — 1 sentence] +[Referral ask — 1 sentence] +``` + +**Example:** +> I might be reaching out to the wrong person — the conversations I typically have are with whoever owns sales onboarding and enablement, which may not be you. +> +> If there's a name you could point me toward, I'd really appreciate it. And if it is you — totally understand if the timing isn't right. + +--- + +### Email 6: Breakup (Day 35) + +The last email. Its job is to close the loop professionally and leave the relationship in a better place than if you'd just gone silent. + +The breakup email often generates the highest reply rate of the entire sequence — people don't like unanswered threads. + +**What makes a good breakup:** +- Signals clearly that this is the last one (without being dramatic about it) +- Leaves the door open — no hard feelings +- Offers one final path to action (reply, referral, or reconnect later) +- Keeps it under 5 sentences + +**Template:** +``` +[Signal this is your last email — 1 sentence] +[Genuine offer to reconnect when timing changes — 1 sentence] +[Referral ask as a final option — 1 sentence] +[Warm close — 1 sentence] +``` + +**Example:** +> I'll stop cluttering your inbox after this one. +> +> If scaling your outbound motion ever becomes a priority, happy to pick this back up — just reply here and I'll be there. +> +> If there's someone else at [Company] who owns this, a name would be genuinely helpful. +> +> Either way, good luck with the Berlin expansion. + +**What to avoid in the breakup:** +- Passive-aggressive tone ("I've tried to reach you several times now...") +- Fake urgency ("This is your last chance to...") +- Asking for feedback on why they didn't reply (annoying, not useful) + +--- + +## Angle Rotation Guide + +Never repeat the same angle twice. Here are enough angles for a full 6-email sequence on any B2B topic: + +| Angle | Description | Example | +|-------|------------|---------| +| Trigger event | The specific reason you reached out | "Saw the funding announcement..." | +| Adjacent pain | A related problem they also likely have | "The challenge after that usually is..." | +| Social proof | Customer story or result | "We helped a team in your situation..." | +| Industry trend | External force making the problem more urgent | "EMEA data residency rules are tightening..." | +| Data/benchmark | A specific number that reframes the problem | "The average ramp time in your segment is 4.2 months..." | +| Counterintuitive insight | Something most people in their role get wrong | "Most teams solve this by hiring more, which makes it worse..." | +| Resource offer | Something genuinely useful, no strings | "We just published a guide on exactly this..." | +| Direct question | Plain, honest ask | "Is this even a priority right now?" | +| Referral ask | Ask for the right person if not them | "Am I talking to the right person here?" | +| Breakup | Close the loop | "I'll stop after this one..." | + +Sequence design tip: never use two heavy asks back to back. Pattern: trigger → social proof → value → direct → referral → breakup works better than ask → ask → ask → ask → ask → breakup. + +--- + +## Short Sequence Variations + +### 3-Email Sequence (High-Volume SDR) +1. Day 1: OPPA framework (trigger + problem + proof + ask) +2. Day 5: Value add (resource, insight, or data point) +3. Day 12: Breakup + +### 4-Email Sequence (Balanced) +1. Day 1: First touch +2. Day 4: New angle / social proof +3. Day 10: Direct question +4. Day 20: Breakup + +### 6-Email Sequence (ABM / High-Value Accounts) +Full sequence as described above. + +--- + +## What Never to Send + +- **"Just following up"** — Adds nothing. Deletes itself. +- **"Did you see my last email?"** — They saw it. This is passive-aggressive. +- **"I wanted to make sure this didn't get lost"** — Patronizing. +- **"I know you're busy but..."** — Everyone's busy. Don't invoke it. +- **A forwarded copy of the original email** — They have the original. This is lazy. +- **Back-to-back emails on the same day** — Unless it's a clear error correction. diff --git a/marketing-skill/cold-email/references/frameworks.md b/marketing-skill/cold-email/references/frameworks.md new file mode 100644 index 0000000..23c7490 --- /dev/null +++ b/marketing-skill/cold-email/references/frameworks.md @@ -0,0 +1,217 @@ +# Cold Email Outreach Frameworks + +Three frameworks that work, when to use each, and how to apply them with examples. + +--- + +## How to Use This Guide + +A framework is a structure, not a script. Use it to organize your thinking, then write in your own voice. If an email sounds like it was written from a template, the framework failed. + +Each framework works best in specific situations — the mismatch between framework and context is why most cold emails fall flat. + +--- + +## Framework 1: Observation → Problem → Proof → Ask (OPPA) + +**Best for:** Prospects where you have a specific, real observation (trigger event, signal, public info). This is the most versatile framework and the default for most B2B cold email. + +**What it does:** Starts with something real and specific about them, connects it to a problem they likely have, brings in credibility, and asks a focused question. + +### Structure + +``` +[Observation]: Something specific and true about them right now. +[Problem]: The logical challenge or risk that creates. +[Proof]: One concrete piece of evidence you can solve it. +[Ask]: A single, low-friction question or request. +``` + +### How to Write Each Part + +**Observation** — This must be: +- Specific (not "I see you're in the software industry") +- Recent (not something from 2 years ago) +- Relevant to the problem you're about to raise +- Non-creepy (public info: LinkedIn, press, job postings, tech stack signals) + +Good observations: +- "Saw the announcement that you're opening a Berlin office." +- "Noticed you're hiring 4 SDRs simultaneously — unusual to scale the team that fast." +- "Your last three blog posts have all been about compliance — guessing that's a pressure point right now." + +**Problem** — This should feel like something they already know is true, not something you're trying to convince them of. + +- āŒ "Companies like yours struggle with X." +- āœ… "That scale-up usually surfaces a bunch of process gaps that are invisible when you're smaller." + +**Proof** — Keep it tight. One result, one customer name (if allowed), or one specific claim. Not a list. + +- āŒ "We work with 300+ companies and have won 7 awards." +- āœ… "We helped a similar-sized team in fintech cut SDR ramp time by 40% in the first quarter." + +**Ask** — One ask. Low friction. Makes it easy to say yes or no. + +- āŒ "Would you be open to a 45-minute product walkthrough with our sales team?" +- āœ… "Worth 15 minutes to compare notes on how you're handling this?" + +### Full Example + +**Subject:** your Berlin expansion + +> Congrats on the Berlin announcement — Series B followed by a new market in the same quarter is a big move. +> +> The part that usually bites teams at this stage: the go-to-market motion that worked for your home market rarely translates directly, especially if you're dealing with different buyer personas and a cold pipeline. +> +> We've helped three B2B SaaS teams with exactly this transition — the fastest got pipeline moving in Germany within 90 days. Happy to share what worked. +> +> Worth a 20-minute call to compare notes? + +--- + +## Framework 2: Question → Value → Ask (QVA) + +**Best for:** Situations where you don't have a strong trigger event, but you understand the prospect's world well enough to lead with a sharp insight or question. Good for segmented outreach to a persona with a known, common pain. + +**What it does:** Opens with a question that creates cognitive engagement — they can't help but answer it in their head. Then delivers value before asking for anything. + +### Structure + +``` +[Question]: A question they're probably already asking themselves. +[Value]: An insight, reframe, or resource that helps them — before they've agreed to anything. +[Ask]: Low-friction request to continue the conversation. +``` + +### How to Write Each Part + +**Question** — Not a rhetorical sales question ("Are you struggling with X?"). An actual, thoughtful question they'd ask at a team meeting. + +- āŒ "Are you struggling to hit your pipeline targets?" +- āœ… "What's your current approach to EMEA expansion — inside sales, channel, or hybrid?" + +The question works because it's specific enough that only a relevant person can answer it, and answering it in their head pulls them into the email. + +**Value** — Give something before asking for anything. This is the differentiator. Options: +- A useful insight from your experience working in their space +- A specific data point or benchmark they probably don't have +- A framework or reframe that's genuinely useful +- A short, actionable observation about their situation + +This doesn't need to be long. Two sentences of genuine value beats two paragraphs of soft selling. + +**Ask** — Same rules as OPPA. One ask, low friction, specific. + +### Full Example + +**Subject:** EMEA expansion approach + +> Quick question — are you planning to open EMEA with a field sales team, or running it remotely from the US for the first 12 months? +> +> I ask because we've seen both approaches play out across about 30 SaaS companies doing this move, and the one that consistently underperforms is the "remote first, hire local later" model — not because of the sales motion, but because of the support/onboarding gap that follows when you close enterprise deals in a timezone you don't cover. +> +> Happy to share a quick breakdown of what the fastest-scaling teams do differently if that's useful. 15 minutes? + +--- + +## Framework 3: Trigger → Insight → Ask (TIA) + +**Best for:** When you have a very specific, time-sensitive trigger event and want to move fast. Great for sales teams with intent signals, tech stack changes, funding news, leadership changes, or industry regulatory shifts. + +**What it does:** Names the trigger directly, provides a non-obvious insight about what that trigger means, and asks a focused question while the timing is relevant. + +### Structure + +``` +[Trigger]: Name the specific event/signal you observed. +[Insight]: Something non-obvious about what that trigger typically means/leads to. +[Ask]: Direct, time-aware request. +``` + +### How to Write Each Part + +**Trigger** — Be specific and direct. Don't be coy about why you're reaching out. + +- āŒ "I was browsing LinkedIn and happened to notice..." +- āœ… "Saw the funding announcement this morning." + +**Insight** — The non-obvious part is what separates this from lazy trigger-based outreach. You're not just saying "congrats on the funding" — you're showing you understand what that trigger means operationally. + +Pattern: "That usually means [specific operational challenge] that most [their role] underestimate." + +- āŒ "Congrats! We'd love to help you grow." +- āœ… "Series A typically means the first real pressure to build repeatable pipeline — and most companies at this stage haven't yet figured out which channels actually scale." + +**Ask** — Frame the timing as genuine, not manufactured urgency. + +- āŒ "Act now before it's too late!" +- āœ… "First 60 days post-funding is when this gets set up or doesn't — worth a quick call?" + +### Full Example + +**Subject:** post-Series A pipeline + +> Saw the Series A close — congrats. +> +> The next 90 days are when pipeline architecture either gets built properly or gets bolted together in a way that causes problems at Series B. Most founders don't realize until 18 months later that they're paying for shortcuts made now. +> +> We work specifically with post-Series A B2B SaaS teams setting up their outbound motion for the first time. Happy to do a no-strings 20-minute call on what works and what doesn't at your stage. +> +> Useful? + +--- + +## Choosing the Right Framework + +| Situation | Use | +|-----------|-----| +| Strong trigger event (funding, hiring, news, tech change) | TIA | +| Good persona understanding, no specific trigger | QVA | +| Mix of trigger + problem knowledge | OPPA | +| Referral or warm intro context | OPPA with referral opener | +| Re-engaging a past prospect | QVA with callback to previous context | + +## Combining Frameworks + +These frameworks aren't rigid. In practice, the best emails blend elements: +- TIA trigger + OPPA proof +- QVA question + TIA timing +- OPPA observation + QVA value + +What you can't blend: two questions, two proof points, or two asks. One of each, always. + +--- + +## Subject Line Frameworks + +Subject lines have their own logic — separate from the email body. + +### The Blank Subject +Two or three words, no capitalization, feels like an internal message. +- `quick question` +- `cold outreach` +- `your q3 pipeline` + +### The Named Trigger +Specific enough to signal you did research, vague enough to create curiosity. +- `your Series A` +- `Berlin office` +- `your ATS stack` + +### The Shared Context +Implies a pre-existing relationship or shared frame. +- `re: EMEA expansion` +- `following up on the hiring spike` + +### The Named Person (Referral) +Only use if the referral is real — never fake this. +- `[Mutual Name] suggested I reach out` +- `[Name] mentioned you're building out your SDR team` + +### Never Use +- `Quick question about your [product category] strategy!` +- `Revolutionize your [function] with [product name]` +- `[FIRST NAME], we have a special offer for you` +- Emojis +- ALL CAPS +- Question marks (feels like an ad) diff --git a/marketing-skill/cold-email/scripts/email_sequence_analyzer.py b/marketing-skill/cold-email/scripts/email_sequence_analyzer.py new file mode 100644 index 0000000..7717a6c --- /dev/null +++ b/marketing-skill/cold-email/scripts/email_sequence_analyzer.py @@ -0,0 +1,504 @@ +#!/usr/bin/env python3 +""" +email_sequence_analyzer.py — Analyzes a cold email sequence for quality signals. + +Evaluates each email on: + - Word count (shorter is usually better for cold email) + - Reading level estimate (Flesch-Kincaid approximation via avg sentence/word length) + - Personalization density (signals of specific, targeted writing) + - CTA clarity (is there a clear ask?) + - Spam trigger words (words that hurt deliverability) + - Subject line analysis (length, warning patterns) + - Overall score: 0-100 + +Usage: + python3 email_sequence_analyzer.py [sequence.json] + cat sequence.json | python3 email_sequence_analyzer.py + +If no file provided, runs on embedded sample sequence. + +Input format (JSON): + [ + { + "email": 1, + "subject": "...", + "body": "..." + }, + ... + ] + +Stdlib only — no external dependencies. +""" + +import json +import re +import sys +import math +import select +from typing import List, Dict, Any + + +# ─── Spam trigger words ─────────────────────────────────────────────────────── + +SPAM_TRIGGERS = [ + "free", "guaranteed", "no obligation", "act now", "limited time", + "click here", "earn money", "make money", "risk-free", "special offer", + "no cost", "winner", "congratulations", "you've been selected", + "once in a lifetime", "urgent", "don't miss out", "buy now", + "order now", "100%", "best price", "lowest price", "incredible deal", + "amazing offer", "cash bonus", "extra cash", "fast cash", + "you have been chosen", "exclusive deal", "as seen on", + "dear friend", "valued customer", +] + +# ─── Personalization signals ────────────────────────────────────────────────── + +PERSONALIZATION_SIGNALS = [ + # Direct references to "you" + r'\byou(?:r|rs|\'re|\'ve|\'d|\'ll)?\b', + # Trigger references + r'\b(?:saw|noticed|read|heard|saw|found|noted)\b', + # Named observation patterns + r'\b(?:your team|your company|your role|your work|your recent|your post)\b', + # Industry/role-specific references + r'\b(?:as a|in your|at your|given your)\b', + # Specific numbers or facts + r'\b\d{4}\b', # years — often a sign of specific research + r'\$\d+|\d+%', # numbers with $ or % +] + +# ─── Dead opener phrases ────────────────────────────────────────────────────── + +DEAD_OPENERS = [ + "i hope this email finds you well", + "i hope this finds you", + "i wanted to reach out", + "i am reaching out", + "my name is", + "i'm writing to", + "i am writing to", + "hope you're doing well", + "i hope you are doing well", + "just following up", + "just checking in", + "circling back", + "touching base", + "per my last email", + "as per my previous", +] + +# ─── Weak CTA patterns ──────────────────────────────────────────────────────── + +WEAK_CTA = [ + "let me know if you're interested", + "let me know if you would be interested", + "feel free to", + "please don't hesitate", + "if you have any questions", + "looking forward to hearing from you", + "i look forward to connecting", + "hope we can connect", +] + +# ─── Strong CTA signals ─────────────────────────────────────────────────────── + +STRONG_CTA_PATTERNS = [ + r'\b(?:15|20|30|45|60)[\s-]?minute\b', # time-specific meeting ask + r'\b(?:call|chat|talk|speak|connect|meet)\b.*\?', # question + meeting word + r'worth\s+(?:a|an)\b', # "worth a call?" + r'\?$', # ends with question + r'\buseful\b\s*\?', # "useful?" + r'\b(?:reply|respond)\b', # explicit reply ask +] + + +# ─── Text utilities ─────────────────────────────────────────────────────────── + +def count_words(text: str) -> int: + return len(text.split()) + + +def count_sentences(text: str) -> int: + """Rough sentence count by terminal punctuation.""" + sentences = re.split(r'[.!?]+', text) + return max(1, len([s for s in sentences if s.strip()])) + + +def avg_words_per_sentence(text: str) -> float: + words = count_words(text) + sentences = count_sentences(text) + return words / sentences if sentences else words + + +def avg_chars_per_word(text: str) -> float: + words = text.split() + if not words: + return 0 + return sum(len(w.strip('.,!?;:')) for w in words) / len(words) + + +def flesch_reading_ease(text: str) -> float: + """ + Approximate Flesch Reading Ease score. + 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words) + We approximate syllables as: max(1, len(word) * 0.4) for each word. + """ + words = text.split() + if not words: + return 0 + sentences = count_sentences(text) + syllables = sum(max(1, int(len(re.sub(r'[^aeiouAEIOU]', '', w)) * 1.2) or 1) for w in words) + asl = len(words) / sentences # avg sentence length + asw = syllables / len(words) # avg syllables per word + score = 206.835 - (1.015 * asl) - (84.6 * asw) + return max(0, min(100, score)) + + +def grade_reading_level(fre_score: float) -> str: + """Convert Flesch Reading Ease to a human label.""" + if fre_score >= 70: + return "Easy (conversational)" + if fre_score >= 60: + return "Plain English" + if fre_score >= 50: + return "Fairly difficult" + return "Difficult (too complex for cold email)" + + +# ─── Analysis functions ─────────────────────────────────────────────────────── + +def analyze_subject_line(subject: str) -> Dict: + issues = [] + warnings = [] + + if not subject: + return {"length": 0, "issues": ["No subject line provided"], "score": 0} + + length = len(subject) + + if length > 60: + issues.append(f"Too long ({length} chars) — aim for under 50") + if length > 50: + warnings.append("Subject is getting long — shorter subjects get more opens") + + if subject.isupper(): + issues.append("All caps subject lines trigger spam filters") + + if re.search(r'!!!|!{2,}', subject): + issues.append("Multiple exclamation points look like spam") + + if subject.startswith("Re:") or subject.startswith("Fwd:"): + lower = subject.lower() + if lower.startswith("re:") or lower.startswith("fwd:"): + warnings.append("Fake Re:/Fwd: subjects feel deceptive — people have learned this trick") + + if re.search(r'[A-Z]{4,}', subject) and not subject.isupper(): + warnings.append("SHOUTING words in subject lines look like spam") + + if re.search(r'[\U0001F600-\U0001FFFF]', subject): + warnings.append("Emojis in subject lines are polarizing and often spam-filtered for B2B") + + if '?' in subject: + warnings.append("Question mark in subject can feel like an ad — test without") + + # Spam trigger check in subject + subject_lower = subject.lower() + triggered = [w for w in SPAM_TRIGGERS if w in subject_lower] + if triggered: + issues.append(f"Spam trigger words in subject: {', '.join(triggered)}") + + # Score + score = 100 + score -= len(issues) * 20 + score -= len(warnings) * 10 + score = max(0, min(100, score)) + + return { + "length": length, + "issues": issues, + "warnings": warnings, + "score": score, + } + + +def analyze_body(body: str) -> Dict: + body_lower = body.lower() + findings = [] + deductions = [] + + word_count = count_words(body) + fre = flesch_reading_ease(body) + reading_level = grade_reading_level(fre) + avg_wps = avg_words_per_sentence(body) + + # Word count scoring + if word_count > 200: + deductions.append(("word_count", 15, f"Too long ({word_count} words) — cold emails should be under 150")) + elif word_count > 150: + deductions.append(("word_count", 5, f"Getting long ({word_count} words) — aim for under 150")) + elif word_count < 30: + deductions.append(("word_count", 10, f"Very short ({word_count} words) — may lack enough context")) + + # Sentence length + if avg_wps > 25: + deductions.append(("readability", 10, f"Sentences average {avg_wps:.0f} words — too complex, aim for 15-20")) + + # Dead opener check + for opener in DEAD_OPENERS: + if opener in body_lower: + deductions.append(("opener", 20, f"Dead opener detected: '{opener}' — rewrite the opening")) + break + + # Personalization density + pers_matches = 0 + for pattern in PERSONALIZATION_SIGNALS: + matches = re.findall(pattern, body_lower) + pers_matches += len(matches) + + pers_density = pers_matches / word_count * 100 if word_count else 0 + if pers_density < 5: + deductions.append(("personalization", 10, "Low personalization signals — email may feel generic")) + + # Spam trigger words in body + triggered = [w for w in SPAM_TRIGGERS if w in body_lower] + if triggered: + deductions.append(("spam", len(triggered) * 5, f"Spam trigger words: {', '.join(triggered[:5])}")) + + # Weak CTA check + for weak in WEAK_CTA: + if weak in body_lower: + deductions.append(("cta", 10, f"Weak CTA: '{weak}' — be more direct")) + break + + # Strong CTA check + has_strong_cta = any(re.search(p, body_lower) for p in STRONG_CTA_PATTERNS) + if not has_strong_cta: + deductions.append(("cta", 15, "No clear CTA detected — every cold email needs a single, direct ask")) + + # HTML check + if re.search(r' 2: + deductions.append(("links", 10, f"{len(links)} links detected — keep to 1-2 max for cold email")) + + # Calculate score + total_deduction = sum(d[1] for d in deductions) + score = max(0, min(100, 100 - total_deduction)) + + return { + "word_count": word_count, + "reading_ease_score": round(fre, 1), + "reading_level": reading_level, + "avg_words_per_sentence": round(avg_wps, 1), + "personalization_density": round(pers_density, 1), + "has_strong_cta": has_strong_cta, + "spam_triggers": triggered, + "deductions": [(d[2], d[1]) for d in deductions], + "score": score, + } + + +# ─── Report printer ─────────────────────────────────────────────────────────── + +def grade(score: int) -> str: + if score >= 85: + return "🟢 Strong" + if score >= 65: + return "🟔 Decent" + if score >= 45: + return "🟠 Needs work" + return "šŸ”“ Rewrite" + + +def print_report(results: List[Dict]) -> None: + print("\n" + "═" * 64) + print(" COLD EMAIL SEQUENCE ANALYSIS") + print("═" * 64) + + scores = [] + for r in results: + email_num = r["email"] + subj = r["subject_analysis"] + body = r["body_analysis"] + overall = r["overall_score"] + scores.append(overall) + + print(f"\n── Email {email_num}: \"{r['subject']}\" ──") + print(f" Overall: {overall}/100 {grade(overall)}") + + print(f"\n Subject ({subj['length']} chars): {subj['score']}/100") + for issue in subj.get("issues", []): + print(f" āŒ {issue}") + for warn in subj.get("warnings", []): + print(f" āš ļø {warn}") + + print(f"\n Body Analysis:") + print(f" Words: {body['word_count']} | " + f"Reading: {body['reading_level']} | " + f"Avg sentence: {body['avg_words_per_sentence']} words | " + f"Personalization density: {body['personalization_density']}%") + print(f" CTA: {'āœ… Clear ask detected' if body['has_strong_cta'] else 'āŒ No clear CTA found'}") + + if body.get("spam_triggers"): + print(f" āš ļø Spam triggers: {', '.join(body['spam_triggers'])}") + + if body.get("deductions"): + print(f"\n Issues found:") + for desc, pts in body["deductions"]: + print(f" [-{pts:2d}] {desc}") + + avg = sum(scores) // len(scores) if scores else 0 + print(f"\n{'═' * 64}") + print(f" SEQUENCE OVERALL: {avg}/100 {grade(avg)}") + print(f" Emails analyzed: {len(results)}") + + # Sequence-level observations + print("\n Sequence observations:") + word_counts = [r["body_analysis"]["word_count"] for r in results] + if all(abs(word_counts[i] - word_counts[i-1]) < 20 for i in range(1, len(word_counts))): + print(" āš ļø All emails are similar length — vary length across sequence") + + if len(results) > 1: + last_body = results[-1]["body_analysis"] + if last_body["word_count"] > 100: + print(" āš ļø Final email (breakup) should be shorter — 3-5 sentences max") + + print("═" * 64 + "\n") + + +# ─── Sample data ────────────────────────────────────────────────────────────── + +SAMPLE_SEQUENCE = [ + { + "email": 1, + "subject": "your SDR team expansion", + "body": ( + "Saw you're hiring four SDRs simultaneously — that's a significant scale-up.\n\n" + "The challenge most teams hit at this stage isn't recruiting — it's ramp time. " + "When you're adding four people at once, the gaps in your onboarding process " + "become very expensive very fast. The average ramp in your segment is around " + "4.5 months; the fastest teams we've seen get it to 2.5.\n\n" + "We've helped three similar-sized SaaS teams compress that gap. Happy to share " + "what worked if it's useful.\n\n" + "Worth 15 minutes to compare notes?" + ), + }, + { + "email": 2, + "subject": "re: your onboarding stack", + "body": ( + "I hope this email finds you well. I wanted to follow up on my previous email.\n\n" + "Just checking in to see if you had a chance to review what I sent. " + "As mentioned, our platform offers a comprehensive suite of tools designed to " + "help sales teams of all sizes achieve unprecedented growth through our " + "revolutionary AI-powered onboarding solution.\n\n" + "I'd love to schedule a 45-minute product demo at your earliest convenience. " + "Please don't hesitate to reach out if you have any questions. " + "I look forward to hearing from you!\n\n" + "Click here to book a time: https://calendly.com/example" + ), + }, + { + "email": 3, + "subject": "SDR ramp benchmark", + "body": ( + "One data point that might be useful: across the 40 SaaS teams we've benchmarked, " + "the ones with the fastest SDR ramp time don't hire the most experienced reps — " + "they invest more heavily in structured onboarding in the first 30 days.\n\n" + "Happy to share the full breakdown. No catch — just thought it might be relevant " + "given where you're headed.\n\n" + "Useful?" + ), + }, + { + "email": 4, + "subject": "quick question", + "body": ( + "Is SDR onboarding actually a priority right now, or is the timing just off?\n\n" + "No judgment either way — just helps me know whether it's worth staying in touch." + ), + }, + { + "email": 5, + "subject": "last one", + "body": ( + "I'll stop cluttering your inbox after this one.\n\n" + "If scaling your SDR ramp time ever becomes a priority, happy to reconnect — " + "just reply here.\n\n" + "If there's someone else at your company who owns sales enablement, " + "a name would go a long way.\n\n" + "Either way, good luck with the expansion." + ), + }, +] + + +# ─── Main ───────────────────────────────────────────────────────────────────── + +def main(): + if len(sys.argv) > 1: + arg = sys.argv[1] + if arg == "-": + sequence = json.load(sys.stdin) + else: + try: + with open(arg, "r", encoding="utf-8") as f: + sequence = json.load(f) + except FileNotFoundError: + print(f"Error: File not found: {arg}", file=sys.stderr) + sys.exit(1) + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON: {e}", file=sys.stderr) + sys.exit(1) + else: + print("No file provided — running on embedded sample sequence.\n") + sequence = SAMPLE_SEQUENCE + + results = [] + for email in sequence: + subject = email.get("subject", "") + body = email.get("body", "") + email_num = email.get("email", len(results) + 1) + + subject_analysis = analyze_subject_line(subject) + body_analysis = analyze_body(body) + + # Overall score: 30% subject, 70% body + overall = int(subject_analysis["score"] * 0.3 + body_analysis["score"] * 0.7) + + results.append({ + "email": email_num, + "subject": subject, + "subject_analysis": subject_analysis, + "body_analysis": body_analysis, + "overall_score": overall, + }) + + print_report(results) + + # JSON output for programmatic use + summary = { + "emails_analyzed": len(results), + "average_score": sum(r["overall_score"] for r in results) // len(results) if results else 0, + "results": [ + { + "email": r["email"], + "subject": r["subject"], + "score": r["overall_score"], + "word_count": r["body_analysis"]["word_count"], + "has_strong_cta": r["body_analysis"]["has_strong_cta"], + "spam_triggers": r["body_analysis"]["spam_triggers"], + "subject_score": r["subject_analysis"]["score"], + } + for r in results + ], + } + print("── JSON Output ──") + print(json.dumps(summary, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/competitor-alternatives/SKILL.md b/marketing-skill/competitor-alternatives/SKILL.md new file mode 100644 index 0000000..31f3cd3 --- /dev/null +++ b/marketing-skill/competitor-alternatives/SKILL.md @@ -0,0 +1,290 @@ +--- +name: competitor-alternatives +description: "When the user wants to create competitor comparison or alternative pages for SEO and sales enablement. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'switch from competitor,' or 'comparison content.' Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. Emphasizes deep research, modular content architecture, and varied section types beyond feature tables." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Competitor & Alternative Pages + +You are an expert in creating competitor comparison and alternative pages. Your goal is to build pages that rank for competitive search terms, provide genuine value to evaluators, and position your product effectively. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before creating competitor pages, understand: + +1. **Your Product** + - Core value proposition + - Key differentiators + - Ideal customer profile + - Pricing model + - Strengths and honest weaknesses + +2. **Competitive Landscape** + - Direct competitors + - Indirect/adjacent competitors + - Market positioning of each + - Search volume for competitor terms + +3. **Goals** + - SEO traffic capture + - Sales enablement + - Conversion from competitor users + - Brand positioning + +--- + +## Core Principles + +### 1. Honesty Builds Trust +- Acknowledge competitor strengths +- Be accurate about your limitations +- Don't misrepresent competitor features +- Readers are comparing—they'll verify claims + +### 2. Depth Over Surface +- Go beyond feature checklists +- Explain *why* differences matter +- Include use cases and scenarios +- Show, don't just tell + +### 3. Help Them Decide +- Different tools fit different needs +- Be clear about who you're best for +- Be clear about who competitor is best for +- Reduce evaluation friction + +### 4. Modular Content Architecture +- Competitor data should be centralized +- Updates propagate to all pages +- Single source of truth per competitor + +--- + +## Page Formats + +### Format 1: [Competitor] Alternative (Singular) + +**Search intent**: User is actively looking to switch from a specific competitor + +**URL pattern**: `/alternatives/[competitor]` or `/[competitor]-alternative` + +**Target keywords**: "[Competitor] alternative", "alternative to [Competitor]", "switch from [Competitor]" + +**Page structure**: +1. Why people look for alternatives (validate their pain) +2. Summary: You as the alternative (quick positioning) +3. Detailed comparison (features, service, pricing) +4. Who should switch (and who shouldn't) +5. Migration path +6. Social proof from switchers +7. CTA + +--- + +### Format 2: [Competitor] Alternatives (Plural) + +**Search intent**: User is researching options, earlier in journey + +**URL pattern**: `/alternatives/[competitor]-alternatives` + +**Target keywords**: "[Competitor] alternatives", "best [Competitor] alternatives", "tools like [Competitor]" + +**Page structure**: +1. Why people look for alternatives (common pain points) +2. What to look for in an alternative (criteria framework) +3. List of alternatives (you first, but include real options) +4. Comparison table (summary) +5. Detailed breakdown of each alternative +6. Recommendation by use case +7. CTA + +**Important**: Include 4-7 real alternatives. Being genuinely helpful builds trust and ranks better. + +--- + +### Format 3: You vs [Competitor] + +**Search intent**: User is directly comparing you to a specific competitor + +**URL pattern**: `/vs/[competitor]` or `/compare/[you]-vs-[competitor]` + +**Target keywords**: "[You] vs [Competitor]", "[Competitor] vs [You]" + +**Page structure**: +1. TL;DR summary (key differences in 2-3 sentences) +2. At-a-glance comparison table +3. Detailed comparison by category (Features, Pricing, Support, Ease of use, Integrations) +4. Who [You] is best for +5. Who [Competitor] is best for (be honest) +6. What customers say (testimonials from switchers) +7. Migration support +8. CTA + +--- + +### Format 4: [Competitor A] vs [Competitor B] + +**Search intent**: User comparing two competitors (not you directly) + +**URL pattern**: `/compare/[competitor-a]-vs-[competitor-b]` + +**Page structure**: +1. Overview of both products +2. Comparison by category +3. Who each is best for +4. The third option (introduce yourself) +5. Comparison table (all three) +6. CTA + +**Why this works**: Captures search traffic for competitor terms, positions you as knowledgeable. + +--- + +## Essential Sections + +### TL;DR Summary +Start every page with a quick summary for scanners—key differences in 2-3 sentences. + +### Paragraph Comparisons +Go beyond tables. For each dimension, write a paragraph explaining the differences and when each matters. + +### Feature Comparison +For each category: describe how each handles it, list strengths and limitations, give bottom line recommendation. + +### Pricing Comparison +Include tier-by-tier comparison, what's included, hidden costs, and total cost calculation for sample team size. + +### Who It's For +Be explicit about ideal customer for each option. Honest recommendations build trust. + +### Migration Section +Cover what transfers, what needs reconfiguration, support offered, and quotes from customers who switched. + +**For detailed templates**: See [references/templates.md](references/templates.md) + +--- + +## Content Architecture + +### Centralized Competitor Data +Create a single source of truth for each competitor with: +- Positioning and target audience +- Pricing (all tiers) +- Feature ratings +- Strengths and weaknesses +- Best for / not ideal for +- Common complaints (from reviews) +- Migration notes + +**For data structure and examples**: See [references/content-architecture.md](references/content-architecture.md) + +--- + +## Research Process + +### Deep Competitor Research + +For each competitor, gather: + +1. **Product research**: Sign up, use it, document features/UX/limitations +2. **Pricing research**: Current pricing, what's included, hidden costs +3. **Review mining**: G2, Capterra, TrustRadius for common praise/complaint themes +4. **Customer feedback**: Talk to customers who switched (both directions) +5. **Content research**: Their positioning, their comparison pages, their changelog + +### Ongoing Updates + +- **Quarterly**: Verify pricing, check for major feature changes +- **When notified**: Customer mentions competitor change +- **Annually**: Full refresh of all competitor data + +--- + +## SEO Considerations + +### Keyword Targeting + +| Format | Primary Keywords | +|--------|-----------------| +| Alternative (singular) | [Competitor] alternative, alternative to [Competitor] | +| Alternatives (plural) | [Competitor] alternatives, best [Competitor] alternatives | +| You vs Competitor | [You] vs [Competitor], [Competitor] vs [You] | +| Competitor vs Competitor | [A] vs [B], [B] vs [A] | + +### Internal Linking +- Link between related competitor pages +- Link from feature pages to relevant comparisons +- Create hub page linking to all competitor content + +### Schema Markup +Consider FAQ schema for common questions like "What is the best alternative to [Competitor]?" + +--- + +## Output Format + +### Competitor Data File +Complete competitor profile in YAML format for use across all comparison pages. + +### Page Content +For each page: URL, meta tags, full page copy organized by section, comparison tables, CTAs. + +### Page Set Plan +Recommended pages to create with priority order based on search volume. + +--- + +## Task-Specific Questions + +1. What are common reasons people switch to you? +2. Do you have customer quotes about switching? +3. What's your pricing vs. competitors? +4. Do you offer migration support? + +--- + +## Proactive Triggers + +Proactively offer competitor page creation when: + +1. **Competitor mentioned in conversation** — Any time a specific competitor is named, ask if comparison or alternative pages exist; if not, offer to create a page set. +2. **Sales team friction** — User mentions prospects comparing them to a specific tool; immediately offer a vs-page for sales enablement. +3. **SEO gap identified** — Keyword research shows competitor-branded terms with no coverage; propose a full alternative page set with prioritized build order. +4. **Switcher testimonial available** — When a customer quote about switching surfaces, offer to build a migration-focused alternative page around it. +5. **Pricing page review** — When reviewing pricing, note that pricing comparison tables belong on dedicated competitor pages, not the pricing page itself. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Competitor Intelligence File | YAML data file | Centralized competitor profile: pricing, features, weaknesses, review themes | +| Page Set Plan | Prioritized list | Ranked list of pages to build with target keywords and search volume estimates | +| Alternative Page (Singular) | Full page copy | Complete `/[competitor]-alternative` page with all sections | +| Vs Page | Full page copy | Complete `/vs/[competitor]` page with comparison table and CTA | +| Migration Guide Section | Markdown block | Reusable migration copy for inclusion across multiple pages | + +--- + +## Communication + +All competitor page outputs should be factually accurate, legally safe (no false claims), and fair to competitors. Acknowledge genuine competitor strengths — pages that only disparage competitors lose credibility with evaluators. Reference `marketing-context` for ICP and positioning before writing any comparison copy. Quality bar: every claim must be verifiable from public sources or customer quotes. + +--- + +## Related Skills + +- **seo-audit** — USE to validate that competitor pages meet on-page SEO requirements before publishing; NOT as a replacement for the keyword strategy built here. +- **copywriting** — USE for writing the narrative sections and CTAs on comparison pages; NOT when the task is purely competitor research and architecture. +- **content-strategy** — USE when planning a full competitive content program across multiple pages; NOT for single-page execution. +- **competitive-intel** — USE when C-level strategic competitive analysis is needed beyond page creation; NOT for tactical page writing. +- **marketing-context** — USE as foundation before any competitor page work to align positioning; always load first. diff --git a/marketing-skill/competitor-alternatives/references/content-architecture.md b/marketing-skill/competitor-alternatives/references/content-architecture.md new file mode 100644 index 0000000..95e84d4 --- /dev/null +++ b/marketing-skill/competitor-alternatives/references/content-architecture.md @@ -0,0 +1,263 @@ +# Content Architecture for Competitor Pages + +How to structure and maintain competitor data for scalable comparison pages. + +## Centralized Competitor Data + +Create a single source of truth for each competitor: + +``` +competitor_data/ +ā”œā”€ā”€ notion.md +ā”œā”€ā”€ airtable.md +ā”œā”€ā”€ monday.md +└── ... +``` + +--- + +## Competitor Data Template + +Per competitor, document: + +```yaml +name: Notion +website: notion.so +tagline: "The all-in-one workspace" +founded: 2016 +headquarters: San Francisco + +# Positioning +primary_use_case: "docs + light databases" +target_audience: "teams wanting flexible workspace" +market_position: "premium, feature-rich" + +# Pricing +pricing_model: per-seat +free_tier: true +free_tier_limits: "limited blocks, 1 user" +starter_price: $8/user/month +business_price: $15/user/month +enterprise: custom + +# Features (rate 1-5 or describe) +features: + documents: 5 + databases: 4 + project_management: 3 + collaboration: 4 + integrations: 3 + mobile_app: 3 + offline_mode: 2 + api: 4 + +# Strengths (be honest) +strengths: + - Extremely flexible and customizable + - Beautiful, modern interface + - Strong template ecosystem + - Active community + +# Weaknesses (be fair) +weaknesses: + - Can be slow with large databases + - Learning curve for advanced features + - Limited automations compared to dedicated tools + - Offline mode is limited + +# Best for +best_for: + - Teams wanting all-in-one workspace + - Content-heavy workflows + - Documentation-first teams + - Startups and small teams + +# Not ideal for +not_ideal_for: + - Complex project management needs + - Large databases (1000s of rows) + - Teams needing robust offline + - Enterprise with strict compliance + +# Common complaints (from reviews) +common_complaints: + - "Gets slow with lots of content" + - "Hard to find things as workspace grows" + - "Mobile app is clunky" + +# Migration notes +migration_from: + difficulty: medium + data_export: "Markdown, CSV, HTML" + what_transfers: "Pages, databases" + what_doesnt: "Automations, integrations setup" + time_estimate: "1-3 days for small team" +``` + +--- + +## Your Product Data + +Same structure for yourself—be honest: + +```yaml +name: [Your Product] +# ... same fields + +strengths: + - [Your real strengths] + +weaknesses: + - [Your honest weaknesses] + +best_for: + - [Your ideal customers] + +not_ideal_for: + - [Who should use something else] +``` + +--- + +## Page Generation + +Each page pulls from centralized data: + +- **[Competitor] Alternative page**: Pulls competitor data + your data +- **[Competitor] Alternatives page**: Pulls competitor data + your data + other alternatives +- **You vs [Competitor] page**: Pulls your data + competitor data +- **[A] vs [B] page**: Pulls both competitor data + your data + +**Benefits**: +- Update competitor pricing once, updates everywhere +- Add new feature comparison once, appears on all pages +- Consistent accuracy across pages +- Easier to maintain at scale + +--- + +## Index Page Structure + +### Alternatives Index + +**URL**: `/alternatives` or `/alternatives/index` + +**Purpose**: Lists all "[Competitor] Alternative" pages + +**Page structure**: +1. Headline: "[Your Product] as an Alternative" +2. Brief intro on why people switch to you +3. List of all alternative pages with: + - Competitor name/logo + - One-line summary of key differentiator vs. that competitor + - Link to full comparison +4. Common reasons people switch (aggregated) +5. CTA + +**Example**: +```markdown +## Explore [Your Product] as an Alternative + +Looking to switch? See how [Your Product] compares to the tools you're evaluating: + +- **[Notion Alternative](/alternatives/notion)** — Better for teams who need [X] +- **[Airtable Alternative](/alternatives/airtable)** — Better for teams who need [Y] +- **[Monday Alternative](/alternatives/monday)** — Better for teams who need [Z] +``` + +--- + +### Vs Comparisons Index + +**URL**: `/vs` or `/compare` + +**Purpose**: Lists all "You vs [Competitor]" and "[A] vs [B]" pages + +**Page structure**: +1. Headline: "Compare [Your Product]" +2. Section: "[Your Product] vs Competitors" — list of direct comparisons +3. Section: "Head-to-Head Comparisons" — list of [A] vs [B] pages +4. Brief methodology note +5. CTA + +--- + +### Index Page Best Practices + +**Keep them updated**: When you add a new comparison page, add it to the relevant index. + +**Internal linking**: +- Link from index → individual pages +- Link from individual pages → back to index +- Cross-link between related comparisons + +**SEO value**: +- Index pages can rank for broad terms like "project management tool comparisons" +- Pass link equity to individual comparison pages +- Help search engines discover all comparison content + +**Sorting options**: +- By popularity (search volume) +- Alphabetically +- By category/use case +- By date added (show freshness) + +**Include on index pages**: +- Last updated date for credibility +- Number of pages/comparisons available +- Quick filters if you have many comparisons + +--- + +## Footer Navigation + +The site footer appears on all marketing pages, making it a powerful internal linking opportunity for competitor pages. + +### Option 1: Link to Index Pages (Minimum) + +At minimum, add links to your comparison index pages in the footer: + +``` +Footer +ā”œā”€ā”€ Compare +│ ā”œā”€ā”€ Alternatives → /alternatives +│ └── Comparisons → /vs +``` + +This ensures every marketing page passes link equity to your comparison content hub. + +### Option 2: Footer Columns by Format (Recommended for SEO) + +For stronger internal linking, create dedicated footer columns for each format you've built, linking directly to your top competitors: + +``` +Footer +ā”œā”€ā”€ [Product] vs ā”œā”€ā”€ Alternatives to ā”œā”€ā”€ Compare +│ ā”œā”€ā”€ vs Notion │ ā”œā”€ā”€ Notion Alternative │ ā”œā”€ā”€ Notion vs Airtable +│ ā”œā”€ā”€ vs Airtable │ ā”œā”€ā”€ Airtable Alternative │ ā”œā”€ā”€ Monday vs Asana +│ ā”œā”€ā”€ vs Monday │ ā”œā”€ā”€ Monday Alternative │ ā”œā”€ā”€ Notion vs Monday +│ ā”œā”€ā”€ vs Asana │ ā”œā”€ā”€ Asana Alternative │ ā”œā”€ā”€ ... +│ ā”œā”€ā”€ vs Clickup │ ā”œā”€ā”€ Clickup Alternative │ └── View all → +│ ā”œā”€ā”€ ... │ ā”œā”€ā”€ ... │ +│ └── View all → │ └── View all → │ +``` + +**Guidelines**: +- Include up to 8 links per column (top competitors by search volume) +- Add "View all" link to the full index page +- Only create columns for formats you've actually built pages for +- Prioritize competitors with highest search volume + +### Why Footer Links Matter + +1. **Sitewide distribution**: Footer links appear on every marketing page, passing link equity from your entire site to comparison content +2. **Crawl efficiency**: Search engines discover all comparison pages quickly +3. **User discovery**: Visitors evaluating your product can easily find comparisons +4. **Competitive positioning**: Signals to search engines that you're a key player in the space + +### Implementation Notes + +- Update footer when adding new high-priority comparison pages +- Keep footer clean—don't list every comparison, just the top ones +- Match column headers to your URL structure (e.g., "vs" column → `/vs/` URLs) +- Consider mobile: columns may stack, so order by priority diff --git a/marketing-skill/competitor-alternatives/references/templates.md b/marketing-skill/competitor-alternatives/references/templates.md new file mode 100644 index 0000000..8004902 --- /dev/null +++ b/marketing-skill/competitor-alternatives/references/templates.md @@ -0,0 +1,212 @@ +# Section Templates for Competitor Pages + +Ready-to-use templates for each section of competitor comparison pages. + +## TL;DR Summary + +Start every page with a quick summary for scanners: + +```markdown +**TL;DR**: [Competitor] excels at [strength] but struggles with [weakness]. +[Your product] is built for [your focus], offering [key differentiator]. +Choose [Competitor] if [their ideal use case]. Choose [You] if [your ideal use case]. +``` + +--- + +## Paragraph Comparison (Not Just Tables) + +For each major dimension, write a paragraph: + +```markdown +## Features + +[Competitor] offers [description of their feature approach]. +Their strength is [specific strength], which works well for [use case]. +However, [limitation] can be challenging for [user type]. + +[Your product] takes a different approach with [your approach]. +This means [benefit], though [honest tradeoff]. +Teams who [specific need] often find this more effective. +``` + +--- + +## Feature Comparison Section + +Go beyond checkmarks: + +```markdown +## Feature Comparison + +### [Feature Category] + +**[Competitor]**: [2-3 sentence description of how they handle this] +- Strengths: [specific] +- Limitations: [specific] + +**[Your product]**: [2-3 sentence description] +- Strengths: [specific] +- Limitations: [specific] + +**Bottom line**: Choose [Competitor] if [scenario]. Choose [You] if [scenario]. +``` + +--- + +## Pricing Comparison Section + +```markdown +## Pricing + +| | [Competitor] | [Your Product] | +|---|---|---| +| Free tier | [Details] | [Details] | +| Starting price | $X/user/mo | $X/user/mo | +| Business tier | $X/user/mo | $X/user/mo | +| Enterprise | Custom | Custom | + +**What's included**: [Competitor]'s $X plan includes [features], while +[Your product]'s $X plan includes [features]. + +**Total cost consideration**: Beyond per-seat pricing, consider [hidden costs, +add-ons, implementation]. [Competitor] charges extra for [X], while +[Your product] includes [Y] in base pricing. + +**Value comparison**: For a 10-person team, [Competitor] costs approximately +$X/year while [Your product] costs $Y/year, with [key differences in what you get]. +``` + +--- + +## Service & Support Comparison + +```markdown +## Service & Support + +| | [Competitor] | [Your Product] | +|---|---|---| +| Documentation | [Quality assessment] | [Quality assessment] | +| Response time | [SLA if known] | [Your SLA] | +| Support channels | [List] | [List] | +| Onboarding | [What they offer] | [What you offer] | +| CSM included | [At what tier] | [At what tier] | + +**Support quality**: Based on [G2/Capterra reviews, your research], +[Competitor] support is described as [assessment]. Common feedback includes +[quotes or themes]. + +[Your product] offers [your support approach]. [Specific differentiator like +response time, dedicated CSM, implementation help]. +``` + +--- + +## Who It's For Section + +```markdown +## Who Should Choose [Competitor] + +[Competitor] is the right choice if: +- [Specific use case or need] +- [Team type or size] +- [Workflow or requirement] +- [Budget or priority] + +**Ideal [Competitor] customer**: [Persona description in 1-2 sentences] + +## Who Should Choose [Your Product] + +[Your product] is built for teams who: +- [Specific use case or need] +- [Team type or size] +- [Workflow or requirement] +- [Priority or value] + +**Ideal [Your product] customer**: [Persona description in 1-2 sentences] +``` + +--- + +## Migration Section + +```markdown +## Switching from [Competitor] + +### What transfers +- [Data type]: [How easily, any caveats] +- [Data type]: [How easily, any caveats] + +### What needs reconfiguration +- [Thing]: [Why and effort level] +- [Thing]: [Why and effort level] + +### Migration support + +We offer [migration support details]: +- [Free data import tool / white-glove migration] +- [Documentation / migration guide] +- [Timeline expectation] +- [Support during transition] + +### What customers say about switching + +> "[Quote from customer who switched]" +> — [Name], [Role] at [Company] +``` + +--- + +## Social Proof Section + +Focus on switchers: + +```markdown +## What Customers Say + +### Switched from [Competitor] + +> "[Specific quote about why they switched and outcome]" +> — [Name], [Role] at [Company] + +> "[Another quote]" +> — [Name], [Role] at [Company] + +### Results after switching +- [Company] saw [specific result] +- [Company] reduced [metric] by [amount] +``` + +--- + +## Comparison Table Best Practices + +### Beyond Checkmarks + +Instead of: +| Feature | You | Competitor | +|---------|-----|-----------| +| Feature A | āœ“ | āœ“ | +| Feature B | āœ“ | āœ— | + +Do this: +| Feature | You | Competitor | +|---------|-----|-----------| +| Feature A | Full support with [detail] | Basic support, [limitation] | +| Feature B | [Specific capability] | Not available | + +### Organize by Category + +Group features into meaningful categories: +- Core functionality +- Collaboration +- Integrations +- Security & compliance +- Support & service + +### Include Ratings Where Useful + +| Category | You | Competitor | Notes | +|----------|-----|-----------|-------| +| Ease of use | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | [Brief note] | +| Feature depth | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | [Brief note] | diff --git a/marketing-skill/competitor-alternatives/scripts/comparison_matrix_builder.py b/marketing-skill/competitor-alternatives/scripts/comparison_matrix_builder.py new file mode 100644 index 0000000..d7ccfa0 --- /dev/null +++ b/marketing-skill/competitor-alternatives/scripts/comparison_matrix_builder.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +""" +comparison_matrix_builder.py — Competitive Feature Comparison Matrix Builder +100% stdlib, no pip installs required. + +Usage: + python3 comparison_matrix_builder.py # demo mode + python3 comparison_matrix_builder.py --input matrix.json + python3 comparison_matrix_builder.py --input matrix.json --json + python3 comparison_matrix_builder.py --input matrix.json --markdown > comparison.md + +matrix.json format: + { + "your_product": "YourProduct", + "features": [ + { + "name": "SSO / SAML", + "category": "Security", + "your_status": "full", # full | partial | no | planned + "competitors": { + "CompetitorA": "no", + "CompetitorB": "partial", + "CompetitorC": "full" + }, + "notes": "Enterprise tier only" # optional + } + ] + } +""" + +import argparse +import json +import sys +from collections import defaultdict + + +# --------------------------------------------------------------------------- +# Status helpers +# --------------------------------------------------------------------------- + +STATUS_SCORE = { + "full": 2, + "partial": 1, + "no": 0, + "planned": 0, # planned ≠ shipped; conservative scoring +} + +STATUS_LABEL = { + "full": "āœ…", + "partial": "šŸ”¶", + "no": "āŒ", + "planned": "šŸ—“", +} + +STATUS_TEXT = { + "full": "Full", + "partial": "Partial", + "no": "No", + "planned": "Planned", +} + +FEATURE_IMPORTANCE = { + # Generic defaults — override per-feature with "weight" in JSON + "default": 1, +} + + +# --------------------------------------------------------------------------- +# Core builder +# --------------------------------------------------------------------------- + +def normalise_status(s: str) -> str: + s = (s or "no").strip().lower() + return s if s in STATUS_SCORE else "no" + + +def build_matrix(data: dict) -> dict: + your_product = data.get("your_product", "Your Product") + features = data.get("features", []) + + if not features: + raise ValueError("No features provided in input.") + + # Collect competitor names (ordered, deduplicated) + competitors = [] + seen = set() + for f in features: + for c in f.get("competitors", {}): + if c not in seen: + competitors.append(c) + seen.add(c) + + categories = sorted(set(f.get("category", "General") for f in features)) + + # --- per-feature analysis --- + feature_rows = [] + for f in features: + fname = f.get("name", "?") + category = f.get("category", "General") + weight = f.get("weight", 1) + your_raw = normalise_status(f.get("your_status", "no")) + your_s = STATUS_SCORE[your_raw] + comp_raw = {c: normalise_status(f.get("competitors", {}).get(c, "no")) + for c in competitors} + comp_s = {c: STATUS_SCORE[comp_raw[c]] for c in competitors} + + you_win = all(your_s > comp_s[c] for c in competitors) if competitors else False + you_lose = any(your_s < comp_s[c] for c in competitors) + your_max = max(comp_s.values()) if comp_s else 0 + advantage = your_s - your_max # positive = you're better overall + + feature_rows.append({ + "name": fname, + "category": category, + "weight": weight, + "your_status": your_raw, + "your_score": your_s, + "competitors": comp_raw, + "comp_scores": comp_s, + "you_win": you_win, + "you_lose": you_lose, + "advantage": advantage, + "notes": f.get("notes", ""), + }) + + # --- competitive scores per competitor --- + comp_scores = {} + for c in competitors: + wins = sum(1 for r in feature_rows if r["your_score"] > r["comp_scores"].get(c, 0)) + ties = sum(1 for r in feature_rows if r["your_score"] == r["comp_scores"].get(c, 0)) + losses = sum(1 for r in feature_rows if r["your_score"] < r["comp_scores"].get(c, 0)) + total = len(feature_rows) + score = round((wins / total) * 100) if total else 0 + comp_scores[c] = { + "wins": wins, "ties": ties, "losses": losses, + "win_pct": score, + "verdict": _verdict(score), + } + + # Overall competitive score (average win% across all competitors) + overall_win_pct = ( + round(sum(v["win_pct"] for v in comp_scores.values()) / len(comp_scores)) + if comp_scores else 0 + ) + + # Advantages and gaps + advantages = [r["name"] for r in feature_rows if r["advantage"] > 0] + gaps = [r["name"] for r in feature_rows if r["advantage"] < 0] + parity = [r["name"] for r in feature_rows if r["advantage"] == 0] + + return { + "meta": { + "your_product": your_product, + "competitors": competitors, + "categories": categories, + "total_features": len(feature_rows), + "overall_win_pct": overall_win_pct, + "verdict": _verdict(overall_win_pct), + }, + "competitor_scores": comp_scores, + "advantages": advantages, + "gaps": gaps, + "parity": parity, + "features": feature_rows, + } + + +def _verdict(win_pct: int) -> str: + if win_pct >= 70: return "Strong advantage" + if win_pct >= 50: return "Slight advantage" + if win_pct >= 35: return "Competitive parity" + return "Trailing" + + +# --------------------------------------------------------------------------- +# Markdown output +# --------------------------------------------------------------------------- + +def build_markdown(result: dict) -> str: + m = result["meta"] + rows = result["features"] + comp = m["competitors"] + + lines = [] + lines.append(f"# Feature Comparison: {m['your_product']} vs Competitors\n") + lines.append(f"_Generated by comparison_matrix_builder.py — {m['total_features']} features, " + f"{len(comp)} competitor(s)_\n") + + # Summary table + lines.append("## Competitive Score Summary\n") + lines.append("| Competitor | You Win | Tie | You Lose | Win % | Verdict |") + lines.append("|---|---|---|---|---|---|") + for c, s in result["competitor_scores"].items(): + lines.append(f"| {c} | {s['wins']} | {s['ties']} | {s['losses']} | " + f"**{s['win_pct']}%** | {s['verdict']} |") + lines.append(f"\n**Overall win rate: {m['overall_win_pct']}% — {m['verdict']}**\n") + + # Feature matrix by category + lines.append("## Feature Matrix\n") + header = f"| Feature | {m['your_product']} | " + " | ".join(comp) + " | Notes |" + sep = "|---|---|" + "|".join(["---"] * len(comp)) + "|---|" + lines.append(header) + lines.append(sep) + + current_cat = None + for r in rows: + cat = r["category"] + if cat != current_cat: + lines.append(f"| **{cat}** | | " + " | ".join([""] * len(comp)) + " | |") + current_cat = cat + you_icon = STATUS_LABEL[r["your_status"]] + comp_icons = " | ".join(STATUS_LABEL[r["competitors"].get(c, "no")] for c in comp) + note = r["notes"] or "" + # Highlight row if it's a unique advantage + fname = f"**{r['name']}**" if r["advantage"] > 0 else r["name"] + lines.append(f"| {fname} | {you_icon} | {comp_icons} | {note} |") + + lines.append("") + + # Advantages + if result["advantages"]: + lines.append("## āœ… Your Advantages\n") + for a in result["advantages"]: + lines.append(f"- {a}") + lines.append("") + + # Gaps + if result["gaps"]: + lines.append("## āš ļø Feature Gaps (competitors ahead)\n") + for g in result["gaps"]: + lines.append(f"- {g}") + lines.append("") + + # Legend + lines.append("## Legend\n") + for k, v in STATUS_LABEL.items(): + lines.append(f"- {v} {STATUS_TEXT[k]}") + lines.append("") + + return "\n".join(lines) + + +# --------------------------------------------------------------------------- +# Pretty terminal output +# --------------------------------------------------------------------------- + +def pretty_print(result: dict) -> None: + m = result["meta"] + print("\n" + "=" * 70) + print(f" COMPETITIVE MATRIX: {m['your_product'].upper()} vs {', '.join(m['competitors'])}") + print("=" * 70) + print(f"\n Total features analysed : {m['total_features']}") + print(f" Overall win rate : {m['overall_win_pct']}% ({m['verdict']})") + + print(f"\n{'─'*70}") + print(f" {'COMPETITOR':<22} {'WIN%':>5} {'WINS':>5} {'TIES':>5} {'LOSSES':>7} VERDICT") + print(f"{'─'*70}") + for c, s in result["competitor_scores"].items(): + bar = "ā–ˆ" * (s["win_pct"] // 10) + "ā–‘" * (10 - s["win_pct"] // 10) + print(f" {c:<22} {s['win_pct']:>4}% {s['wins']:>5} {s['ties']:>5} " + f"{s['losses']:>7} {bar} {s['verdict']}") + + print(f"\n{'─'*70}") + col_w = 20 + header = f" {'FEATURE':<28} | {'YOU':^8}" + for c in m["competitors"]: + header += f" | {c[:8]:^8}" + print(header) + print("─" * (30 + 11 * (1 + len(m["competitors"])))) + + current_cat = None + for r in result["features"]: + if r["category"] != current_cat: + print(f"\n [{r['category']}]") + current_cat = r["category"] + you_icon = STATUS_LABEL[r["your_status"]] + line = f" {' '+r['name']:<28} | {you_icon:^8}" + for c in m["competitors"]: + ci = STATUS_LABEL[r["competitors"].get(c, "no")] + line += f" | {ci:^8}" + if r["advantage"] > 0: + line += " ← advantage" + elif r["advantage"] < 0: + line += " ← gap" + print(line) + + print(f"\n āœ… YOUR ADVANTAGES ({len(result['advantages'])} features)") + for a in result["advantages"]: + print(f" • {a}") + + print(f"\n āš ļø FEATURE GAPS ({len(result['gaps'])} features)") + for g in result["gaps"]: + print(f" • {g}") + + print(f"\n Legend: {STATUS_LABEL['full']} Full {STATUS_LABEL['partial']} Partial " + f"{STATUS_LABEL['no']} No {STATUS_LABEL['planned']} Planned\n") + + +# --------------------------------------------------------------------------- +# Sample data +# --------------------------------------------------------------------------- + +DEMO_DATA = { + "your_product": "SwiftBase", + "features": [ + {"name": "SSO / SAML", "category": "Security", "weight": 3, "your_status": "full", "competitors": {"AcmeSaaS": "no", "ProStack": "partial"}, "notes": "All plans"}, + {"name": "2FA / MFA", "category": "Security", "weight": 3, "your_status": "full", "competitors": {"AcmeSaaS": "full", "ProStack": "full"}, "notes": ""}, + {"name": "SOC 2 Type II", "category": "Security", "weight": 3, "your_status": "planned", "competitors": {"AcmeSaaS": "full", "ProStack": "no"}, "notes": "Q3 target"}, + {"name": "Role-based access", "category": "Security", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "partial", "ProStack": "full"}, "notes": ""}, + {"name": "REST API", "category": "Integrations", "weight": 3, "your_status": "full", "competitors": {"AcmeSaaS": "full", "ProStack": "full"}, "notes": ""}, + {"name": "GraphQL API", "category": "Integrations", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "no", "ProStack": "partial"}, "notes": ""}, + {"name": "Zapier Integration", "category": "Integrations", "weight": 2, "your_status": "partial", "competitors": {"AcmeSaaS": "full", "ProStack": "full"}, "notes": "10 zaps only"}, + {"name": "Webhooks", "category": "Integrations", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "full", "ProStack": "no"}, "notes": ""}, + {"name": "Custom domain", "category": "Branding", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "partial", "ProStack": "full"}, "notes": ""}, + {"name": "White-label / rebrand","category": "Branding", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "no", "ProStack": "partial"}, "notes": "Agency plan"}, + {"name": "Priority support", "category": "Support", "weight": 2, "your_status": "full", "competitors": {"AcmeSaaS": "partial", "ProStack": "full"}, "notes": "24/7"}, + {"name": "Dedicated CSM", "category": "Support", "weight": 2, "your_status": "no", "competitors": {"AcmeSaaS": "full", "ProStack": "full"}, "notes": "Enterprise only"}, + {"name": "SLA guarantee", "category": "Support", "weight": 3, "your_status": "no", "competitors": {"AcmeSaaS": "full", "ProStack": "no"}, "notes": "Roadmap"}, + ], +} + + +# --------------------------------------------------------------------------- +# CLI +# --------------------------------------------------------------------------- + +def parse_args(): + parser = argparse.ArgumentParser( + description="Build a competitive feature comparison matrix (stdlib only).", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--input", type=str, default=None, + help="Path to JSON input file") + parser.add_argument("--json", action="store_true", + help="Output analysis as JSON") + parser.add_argument("--markdown", action="store_true", + help="Output comparison table as Markdown") + return parser.parse_args() + + +def main(): + args = parse_args() + + if args.input: + with open(args.input) as f: + data = json.load(f) + else: + print("šŸ”¬ DEMO MODE — using sample SaaS product matrix\n", file=sys.stderr) + data = DEMO_DATA + + result = build_matrix(data) + + if args.json: + # Serialise (remove non-JSON-safe keys) + print(json.dumps(result, indent=2)) + elif args.markdown: + print(build_markdown(result)) + else: + pretty_print(result) + print("\nšŸ’” TIP: Re-run with --markdown to get a copyable Markdown table.\n") + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/content-creator/SKILL.md b/marketing-skill/content-creator/SKILL.md index ea86087..542542c 100644 --- a/marketing-skill/content-creator/SKILL.md +++ b/marketing-skill/content-creator/SKILL.md @@ -1,303 +1,55 @@ --- name: content-creator -description: Create SEO-optimized marketing content with consistent brand voice. Includes brand voice analyzer, SEO optimizer, content frameworks, and social media templates. Use when writing blog posts, creating social media content, analyzing brand voice, optimizing SEO, planning content calendars, or when user mentions content creation, brand voice, SEO optimization, social media marketing, or content strategy. +description: "DEPRECATED — Use content-production for full content pipeline, or content-strategy for planning. This skill redirects to the appropriate specialist." license: MIT metadata: - version: 1.0.0 + version: 2.0.0 author: Alireza Rezvani category: marketing - domain: content-marketing - updated: 2025-10-20 - python-tools: brand_voice_analyzer.py, seo_optimizer.py - tech-stack: SEO, social-media-platforms + updated: 2026-03-06 + status: deprecated --- -# Content Creator +# Content Creator → Redirected -Professional-grade brand voice analysis, SEO optimization, and platform-specific content frameworks. +> **This skill has been split into two specialist skills.** Use the one that matches your intent: ---- +| You want to... | Use this instead | +|----------------|-----------------| +| **Write** a blog post, article, or guide | [content-production](../content-production/) | +| **Plan** what content to create, topic clusters, calendar | [content-strategy](../content-strategy/) | +| **Analyze brand voice** | [content-production](../content-production/) (includes `brand_voice_analyzer.py`) | +| **Optimize SEO** for existing content | [content-production](../content-production/) (includes `seo_optimizer.py`) | +| **Create social media content** | [social-content](../social-content/) | -## Table of Contents +## Why the Change -- [Keywords](#keywords) -- [Quick Start](#quick-start) -- [Core Workflows](#core-workflows) -- [Tools](#tools) -- [Reference Guides](#reference-guides) -- [Best Practices](#best-practices) -- [Integration Points](#integration-points) +The original `content-creator` tried to do everything: planning, writing, SEO, social, brand voice. That made it a jack of all trades. The specialist skills do each job better: ---- +- **content-production** — Full pipeline: research → brief → draft → optimize → publish. Includes all Python tools from the original content-creator. +- **content-strategy** — Strategic planning: topic clusters, keyword research, content calendars, prioritization frameworks. -## Keywords +## Proactive Triggers -content creation, blog posts, SEO, brand voice, social media, content calendar, marketing content, content strategy, content marketing, brand consistency, content optimization, social media marketing, content planning, blog writing, content frameworks, brand guidelines, social media strategy +- **User asks "content creator"** → Route to content-production (most likely intent is writing). +- **User asks "content plan" or "what should I write"** → Route to content-strategy. ---- +## Output Artifacts -## Quick Start +| When you ask for... | Routed to... | +|---------------------|-------------| +| "Write a blog post" | content-production | +| "Content calendar" | content-strategy | +| "Brand voice analysis" | content-production (`brand_voice_analyzer.py`) | +| "SEO optimization" | content-production (`seo_optimizer.py`) | -### Brand Voice Development +## Communication -1. Run `scripts/brand_voice_analyzer.py` on existing content to establish baseline -2. Review `references/brand_guidelines.md` to select voice attributes -3. Apply chosen voice consistently across all content +This is a redirect skill. Route the user to the correct specialist — don't attempt to handle the request here. -### Blog Content Creation +## Related Skills -1. Choose template from `references/content_frameworks.md` -2. Research keywords for topic -3. Write content following template structure -4. Run `scripts/seo_optimizer.py [file] [primary-keyword]` to optimize -5. Apply recommendations before publishing - -### Social Media Content - -1. Review platform best practices in `references/social_media_optimization.md` -2. Use appropriate template from `references/content_frameworks.md` -3. Optimize based on platform-specific guidelines -4. Schedule using `assets/content_calendar_template.md` - ---- - -## Core Workflows - -### Workflow 1: Establish Brand Voice (First Time Setup) - -For new brands or clients: - -**Step 1: Analyze Existing Content (if available)** - -```bash -python scripts/brand_voice_analyzer.py existing_content.txt -``` - -**Step 2: Define Voice Attributes** - -- Review brand personality archetypes in `references/brand_guidelines.md` -- Select primary and secondary archetypes -- Choose 3-5 tone attributes -- Document in brand guidelines - -**Step 3: Create Voice Sample** - -- Write 3 sample pieces in chosen voice -- Test consistency using analyzer -- Refine based on results - -### Workflow 2: Create SEO-Optimized Blog Posts - -**Step 1: Keyword Research** - -- Identify primary keyword (search volume 500-5000/month) -- Find 3-5 secondary keywords -- List 10-15 LSI keywords - -**Step 2: Content Structure** - -- Use blog template from `references/content_frameworks.md` -- Include keyword in title, first paragraph, and 2-3 H2s -- Aim for 1,500-2,500 words for comprehensive coverage - -**Step 3: Optimization Check** - -```bash -python scripts/seo_optimizer.py blog_post.md "primary keyword" "secondary,keywords,list" -``` - -**Step 4: Apply SEO Recommendations** - -- Adjust keyword density to 1-3% -- Ensure proper heading structure -- Add internal and external links -- Optimize meta description - -### Workflow 3: Create Social Media Content - -**Step 1: Platform Selection** - -- Identify primary platforms based on audience -- Review platform-specific guidelines in `references/social_media_optimization.md` - -**Step 2: Content Adaptation** - -- Start with blog post or core message -- Use repurposing matrix from `references/content_frameworks.md` -- Adapt for each platform following templates - -**Step 3: Optimization Checklist** - -- Platform-appropriate length -- Optimal posting time -- Correct image dimensions -- Platform-specific hashtags -- Engagement elements (polls, questions) - -### Workflow 4: Plan Content Calendar - -**Step 1: Monthly Planning** - -- Copy `assets/content_calendar_template.md` -- Set monthly goals and KPIs -- Identify key campaigns/themes - -**Step 2: Weekly Distribution** - -- Follow 40/25/25/10 content pillar ratio -- Balance platforms throughout week -- Align with optimal posting times - -**Step 3: Batch Creation** - -- Create all weekly content in one session -- Maintain consistent voice across pieces -- Prepare all visual assets together - ---- - -## Tools - -### Brand Voice Analyzer - -Analyzes text content for voice characteristics, readability, and consistency. - -**Usage:** - -```bash -# Human-readable output -python scripts/brand_voice_analyzer.py content.txt - -# JSON output for integrations -python scripts/brand_voice_analyzer.py content.txt json -``` - -**Parameters:** - -| Parameter | Required | Description | -|-----------|----------|-------------| -| `file` | Yes | Path to content file | -| `format` | No | Output format: `text` (default) or `json` | - -**Output:** - -- Voice profile (formality, tone, perspective) -- Readability score (Flesch Reading Ease) -- Sentence structure analysis -- Improvement recommendations - -### SEO Optimizer - -Analyzes content for SEO optimization and provides actionable recommendations. - -**Usage:** - -```bash -# Basic analysis -python scripts/seo_optimizer.py article.md "main keyword" - -# With secondary keywords -python scripts/seo_optimizer.py article.md "main keyword" "secondary,keywords,list" - -# JSON output -python scripts/seo_optimizer.py article.md "keyword" --json -``` - -**Parameters:** - -| Parameter | Required | Description | -|-----------|----------|-------------| -| `file` | Yes | Path to content file (md or html) | -| `primary_keyword` | Yes | Main target keyword | -| `secondary_keywords` | No | Comma-separated secondary keywords | -| `--json` | No | Output in JSON format | - -**Output:** - -- SEO score (0-100) -- Keyword density analysis -- Structure assessment -- Meta tag suggestions -- Specific optimization recommendations - ---- - -## Reference Guides - -### When to Use Each Reference - -**references/brand_guidelines.md** - -- Setting up new brand voice -- Ensuring consistency across content -- Training new team members -- Resolving voice/tone questions - -**references/content_frameworks.md** - -- Starting any new content piece -- Structuring different content types -- Creating content templates -- Planning content repurposing - -**references/social_media_optimization.md** - -- Platform-specific optimization -- Hashtag strategy development -- Understanding algorithm factors -- Setting up analytics tracking - -**references/analytics_guide.md** - -- Tracking content performance -- Setting up measurement frameworks -- Creating performance reports -- Attribution modeling - ---- - -## Best Practices - -### Content Creation Process - -1. Start with audience need/pain point -2. Research before writing -3. Create outline using templates -4. Write first draft without editing -5. Optimize for SEO -6. Edit for brand voice -7. Proofread and fact-check -8. Optimize for platform -9. Schedule strategically - -### Quality Indicators - -- SEO score above 75/100 -- Readability appropriate for audience -- Consistent brand voice throughout -- Clear value proposition -- Actionable takeaways -- Proper visual formatting -- Platform-optimized - -### Common Pitfalls to Avoid - -- Writing before researching keywords -- Ignoring platform-specific requirements -- Inconsistent brand voice -- Over-optimizing for SEO (keyword stuffing) -- Missing clear CTAs -- Publishing without proofreading -- Ignoring analytics feedback - ---- - -## Integration Points - -This skill works best with: - -- **Analytics platforms** - Google Analytics, social media insights for tracking (see `references/analytics_guide.md`) -- **SEO tools** - For keyword research and competitive analysis -- **Design tools** - Canva, Figma for visual content -- **Scheduling platforms** - Buffer, Hootsuite for content distribution -- **Email marketing systems** - For newsletter content campaigns +- **content-production**: Full content execution pipeline (successor). +- **content-strategy**: Content planning and topic selection (successor). +- **content-humanizer**: Post-processing AI content to sound authentic. +- **marketing-context**: Foundation context that both successors read. diff --git a/marketing-skill/content-humanizer/SKILL.md b/marketing-skill/content-humanizer/SKILL.md new file mode 100644 index 0000000..c0a8358 --- /dev/null +++ b/marketing-skill/content-humanizer/SKILL.md @@ -0,0 +1,261 @@ +--- +name: content-humanizer +description: "Makes AI-generated content sound genuinely human — not just cleaned up, but alive. Use when content feels robotic, uses too many AI clichĆ©s, lacks personality, or reads like it was written by committee. Triggers: 'this sounds like AI', 'make it more human', 'add personality', 'it feels generic', 'sounds robotic', 'fix AI writing', 'inject our voice'. NOT for initial content creation (use content-production). NOT for SEO optimization (use content-production Mode 3)." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Content Humanizer + +You are an expert in authentic writing and brand voice. Your goal is to transform content that reads like it was generated by a machine — even when it technically was — into writing that sounds like a real person with real opinions, real experience, and real stakes in what they're saying. + +This is not a cleaning service. You're not just removing "delve" and calling it a day. You're rebuilding the voice from the ground up. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it. It contains brand voice guidelines, writing examples, and the specific tone this brand uses. That context is your voice blueprint. Use it — don't improvise a voice when the brief already defines one. + +Gather what you need before starting: + +### What you need +- **The content** — paste the draft to humanize +- **Brand voice notes** — if no `marketing-context.md`, ask: "Is your voice direct/casual/technical/irreverent? Give me one example of writing you love." +- **Audience** — who reads this? (This changes what "human" sounds like) +- **Goal** — what should this piece do? (Knowing the goal tells you how much personality is appropriate) + +One question if needed: "Before I rewrite this, give me an example of content you've written or read that felt right. Specific is better than descriptive." + +## How This Skill Works + +Three modes. Run them in sequence for a full transformation, or jump to the one you need: + +### Mode 1: Detect — AI Pattern Analysis +Audit the content for AI tells. Name what's wrong and why before fixing anything. This is diagnostic — not editorial. + +### Mode 2: Humanize — Pattern Removal and Rhythm Fix +Strip the AI patterns. Fix sentence rhythm. Replace generic with specific. The content starts sounding like a person. + +### Mode 3: Voice Injection — Brand Character +Now that the generic is gone, inject the brand's specific personality. This is where "human" becomes *your brand's* human. + +Run all three in one pass when you have enough context. Split them when the client needs to see the audit before you edit. + +--- + +## Mode 1: Detect — AI Pattern Analysis + +Scan the content for these categories. Score severity: šŸ”“ critical (kills credibility) / 🟔 medium (softens impact) / 🟢 minor (polish only). + +See [references/ai-tells-checklist.md](references/ai-tells-checklist.md) for the comprehensive detection list. + +### The Core AI Tell Categories + +**1. Overused Filler Words** šŸ”“ +The model loves certain words because they appear frequently in its training data. Flag these on sight: +- "delve," "delve into," "delve deeper" +- "landscape" (as in "the current AI landscape") +- "crucial," "vital," "pivotal" +- "leverage" (when "use" works fine) +- "furthermore," "moreover," "in addition" +- "navigate" (metaphorical: "navigate this challenge") +- "robust," "comprehensive," "holistic" +- "foster," "facilitate," "ensure" + +**2. Hedging Chains** šŸ”“ +AI hedges constantly. It hedges because it doesn't know if it's right. Humans hedge sometimes — but not in every sentence. +- "It's important to note that..." +- "It's worth mentioning that..." +- "One might argue that..." +- "In many cases," "In most scenarios," +- "It goes without saying..." +- "Needless to say..." + +**3. Em-Dash Overuse** 🟔 +One or two em-dashes in a piece: fine. Em-dash in every other paragraph: AI fingerprint. The model uses em-dashes to add clauses the way humans add breath — but it does it compulsively. + +**4. Identical Paragraph Structure** šŸ”“ +Every paragraph: topic sentence → explanation → example → bridge to next. AI is remarkably consistent. Remarkably boring. Real writing has short paragraphs. Fragments. Asides. Digressions. Then it snaps back. The structure varies. + +**5. Lack of Specificity** šŸ”“ +AI replaces specific claims with vague ones because specific claims can be wrong. Look for: +- "Many companies" → which companies? +- "Studies show" → which studies? +- "Significantly improved" → improved by how much? +- "Leading brands" → name one +- "A lot of" → how many? + +**6. False Certainty / False Authority** 🟔 +AI asserts confidently about things no one can be certain about. "Companies that do X are more successful." According to what? This isn't humility — it's laziness dressed as confidence. + +**7. The "In conclusion" Paragraph** 🟔 +AI conclusions are often carbon copies of the intro. "In this article, we explored X, Y, and Z. By implementing these strategies, you can achieve..." No human concludes like this. Real conclusions either add something new or nail the exit line. + +--- + +## Mode 2: Humanize — Pattern Removal and Rhythm Fix + +After identifying what's wrong, fix it systematically. + +### Replace Filler Words + +**Rule:** Never just delete — always replace with something better. + +| AI phrase | Human alternative | +|---|---| +| "delve into" | "look at," "dig into," "break down," or just: "here's what matters" | +| "the [X] landscape" | "how [X] works today," "the current state of [X]" | +| "leverage" | "use," "apply," "put to work" | +| "crucial" / "vital" | "the part that actually matters," "the one thing," or just state the thing — let it be self-evidently important | +| "furthermore" | nothing (just start the next sentence), or "and," or "also" | +| "robust" | specific: "handles 10,000 requests/sec," "covers 47 edge cases" | +| "facilitate" | "help," "make easier," "allow" | +| "navigate this challenge" | "handle this," "deal with this," "get through this" | + +### Fix Sentence Rhythm + +**The problem:** AI produces uniform sentence length. Every sentence is 18-22 words. The ear goes numb. + +**The fix:** Deliberate variation. Read aloud. Then: +- Break long sentences into two +- Add a short sentence after a long one. Like this. +- Use fragments where they serve emphasis. Especially for emphasis. +- Let some sentences run longer when the thought needs to unwind and the reader has the context to follow it + +**Rhythm patterns that feel human:** +- Long. Short. Long, long. Short. +- Question? Answer. Proof. +- Claim. Specific example. So what? + +### Replace Generic with Specific + +Every vague claim is an invitation to doubt. Replace: + +**Before:** "Many companies have seen significant improvements by implementing this strategy." + +**After:** "HubSpot published their onboarding funnel data in 2023 — companies that hit their first-value moment within 7 days showed 40% higher 90-day retention. That's not a rounding error." + +If you don't have specific data, be honest: "I haven't seen controlled studies on this, but in my experience working with SaaS onboarding flows, the pattern is consistent: earlier activation = higher retention." + +Personal experience beats vague authority. Every time. + +### Vary Paragraph Structure + +Break the uniform SEEB pattern (Statement → Explanation → Example → Bridge): + +- **Single-sentence paragraph:** Use it. Emphasis needs air. +- **Question paragraph:** Pose a question. Then answer it. +- **List in the middle:** Drop a quick list when there are genuinely 3-5 parallel items. Then return to prose. +- **Aside / parenthetical paragraph:** A small digression that reveals personality. (Readers actually like these. It's the equivalent of a raised eyebrow mid-sentence.) +- **Confession:** "I got this wrong the first time." Instantly human. + +### Add Friction and Imperfection + +AI writing is too smooth. Too complete. Real people: +- Change direction mid-thought and acknowledge it: "Actually, let me back up..." +- Qualify things they're uncertain about without hiding the uncertainty +- Have opinions that might be wrong: "I might be wrong about this, but..." +- Notice things and say so: "What's interesting here is..." +- React: "Which, if you've ever tried to debug this, you know is maddening." + +--- + +## Mode 3: Voice Injection — Brand Character + +Humanizing removes AI. Voice injection makes it *yours*. + +### Read the Voice Blueprint First + +If `marketing-context.md` is available: read the brand voice section and writing examples. If not, ask for one example of content this brand loves. One. Then extract the patterns from it. + +**What to extract from a voice example:** +- Sentence length preference (short punchy vs. longer flowing?) +- Formality level (contractions? slang? industry jargon?) +- Use of humor (dry wit? self-deprecating? none?) +- Relationship stance (peer-to-peer? expert-to-student? provocateur?) +- Signature phrases or patterns + +See [references/voice-techniques.md](references/voice-techniques.md) for specific techniques for each voice type. + +### Voice Injection Techniques + +**1. Personal Anecdotes** +Even branded content gets more credible when grounded in experience. "We saw this firsthand when building X" is worth more than any study citation. + +**2. Direct Address** +Talk to the reader as "you." Not "users" or "teams" or "organizations." You. + +**3. Opinions Without Apology** +State your position. "We think the industry is wrong about this" is more credible than "there are various perspectives." Take the side. + +**4. The Aside** +A brief parenthetical that shows the brand knows more than it's saying. "This also affects API performance, but that's a separate rabbit hole." + +**5. Rhythm Signature** +Every brand has a rhythm. Some write in short staccato bursts. Some write long, winding sentences that spiral back on themselves. Find the rhythm from the examples and apply it consistently. + +### Before / After Example + +**Before (AI-generated):** +> It is crucial to leverage your existing customer data in order to effectively navigate the competitive landscape. Furthermore, by implementing a robust onboarding strategy, organizations can ensure that users achieve maximum value from the product and reduce churn significantly. + +**After (humanized):** +> Here's the thing nobody says out loud: most SaaS companies have the data to fix their churn problem. They just don't look at it until after customers leave. +> +> Your activation funnel is in there. Your best cohorts, your worst, the moment the drop-off happens. You don't need another tool — you need someone to stop ignoring what the tool is already showing you. +> +> Nail onboarding first. Everything else is downstream. + +What changed: +- Removed: "crucial," "leverage," "navigate," "robust," "ensure," "significantly," "furthermore" +- Added: direct address, specific accusation ("what the tool is already showing you"), short-sentence punch at the end +- Changed: passive recommendations → active point of view + +--- + +## Proactive Triggers + +Flag these without being asked: + +- **AI fingerprint density too high** — If the piece has 10+ AI tells per 500 words, a patch job won't work. Flag that the piece needs a full rewrite, not an edit. Trying to polish a piece that's 80% AI patterns produces AI patterns with nicer words. +- **Voice context missing** — If `marketing-context.md` doesn't exist and the user hasn't given voice guidance, pause before injecting voice. Ask for one example. Guessing the voice and being wrong wastes everyone's time. +- **Specificity gap** — If the piece makes 5+ vague claims with zero data or attribution, flag it to the user. You can make the prose flow better, but you can't invent specific proof. They need to provide it. +- **Tone mismatch after humanizing** — If the piece is now genuinely human but sounds like a different brand than everything else the client publishes, flag it. Consistency matters as much as quality. +- **Over-editing risk** — If the original content has one or two genuinely good paragraphs buried in the AI mush, flag them before rewriting. Don't accidentally destroy the good parts. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---|---| +| AI audit | Annotated version of the draft with each AI pattern flagged, severity score, and count by category | +| Humanized draft | Full rewrite with AI patterns removed, rhythm varied, specificity improved | +| Voice injection | Annotated draft with brand voice applied — specific changes called out so you can learn the pattern | +| Before/after comparison | Side-by-side view of key paragraphs showing what changed and why | +| Humanity score | Run `scripts/humanizer_scorer.py` — 0-100 score with breakdown by signal type | + +--- + +## Communication + +All output follows the structured standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding includes all three +- **Actions have owners and deadlines** — no "you might want to consider" +- **Confidence tagging** — 🟢 verified pattern / 🟔 medium / šŸ”“ assumed based on limited voice context + +When auditing: name the pattern → explain why it reads as AI → give the specific fix. Not "this sounds robotic." Say: "Paragraph 4 opens with 'It is important to note that' — this is a pure hedge. Cut it. Start with the actual note." + +--- + +## Related Skills + +- **content-production**: Use to produce the initial draft. Run content-humanizer after drafting, before the SEO optimization pass. +- **copywriting**: Use for conversion copy — landing pages, CTAs, headlines. content-humanizer works on longer-form pieces; copywriting handles short punchy copy with different principles. +- **content-strategy**: Use when deciding what content to create. NOT for voice or draft execution. +- **ai-seo**: Use after humanizing, to optimize for AI search citation. Human-sounding content gets cited more — but it still needs structure to get extracted. diff --git a/marketing-skill/content-humanizer/references/ai-tells-checklist.md b/marketing-skill/content-humanizer/references/ai-tells-checklist.md new file mode 100644 index 0000000..474095e --- /dev/null +++ b/marketing-skill/content-humanizer/references/ai-tells-checklist.md @@ -0,0 +1,157 @@ +# AI Tells Checklist + +A comprehensive reference for detecting AI-generated or AI-assisted writing patterns. Use this during Mode 1 (Detect) to audit content before editing. + +Rate each finding: šŸ”“ Critical (rewrites required) / 🟔 Medium (edits needed) / 🟢 Minor (polish) + +--- + +## Category 1: Overused Vocabulary + +These words appear in AI output at 5-20x the frequency of human writing. One instance is fine. Multiple instances in a single piece is a tell. + +### Red-flag verbs (overused) +| Word | Problem | What humans say instead | +|---|---|---| +| delve / delve into | Pretentious filler | look at, dig into, explore, examine | +| leverage | Jargon for "use" | use, apply, put to work, capitalize on | +| foster | Formal filler | build, develop, encourage, create | +| facilitate | Bureaucratic filler | help, make easier, allow, support | +| navigate | Overused metaphor | handle, manage, work through, deal with | +| ensure | Empty guarantee | check that, make sure, verify | +| utilize | Formal for "use" | just say "use" | +| prioritize | Often redundant | just say what to do first | +| streamline | Vague improvement promise | be specific about what gets faster/easier | + +### Red-flag adjectives (overused) +| Word | Problem | What humans say instead | +|---|---|---| +| crucial / vital / pivotal | Overloaded intensifiers | just show why it matters | +| robust | Vague positive | specific: "handles X load," "covers Y cases" | +| comprehensive | Overpromise | specific: "covers the 5 most common..." | +| innovative | Meaningless | say what it actually does differently | +| holistic | Buzzword | say what it covers | +| seamless | Overused product adjective | describe the actual experience | +| cutting-edge | Dated marketing | say what's new or different specifically | +| dynamic | Filler adjective | usually just delete it | + +### Red-flag nouns (overused) +| Word | Problem | What humans say instead | +|---|---|---| +| landscape | Overused metaphor | "how X works today," "the state of X" | +| ecosystem | Overused for "industry" or "community" | be specific | +| framework | Often vague | name the specific framework or approach | +| paradigm | Academic filler | usually replaceable with "approach" or "way of thinking" | +| synergy | Corporate clichĆ© | delete or replace with what actually happens | + +--- + +## Category 2: Hedging and Qualification Patterns + +Humans hedge. AI hedges compulsively. The difference is frequency and context. + +### Opening hedges (usually safe to cut) +- "It's important to note that..." +- "It's worth mentioning that..." +- "It should be noted that..." +- "Needless to say..." +- "It goes without saying..." +- "Of course, ..." +- "Naturally, ..." + +### Mid-sentence hedges (examine each) +- "In many cases" / "In most instances" / "In certain scenarios" +- "Generally speaking," / "For the most part," +- "This may vary depending on..." +- "Results may differ based on..." +- "While this isn't always the case..." + +**Diagnostic:** If the hedge is protecting a claim that should just be a claim, cut the hedge and state the claim. If the hedge reflects genuine uncertainty, keep it — but make the uncertainty specific: "I don't have data for this, but based on [context]..." + +### Vague authority claims (replace with specifics) +- "Studies show..." → "A 2023 McKinsey study of 400 SaaS companies showed..." +- "Research suggests..." → same — name the research +- "Many companies..." → "HubSpot, Slack, and several bootstrapped SaaS founders we've talked to..." +- "Experts agree..." → name one expert +- "It has been shown that..." → by whom, when, where + +--- + +## Category 3: Structural Patterns + +### The SEEB paragraph (most common) +Pattern: Statement → Explanation → Example → Bridge to next topic +When every paragraph follows this exact structure, the writing reads like a machine assembled it. Because it was. + +**Fix:** Mix in fragments. Questions. Short paragraphs. Asides. Let sections breathe differently. + +### Parallelism overload +AI loves parallel structure. Three-item lists. Four-item lists. Everything in threes. Alliteration sometimes. + +Occasional parallelism is powerful. Three consecutive bulleted lists of three items each is a tell. + +**Fix:** Break the rhythm. Some sections need bullets. Most don't. + +### The summary conclusion +AI conclusions restate the introduction. Paragraph by paragraph. "In this guide, we covered X, Y, and Z. By applying these strategies, you can achieve [thing from the intro]." + +Human conclusions either add something (a new angle, an honest admission, a call to action that feels earned) or they nail the exit line and stop. + +### Symmetric section lengths +Every H2 section is roughly the same length. ~300 words. Every one. That's a machine maintaining consistency. Humans have opinions — some things deserve more space, some less. + +--- + +## Category 4: Punctuation and Formatting Tells + +### Em-dash frequency 🟔 +One or two em-dashes per piece: fine. Three per page: suspicion. Five+: AI fingerprint. + +The em-dash is AI's favorite way to add subordinate clauses — like this — because it sounds sophisticated — and it learned this from a lot of well-written text — so now it can't stop. + +**Fix:** Replace most with periods. Break into shorter sentences. + +### Colon-then-list patterns 🟢 +AI frequently: introduces a list: with: colons. Multiple times per section. Lists are useful. But if every section has a colon-introducing list, it's mechanical. + +### Excessive bold 🟢 +AI sometimes bolds every important-sounding phrase in a paragraph. **This results** in **too many** phrases being **highlighted for emphasis** when the emphasis **dilutes itself**. + +Bold should be used sparingly — for the one thing that matters most in a section, not for three to five things per paragraph. + +--- + +## Category 5: Tonal Tells + +### False warmth 🟔 +"We hope this guide has been helpful in your journey to..." +"We trust that you've found valuable insights in..." +"It's our sincere hope that these strategies will empower you to..." + +No one talks like this. It's the corporate newsletter voice. Cut it. + +### Emotional escalation without basis 🟔 +AI sometimes starts clinical and then, near the end, gets unexpectedly warm and inspirational. "Now that you have these tools, you can transform your business and achieve your goals." The warmth wasn't earned by the preceding content. + +### Artificial enthusiasm 🟢 +"Exciting developments," "fascinating case study," "incredible opportunity" — used to simulate human engagement. Usually reads as hollow because it's disconnected from actual content that earns those descriptors. + +--- + +## Quick Audit Scoring + +For a 1,000-word piece, count: + +| Signal | Count | Severity Threshold | +|---|---|---| +| Red-flag vocabulary words | | >5 = šŸ”“ | +| Opening hedges | | >2 = šŸ”“ | +| Vague authority claims ("studies show") | | >2 = šŸ”“ | +| Em-dashes | | >4 = 🟔 | +| SEEB paragraphs (all follow same structure) | | >60% of paragraphs = šŸ”“ | +| Instances of false warmth | | >1 = 🟔 | + +**Scoring:** +- 0-5 total flags: Light edit (Mode 2 quick pass) +- 6-12 total flags: Full humanize pass (Mode 2 complete) +- 12+ total flags: Full rewrite recommended (Mode 1 audit → complete Mode 2 → Mode 3) diff --git a/marketing-skill/content-humanizer/references/voice-techniques.md b/marketing-skill/content-humanizer/references/voice-techniques.md new file mode 100644 index 0000000..c38ace2 --- /dev/null +++ b/marketing-skill/content-humanizer/references/voice-techniques.md @@ -0,0 +1,168 @@ +# Voice Techniques Reference + +Techniques for injecting authentic brand voice into content. This is the Mode 3 playbook — after you've removed AI patterns (Mode 2), these techniques put the brand's specific personality in. + +--- + +## Step 1: Extract the Voice Profile + +Before writing anything, extract the voice from examples. Ask for one piece of content the brand considers representative. Then answer these questions about it: + +| Question | What to look for | +|---|---| +| Average sentence length? | Count words per sentence across 10 sentences. ≤15 = punchy. ≄25 = flowing. | +| Formality level? | Count contractions ("it's" vs "it is"). Count first-person. Count slang. | +| Use of humor? | Dry wit (unexpected juxtapositions). Self-deprecating (acknowledges own limitations). Provocateur (picks fights). None. | +| Relationship to reader? | Peer (we're both figuring this out). Expert (I know, you're learning). Challenger (you're probably wrong about this). | +| Signature phrases? | Phrases or constructions that appear more than once. That's the brand's verbal tic. | +| What do they avoid? | Listen for what's conspicuously absent. | + +Document this as a voice profile before editing. Reference it throughout. + +--- + +## The Core Voice Types + +### Voice Type 1: The Direct Expert + +**Profile:** Short sentences. Confident claims. No hedging. No qualifications unless the qualification is the point. Reads like advice from the smartest person in the room who also has the least patience. + +**Natural habitat:** Developer tools, technical documentation, no-fluff B2B brands, opinionated founders. + +**Techniques:** +- Lead every section with the conclusion, not the setup +- Make claims without softening them: "Most onboarding is broken" not "Many onboarding flows may have room for improvement" +- Use "you" relentlessly — direct address, always +- Short paragraphs. Often 1-2 sentences. +- When listing, use the smallest number of words possible +- No rhetorical questions unless you're about to immediately answer them +- Swear if the brand does (a well-placed "this is genuinely terrible" signals authenticity) + +**Before:** "It's important to consider that implementing an effective onboarding strategy can have significant positive impacts on user retention rates." + +**After:** "Fix your onboarding. It's where you're losing them." + +--- + +### Voice Type 2: The Thoughtful Peer + +**Profile:** Longer sentences when the thought requires it. Occasional vulnerability. Shares the thinking, not just the conclusion. Treats the reader as someone at roughly the same level. + +**Natural habitat:** B2B SaaS with community focus, content brands, newsletter-first companies, founder blogs. + +**Techniques:** +- Show the reasoning: "Here's how I think about this..." not just the conclusion +- Acknowledge what you don't know: "I don't have solid data on this, but my read is..." +- Share the mistake before the lesson: "We tried X first and it failed. Here's what we learned." +- Longer transitions: connect ideas, don't just jump to the next point +- Questions that earn their keep — rhetorical only when you're genuinely pointing at a tension +- First person plural ("we") where appropriate — but only if there actually is a "we" + +**Before:** "Companies should invest in customer success to improve retention." + +**After:** "I spent two years thinking retention was a marketing problem. It wasn't. Every company we talked to that had great retention had one thing in common: they treated customer success like a product team, not a support team. The product mindset made all the difference." + +--- + +### Voice Type 3: The Provocateur + +**Profile:** Challenges received wisdom. Takes positions most people avoid. Enjoys being right when everyone else was wrong. Not confrontational for its own sake — has actual conviction behind the provocation. + +**Natural habitat:** Opinionated SaaS, contrarian analyst voices, certain agency brands, fast-growing startups trying to differentiate. + +**Techniques:** +- Open with the unpopular claim: "Most SEO advice is wrong" not "There are many perspectives on SEO" +- Name the thing people don't say: "The reason nobody talks about X is because..." +- Acknowledge the argument against your position before making yours stronger +- Use "actually" strategically: "What actually happens is..." +- When everyone agrees on something, be specific about what they're getting wrong +- Let the evidence land without fanfare — state the uncomfortable number, then wait + +**Before:** "There are various approaches to content marketing that teams may find valuable." + +**After:** "Your competitors' content marketing budgets are wasted. The average B2B blog post gets 300 views and zero conversions. The top 10% of pieces generate 90% of the value. Most teams don't know which 10% they have — which means they're spending 90% of their budget on content that will never pay back." + +--- + +### Voice Type 4: The Enthusiastic Practitioner + +**Profile:** Genuine excitement about the craft. Energized by the detail. The person who could talk about their domain for hours and you'd actually enjoy it. + +**Natural habitat:** Creative tools, marketing tech, community platforms, brands with a strong practitioner user base. + +**Techniques:** +- Allow enthusiasm to come through without forcing it: "This is the part I love about cohort analysis..." +- Share the unexpected detail that only a practitioner would notice +- Use specific terminology confidently — don't over-explain to practitioners +- "The thing is..." as a transition — signals you're about to share the real insight +- Parenthetical asides that reveal depth: "(And yes, I know about [edge case] — that's a separate problem)" +- Let the complexity show when the complexity is interesting + +**Before:** "Segmenting your audience allows for more targeted communication." + +**After:** "Here's where audience segmentation gets genuinely interesting. Most people segment by company size or industry. That's fine. But the cohort that always outperforms is behavioral — people who hit your activation event within 72 hours. That cohort has 2-3x the LTV of the same-company-size cohort that took two weeks. The behavior tells you more than the firmographic ever will." + +--- + +## Specific Techniques Regardless of Voice Type + +### The Personal Anecdote Injection + +Every brand can use a personal anecdote — even B2B technical brands. The format: + +**Setup:** "When we [did X thing in context]..." +**What happened:** "[Specific unexpected thing occurred]." +**The lesson:** "[The principle that explains it]." + +The anecdote doesn't have to be dramatic. It just has to be real and specific. "When we rebuilt our onboarding flow in 2023, we expected the copy to be the problem. It was the loading time." + +### The Honest Admission + +Instantly humanizing. Rarely done by brands because it feels like weakness. But readers trust brands that admit: +- What they got wrong +- What they don't know +- What they tried that failed +- What surprised them + +The format: "We thought X. We were wrong. What actually happened was Y." + +### The Contrarian Setup + +Works for any voice type. Setup: state the conventional wisdom. Then undercut it. + +"Everyone says [thing]. The data shows [opposite thing]." + +Or more subtle: "The conventional wisdom is [X]. That's mostly true. Except when [specific condition] — and that's where it gets interesting." + +### Sentence Rhythm Signature + +After analyzing the brand voice, identify the rhythm pattern and apply it: + +- **Staccato brand:** Short sentence. Shorter. Done. +- **Flowing brand:** Content that allows ideas to build on each other, connect, and arrive somewhere richer than where they started. +- **Mixed cadence (most natural):** Long sentence establishing context. Short punch. Then another long one that goes somewhere. Then: done. + +Once you know the pattern, apply it consistently throughout the piece. + +### The Earned Ending + +The last sentence of a piece should land. Not summarize. Not encourage. Land. + +Techniques: +- **The hard cut:** State the core truth one final time, nakedly. No wrap-up. +- **The reversal:** Setup expectation, then subvert it in the last line. +- **The action:** Name the single most important thing to do next. One thing. +- **The honest admission:** "We're still figuring this out too." + +Avoid: "By following these steps, you'll be well on your way to achieving your goals." Nobody reads that. Nobody trusts it. + +--- + +## Voice Injection Quality Check + +After applying voice: +- [ ] Read the piece aloud — does it sound like a person you'd actually follow? +- [ ] Is every paragraph distinguishable from the others? (Not just same rhythm, same length, same pattern) +- [ ] Is there at least one moment where the brand's specific personality is unmistakable? +- [ ] Would someone who knows this brand's other content recognize this as theirs? +- [ ] Is there at least one place where the brand says something most brands wouldn't? diff --git a/marketing-skill/content-humanizer/scripts/humanizer_scorer.py b/marketing-skill/content-humanizer/scripts/humanizer_scorer.py new file mode 100644 index 0000000..55d52a3 --- /dev/null +++ b/marketing-skill/content-humanizer/scripts/humanizer_scorer.py @@ -0,0 +1,487 @@ +#!/usr/bin/env python3 +"""humanizer_scorer.py — scores content 0-100 on 'humanity' by detecting AI writing patterns.""" + +import sys +import re +import json +import math +from collections import Counter + +# ── Sample content for zero-config demo ────────────────────────────────────── +SAMPLE_HUMAN = """ +We tried to fix our churn problem the wrong way for about a year. + +We threw money at marketing, assumed acquisition would outpace loss, and avoided looking at the actual numbers. It didn't work. Churn stayed flat at 8% monthly, which sounds manageable until you realize that's 65% annual churn. We were filling a leaky bucket with a garden hose. + +The breakthrough — if you can call it that — was embarrassingly simple: we actually talked to the customers who left. + +Not the ones who complained. The ones who quietly disappeared. We called 30 churned accounts over two weeks. You know what most of them said? They didn't hate the product. They just... forgot about it. It was solving a problem they cared about once, and then stopped caring about. + +So we rebuilt our onboarding around one question: what would make this impossible to ignore? Not "valuable" — people know it's valuable. Impossible to ignore. + +Three months later, 30-day activation was up 40%. Churn dropped to 4.5%. + +The lesson wasn't about product or pricing. It was about habit formation. And we were terrible at it. +""" + +SAMPLE_AI = """ +It is crucial to leverage data-driven insights in order to effectively navigate the challenges of customer retention in the competitive SaaS landscape. Furthermore, by implementing robust onboarding strategies, organizations can ensure that users achieve maximum value from the product, thereby significantly reducing churn rates. + +To facilitate this process, it's important to note that companies should delve into their customer behavior data to identify patterns and trends. Moreover, by fostering meaningful connections with customers and ensuring comprehensive support throughout their journey, businesses can cultivate lasting relationships that drive long-term success. + +In conclusion, the implementation of these holistic strategies will empower organizations to streamline their customer success operations and achieve sustainable growth in an increasingly competitive marketplace. +""" + + +# ── AI vocabulary signals ───────────────────────────────────────────────────── +AI_VOCABULARY = [ + # The notorious list + "delve", "delve into", "delves", "delving", + "landscape", + "crucial", "vital", "pivotal", + "leverage", "leveraging", "leveraged", + "robust", + "comprehensive", + "holistic", + "foster", "fosters", "fostering", + "facilitate", "facilitates", "facilitating", + "navigate", "navigating", + "ensure", "ensures", "ensuring", + "utilize", "utilizing", "utilizes", + "furthermore", "moreover", + "innovative", "cutting-edge", + "seamless", "seamlessly", + "empower", "empowers", "empowering", + "streamline", "streamlines", "streamlining", + "cultivate", "cultivating", + "paradigm", + "ecosystem", + "synergy", + "in conclusion", + "in summary", + "to summarize", +] + +HEDGING_PHRASES = [ + "it is important to note", + "it's important to note", + "it should be noted", + "it is worth mentioning", + "it's worth mentioning", + "it goes without saying", + "needless to say", + "in many cases", + "in most cases", + "in certain cases", + "in most instances", + "in many instances", + "generally speaking", + "for the most part", + "this may vary", + "results may differ", + "one might argue", + "it can be argued", + "there are various", + "there are many", + "it is crucial to", + "it's crucial to", +] + +PASSIVE_PATTERNS = [ + r'\b(is|are|was|were|be|been|being)\s+(being\s+)?\w+ed\b', + r'\b(can|could|should|would|may|might|must)\s+be\s+\w+ed\b', +] + +VAGUE_AUTHORITY = [ + "studies show", + "research suggests", + "research shows", + "experts agree", + "experts say", + "many companies", + "leading brands", + "it has been shown", + "according to research", + "data suggests", + "evidence suggests", +] + + +# ── Scoring functions ───────────────────────────────────────────────────────── + +def score_ai_vocabulary(text: str) -> dict: + """Score 0-25: fewer AI words = higher score.""" + text_lower = text.lower() + words_total = max(1, len(re.findall(r'\b\w+\b', text))) + + hits = [] + for phrase in AI_VOCABULARY: + count = text_lower.count(phrase) + if count > 0: + hits.append((phrase, count)) + + total_hits = sum(c for _, c in hits) + density = total_hits / (words_total / 100) # per 100 words + + # Score: 0 hits = 25, scales down + if total_hits == 0: + score = 25 + elif total_hits <= 2: + score = 20 + elif total_hits <= 5: + score = 14 + elif total_hits <= 10: + score = 8 + elif total_hits <= 15: + score = 3 + else: + score = 0 + + return { + "score": score, + "max": 25, + "ai_word_hits": total_hits, + "density_per_100_words": round(density, 2), + "flagged_terms": [f for f, _ in hits[:10]], # top 10 for display + } + + +def score_sentence_variance(text: str) -> dict: + """Score 0-20: high variance = more human (robots use uniform length).""" + sentences = re.split(r'[.!?]+', text) + sentences = [s.strip() for s in sentences if len(s.split()) >= 3] + + if len(sentences) < 3: + return {"score": 10, "max": 20, "std_dev": 0, "avg_length": 0, "note": "too few sentences to score"} + + lengths = [len(s.split()) for s in sentences] + avg = sum(lengths) / len(lengths) + variance = sum((l - avg) ** 2 for l in lengths) / len(lengths) + std_dev = math.sqrt(variance) + + # Good human writing has std_dev of 8-15 for mixed content + if std_dev >= 12: + score = 20 + elif std_dev >= 8: + score = 16 + elif std_dev >= 5: + score = 10 + elif std_dev >= 3: + score = 5 + else: + score = 0 # very robotic: all sentences same length + + return { + "score": score, + "max": 20, + "std_dev": round(std_dev, 1), + "avg_length": round(avg, 1), + "min_length": min(lengths), + "max_length": max(lengths), + } + + +def score_passive_voice(text: str) -> dict: + """Score 0-20: less passive = more human.""" + sentences = re.split(r'[.!?]+', text) + sentences = [s.strip() for s in sentences if s.strip()] + n_sentences = max(1, len(sentences)) + + passive_count = 0 + for pattern in PASSIVE_PATTERNS: + passive_count += len(re.findall(pattern, text, re.IGNORECASE)) + + passive_ratio = passive_count / n_sentences + + if passive_ratio < 0.1: + score = 20 + elif passive_ratio < 0.2: + score = 16 + elif passive_ratio < 0.3: + score = 10 + elif passive_ratio < 0.4: + score = 5 + else: + score = 0 + + return { + "score": score, + "max": 20, + "passive_count": passive_count, + "passive_ratio": round(passive_ratio, 2), + "passive_pct": f"{round(passive_ratio * 100)}%", + } + + +def score_hedging(text: str) -> dict: + """Score 0-15: fewer hedges = more direct = more human.""" + text_lower = text.lower() + hits = [] + for phrase in HEDGING_PHRASES: + count = text_lower.count(phrase) + if count > 0: + hits.append((phrase, count)) + + total_hedges = sum(c for _, c in hits) + + if total_hedges == 0: + score = 15 + elif total_hedges == 1: + score = 12 + elif total_hedges == 2: + score = 8 + elif total_hedges == 3: + score = 4 + else: + score = 0 + + vague_hits = sum(text_lower.count(p) for p in VAGUE_AUTHORITY) + + return { + "score": score, + "max": 15, + "hedge_count": total_hedges, + "vague_authority_count": vague_hits, + "flagged_phrases": [f for f, _ in hits], + } + + +def score_em_dashes(text: str) -> dict: + """Score 0-10: moderate em-dash use is fine; overuse is a tell.""" + # Count em-dashes (—) and double-hyphen (--) used as em-dash + em_count = text.count('—') + text.count('--') + word_count = max(1, len(re.findall(r'\b\w+\b', text))) + per_100 = em_count / (word_count / 100) + + if per_100 < 0.5: + score = 10 # none or very rare: fine + elif per_100 < 1.5: + score = 8 # occasional: good + elif per_100 < 3: + score = 5 # frequent: suspicious + elif per_100 < 5: + score = 2 # overuse: likely AI + else: + score = 0 # compulsive: AI fingerprint + + return { + "score": score, + "max": 10, + "em_dash_count": em_count, + "per_100_words": round(per_100, 2), + } + + +def score_paragraph_variety(text: str) -> dict: + """Score 0-10: varied paragraph lengths = more human.""" + paragraphs = [p.strip() for p in text.split('\n\n') if p.strip() and not p.startswith('#')] + if len(paragraphs) < 3: + return {"score": 5, "max": 10, "note": "too few paragraphs to score"} + + lengths = [len(p.split()) for p in paragraphs] + avg = sum(lengths) / len(lengths) + variance = sum((l - avg) ** 2 for l in lengths) / len(lengths) + std_dev = math.sqrt(variance) + + # Has any single-sentence paragraphs? (hallmark of human writing) + has_short = any(l <= 15 for l in lengths) + has_long = any(l >= 80 for l in lengths) + + score = 0 + if std_dev >= 30: + score += 5 + elif std_dev >= 15: + score += 3 + elif std_dev >= 5: + score += 1 + + if has_short: + score += 3 + if has_long and std_dev >= 15: + score += 2 + + score = min(10, score) + return { + "score": score, + "max": 10, + "paragraph_count": len(paragraphs), + "paragraph_std_dev": round(std_dev, 1), + "has_short_paragraphs": has_short, + "avg_paragraph_words": round(avg, 1), + } + + +# ── Main scoring ────────────────────────────────────────────────────────────── + +def score_humanity(text: str) -> dict: + vocab = score_ai_vocabulary(text) + variance = score_sentence_variance(text) + passive = score_passive_voice(text) + hedging = score_hedging(text) + em = score_em_dashes(text) + paragraphs = score_paragraph_variety(text) + + total = vocab["score"] + variance["score"] + passive["score"] + hedging["score"] + em["score"] + paragraphs["score"] + + if total >= 85: + label = "Sounds human āœ…" + elif total >= 70: + label = "Mostly human — light edits needed" + elif total >= 50: + label = "Mixed — AI patterns detectable" + elif total >= 30: + label = "Robotic — significant rewrite needed" + else: + label = "AI fingerprint — full rewrite required šŸ”“" + + return { + "humanity_score": total, + "label": label, + "sections": { + "ai_vocabulary": vocab, + "sentence_variance": variance, + "passive_voice": passive, + "hedging": hedging, + "em_dashes": em, + "paragraph_variety": paragraphs, + } + } + + +def print_report(result: dict, label: str = "") -> None: + total = result["humanity_score"] + verdict = result["label"] + s = result["sections"] + + bar_filled = int(total / 5) + bar = "ā–ˆ" * bar_filled + "ā–‘" * (20 - bar_filled) + + print() + print("╔══════════════════════════════════════════╗") + print("ā•‘ HUMANIZER SCORER — REPORT ā•‘") + print("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•") + if label: + print(f" Input: {label}") + print() + print(f" HUMANITY SCORE: {total}/100") + print(f" [{bar}]") + print(f" Verdict: {verdict}") + print() + print(" ── Section Breakdown ──────────────────────") + + sections = [ + ("AI Vocabulary", s["ai_vocabulary"], 25), + ("Sentence Variance", s["sentence_variance"], 20), + ("Passive Voice", s["passive_voice"], 20), + ("Hedging Phrases", s["hedging"], 15), + ("Em-Dash Use", s["em_dashes"], 10), + ("Paragraph Variety", s["paragraph_variety"], 10), + ] + for name, sec, mx in sections: + sc = sec["score"] + bar2 = "ā–ˆ" * int(sc / mx * 10) + "ā–‘" * (10 - int(sc / mx * 10)) + print(f" {name:<20} {sc:>2}/{mx} [{bar2}]") + + print() + print(" ── Detected Issues ────────────────────────") + + v = s["ai_vocabulary"] + if v["ai_word_hits"] > 0: + terms = ", ".join(v["flagged_terms"][:5]) + print(f" šŸ”“ AI vocabulary: {v['ai_word_hits']} hits — [{terms}]") + else: + print(" āœ… No AI vocabulary detected") + + sv = s["sentence_variance"] + if sv["std_dev"] < 5: + print(f" šŸ”“ Sentence rhythm robotic — std dev only {sv['std_dev']} (target: 8+)") + elif sv["std_dev"] < 8: + print(f" 🟔 Sentence variance low — {sv['std_dev']} (target: 8+)") + else: + print(f" āœ… Sentence variance good — {sv['std_dev']}") + + pv = s["passive_voice"] + if pv["passive_ratio"] > 0.3: + print(f" šŸ”“ Passive voice overuse — {pv['passive_pct']} of sentences") + elif pv["passive_ratio"] > 0.2: + print(f" 🟔 Passive voice elevated — {pv['passive_pct']}") + else: + print(f" āœ… Passive voice in range — {pv['passive_pct']}") + + hg = s["hedging"] + if hg["hedge_count"] > 2: + terms = ", ".join(hg["flagged_phrases"][:3]) + print(f" šŸ”“ Hedging overload — {hg['hedge_count']} phrases: [{terms}]") + elif hg["hedge_count"] > 0: + print(f" 🟔 Hedging present — {hg['hedge_count']} phrase(s): {hg['flagged_phrases']}") + else: + print(" āœ… No hedging detected") + + if hg["vague_authority_count"] > 0: + print(f" 🟔 Vague authority claims: {hg['vague_authority_count']} (e.g. 'studies show') — add citations") + + em = s["em_dashes"] + if em["per_100_words"] > 3: + print(f" 🟔 Em-dash overuse — {em['em_dash_count']} in piece ({em['per_100_words']}/100 words)") + + pg = s["paragraph_variety"] + if not pg.get("has_short_paragraphs"): + print(" 🟔 No short paragraphs found — add some 1-2 sentence paragraphs for rhythm") + + print() + print(" ── Priority Fixes ─────────────────────────") + + if v["ai_word_hits"] > 5: + print(" 1. Replace AI vocabulary (biggest impact)") + if sv["std_dev"] < 8: + print(" 2. Vary sentence length — mix short punchy sentences with longer ones") + if pv["passive_ratio"] > 0.25: + print(" 3. Flip passive sentences to active voice") + if hg["hedge_count"] > 2: + print(" 4. Cut hedging phrases — state claims directly") + if not pg.get("has_short_paragraphs"): + print(" 5. Add short paragraphs — even 1-sentence paragraphs help rhythm") + + if total >= 85: + print(" āœ… No priority fixes — content reads as human") + print() + + +def main(): + if len(sys.argv) == 1: + # Demo mode: compare human vs AI sample + print("[Demo mode — comparing human vs AI sample content]") + print() + print("═" * 50) + print("SAMPLE 1: Human-written content") + print("═" * 50) + r1 = score_humanity(SAMPLE_HUMAN) + print_report(r1, "Human sample") + + print("═" * 50) + print("SAMPLE 2: AI-generated content") + print("═" * 50) + r2 = score_humanity(SAMPLE_AI) + print_report(r2, "AI sample") + + print(f" Delta: Human scored {r1['humanity_score']}, AI scored {r2['humanity_score']}") + print(f" Difference: {r1['humanity_score'] - r2['humanity_score']} points") + print() + else: + filepath = sys.argv[1] + try: + with open(filepath, 'r', encoding='utf-8') as f: + text = f.read() + except FileNotFoundError: + print(f"Error: file not found: {filepath}", file=sys.stderr) + sys.exit(1) + + result = score_humanity(text) + print_report(result, filepath) + + if "--json" in sys.argv: + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/content-production/SKILL.md b/marketing-skill/content-production/SKILL.md new file mode 100644 index 0000000..7444c4d --- /dev/null +++ b/marketing-skill/content-production/SKILL.md @@ -0,0 +1,245 @@ +--- +name: content-production +description: "Full content production pipeline — takes a topic from blank page to published-ready piece. Use when you need to execute content: write a blog post, article, or guide end-to-end. Triggers: 'write a post about', 'draft an article', 'create content for', 'help me write', 'I need a blog post'. NOT for content strategy or calendar planning (use content-strategy). NOT for repurposing existing content (use content-repurposing). NOT for social captions only." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Content Production + +You are an expert content producer with deep experience across B2B SaaS, developer tools, and technical audiences. Your goal is to take a topic from zero to a finished, optimized piece that ranks, converts, and actually gets read. + +This is the execution engine — not the strategy layer. You're here to build, not plan. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. It contains brand voice, target audience, keyword targets, and writing examples. Use what's there — only ask for what's missing. + +Gather this context (ask in one shot, don't drip): + +### What you need +- **Topic / working title** — what are we writing about? +- **Target keyword** — primary search term (if SEO matters) +- **Audience** — who reads this and what do they already know? +- **Goal** — inform, convert, build authority, drive trial? +- **Approximate length** — 800 words? 2,000 words? Long-form? +- **Existing content** — do we have pieces this should link to? + +If the topic is vague ("write about AI"), push back: "Give me the specific angle — who's the reader, what problem are they solving?" + +## How This Skill Works + +Three modes. Start at whichever fits: + +### Mode 1: Research & Brief +You have a topic but no content yet. Do the research, map the competitive landscape, define the angle, and produce a content brief before writing a word. + +### Mode 2: Draft +Brief exists (either provided or from Mode 1). Write the full piece — intro, body, conclusion, headers — following the brief's structure and targeting parameters. + +### Mode 3: Optimize & Polish +Draft exists. Run the full optimization pass: SEO signals, readability, structure audit, meta tags, internal links, quality gates. Output a publish-ready version. + +You can run all 3 in sequence or jump directly to any mode. + +--- + +## Mode 1: Research & Brief + +### Step 1 — Competitive Content Analysis + +Before writing, understand what already ranks. For the target keyword: + +1. Identify the top 5-10 ranking pieces +2. Map their angles: Are they listicles? How-tos? Opinion pieces? Comparisons? +3. Find the gap: What's missing from the existing content? What angle is underserved? +4. Check search intent: Is the person trying to learn, compare, buy, or solve a specific problem? + +**Intent signals:** +| SERP Pattern | Intent | What to write | +|---|---|---| +| "What is / How to" dominate | Informational | Comprehensive guide or explainer | +| Product pages, reviews | Commercial | Comparison or buyer's guide | +| News, updates | Navigational/news | Skip unless you have unique angle | +| Forum results (Reddit, Quora) | Discovery | Opinionated piece with real perspective | + +### Step 2 — Source Gathering + +Collect 3-5 credible, citable sources before drafting. Prioritize: +- Original research (studies, surveys, reports) +- Official documentation +- Expert quotes you can attribute +- Data with specific numbers (not vague claims) + +**Rule:** If you can't cite a specific number, don't make a vague claim. "Studies show" is a red flag. Find the actual study. + +### Step 3 — Produce the Content Brief + +Fill in the [Content Brief Template](templates/content-brief-template.md). The brief defines: +- Target keyword + secondary keywords +- Reader profile and their job-to-be-done +- Angle and unique point of view +- Required sections and H2 structure +- Key claims to prove +- Internal links to include +- Competitive pieces to beat + +See [references/content-brief-guide.md](references/content-brief-guide.md) for how to write a brief that actually produces better drafts. + +--- + +## Mode 2: Draft + +You have a brief. Now write. + +### Outline First + +Build the header skeleton before filling in prose. A good outline: +- Has a hook-worthy H1 (keyword-included, curiosity-driving) +- Has 4-7 H2 sections that follow a logical progression +- Uses H3s sparingly — only when a section genuinely needs subdivision +- Ends with a CTA-adjacent conclusion + +Don't over-engineer the outline. If you're stuck on structure for more than 5 minutes, start writing and restructure later. + +### Intro Principles + +The intro has one job: make the reader believe this piece will answer their question. Get there in 3-4 sentences. + +Formula that works: +1. Name the problem or situation the reader is in +2. Name what this piece does about it +3. Optionally: give them a reason to trust you on this topic + +**What to avoid:** +- Starting with "In today's digital landscape..." (everyone does this) +- Starting with a question unless it's genuinely sharp +- Burying the point under 3 sentences of context-setting + +### Section-by-Section Approach + +For each H2 section: +1. State the main point in the first sentence (don't save it for the end) +2. Prove it with an example, stat, or comparison +3. Add one actionable takeaway before moving on + +Readers skim. Every section should deliver value on its own. + +### Conclusion + +Three elements: +1. Summary of the core argument (1-2 sentences) +2. The single most important thing to do next +3. CTA (if relevant to the goal) + +Don't pad the conclusion. If it's done, it's done. + +--- + +## Mode 3: Optimize & Polish + +Draft exists. Run this in order. + +### SEO Pass + +- **Title tag**: Contains primary keyword, under 60 characters, curiosity-driving +- **H1**: Different from title tag, keyword-rich, reads naturally +- **H2s**: At least 2-3 contain secondary keywords or related phrases +- **First paragraph**: Primary keyword appears in first 100 words +- **Image alt text**: Descriptive, includes keyword where natural +- **URL slug**: Short, keyword-first, no stop words + +### Readability Pass + +Run `scripts/content_scorer.py` on the draft. Target score: 70+. + +Manual checks: +- Average sentence length: aim for 15-20 words, mix it up +- No paragraph over 4 sentences (web readers need air) +- No jargon without explanation (for non-expert audiences) +- Active voice: find passive constructions and flip them + +### Structure Audit + +- Does the intro deliver on the headline's promise? +- Is every H2 section earning its place? (Cut if not) +- Are there at least 2 examples or concrete illustrations? +- Does the conclusion feel earned? + +### Internal Links + +Add 2-4 internal links minimum: +- Link from high-traffic existing pages to this piece +- Link from this piece to related existing content +- Anchor text should describe the destination, not be generic ("click here" is useless) + +### Meta Tags + +Write: +- **Meta description**: 150-160 characters, includes keyword, ends with action or hook +- **OG title / OG description**: Can differ from meta, optimized for social sharing +- **Canonical URL**: Set it, even if obvious + +### Quality Gates — Don't Publish Until These Pass + +See [references/optimization-checklist.md](references/optimization-checklist.md) for the full pre-publish checklist. + +Core gates: +- [ ] Primary keyword appears naturally 3-5x (not stuffed) +- [ ] Every factual claim has a source or is clearly labeled as opinion +- [ ] At least one image, table, or visual element breaks up text +- [ ] Intro doesn't start with a clichĆ© +- [ ] All internal links work +- [ ] Readability score ≄ 70 +- [ ] Word count is within 10% of target + +--- + +## Proactive Triggers + +Flag these without being asked: + +- **Thin content risk** — If the target keyword has high-authority competitors with 2,000+ word pieces, a 600-word post won't rank. Surface this upfront, before drafting starts. +- **Keyword cannibalization** — If existing content already targets this keyword, flag it. Publishing a second piece splits authority instead of building it. +- **Intent mismatch** — If the requested angle doesn't match search intent (e.g., writing a brand awareness piece for a transactional keyword), call it out. The piece will get traffic that doesn't convert. +- **Missing sources** — If the draft contains claims like "many companies" or "studies show" without citation, flag each one before the piece ships. +- **CTA/goal disconnect** — If the piece's goal is "drive trial signups" but there's no CTA, or the CTA is buried at paragraph 12, flag it. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---|---| +| Research & brief | Completed content brief: keyword targets, audience, angle, H2 structure, sources, competitive gaps | +| Full draft | Complete article with H1, H2s, intro, body, conclusion, and inline source markers | +| SEO optimization | Annotated draft with title tag, meta description, keyword placement audit, and OG copy | +| Readability audit | Scorer output + specific sentence-level edits flagged | +| Publish checklist | Completed gate checklist with pass/fail on each item | + +--- + +## Communication + +All output follows the structured standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding includes all three +- **Actions have owners and deadlines** — no "we should probably..." +- **Confidence tagging** — 🟢 verified / 🟔 medium / šŸ”“ assumed + +When reviewing drafts: flag issues → explain impact → give specific fix. Don't just say "improve readability." Say: "Paragraph 3 averages 32 words per sentence. Break the second sentence into two." + +--- + +## Related Skills + +- **content-strategy**: Use when deciding *what* to write — topics, calendar, pillar structure. NOT for writing the actual piece (that's this skill). +- **content-humanizer**: Use after drafting when the piece sounds robotic or AI-generated. Run this before the optimization pass. +- **ai-seo**: Use when optimizing specifically for AI search citation (ChatGPT, Perplexity, AI Overviews) in addition to traditional SEO. +- **copywriting**: Use for landing pages, CTAs, and conversion copy. NOT for long-form content (that's this skill). +- **seo-audit**: Use when auditing an existing content library for SEO gaps. NOT for single-piece production. diff --git a/marketing-skill/content-production/references/content-brief-guide.md b/marketing-skill/content-production/references/content-brief-guide.md new file mode 100644 index 0000000..660fc95 --- /dev/null +++ b/marketing-skill/content-production/references/content-brief-guide.md @@ -0,0 +1,146 @@ +# Content Brief Guide + +A brief isn't a writing assignment. It's a contract between the strategist and the writer — and when you're both the same person, it's still the contract between your thinking brain and your writing brain. Skip it and you'll rewrite. Do it right and the draft almost writes itself. + +--- + +## Why Briefs Fail (and How to Fix Them) + +Most briefs are too vague. They say "write about email marketing" without telling the writer: +- What's the specific angle? +- Who's the reader? +- What keywords matter? +- What tone? +- What should the reader do after? + +The result: a draft that misses the mark on every axis. + +**The fix:** Every field in the brief should be specific enough that two different writers would produce the same piece. + +--- + +## The Most Important Field: Angle + +The angle is the single most critical field in the brief. It's your differentiated take — not just "write about email marketing" but "why most email open rate benchmarks are useless and what to measure instead." + +**A good angle is:** +- One sentence +- Opinionated (takes a position) +- Different from what already ranks +- Grounded in something you actually know or have data on + +**A weak angle is:** +- "Comprehensive guide to email marketing" +- "Everything you need to know about..." +- "Best practices for..." + +If your angle sounds like a Wikipedia article, it's not an angle. + +--- + +## Keyword Targeting: What Actually Matters + +You don't need to stuff the brief with 20 keywords. You need: + +1. **One primary keyword** — the main search term this piece is targeting. Every SEO decision flows from this. +2. **2-4 secondary keywords** — related phrases that appear naturally. These expand coverage without forcing it. + +**How to find secondary keywords:** +- Look at "People Also Ask" on the SERP for your primary term +- Check what related terms appear in the top-ranking articles +- Use autocomplete on the search bar for your primary term + +**Common mistake:** Targeting a keyword that's informational (someone learning) with a piece that's commercial (someone buying). Match intent or waste the effort. + +--- + +## The Competitive Gap: Finding the Opening + +Before writing the brief's angle, look at what's ranking. You're not copying them — you're finding what they missed. + +**Gap patterns to look for:** + +| Pattern | What It Means | Opportunity | +|---|---|---| +| All top pieces are listicles | No deep explanation exists | Write the definitive guide | +| Top pieces are outdated (2+ years old) | Information is stale | Write the current-year version with updated data | +| Top pieces are generic (no real examples) | Theory without practice | Write a practitioner piece with real cases | +| Top pieces are all from the same POV | Perspective monopoly | Write the contrarian or underdog angle | +| Top pieces are very long but shallow | Word count without depth | Write shorter but genuinely useful | + +The gap is your angle. Find it before you brief. + +--- + +## Structure: H2s Are the Real Deliverable + +Writers often write vague outlines. "Introduction. Section 1. Conclusion." That's not a structure — that's a placeholder. + +Good H2s do three things: +1. **Promise value** — the reader knows what they'll learn +2. **Follow logic** — each section flows from the previous +3. **Hit keywords** — secondary terms appear naturally + +**Building the H2 structure:** +- Write the outline as if you're writing the table of contents for a useful reference book +- Each H2 should be a complete thought ("How to Write Subject Lines That Get Opened" not "Subject Lines") +- Sequence matters: don't put "Advanced Tactics" before "Why This Matters" + +**The rule of 5:** Most blog posts need 4-6 H2s. Fewer and it's shallow. More and it's scattered. + +--- + +## Sources: Non-Negotiable Before Drafting + +Writers who draft without sources invent claims. Then those claims go live on your website. + +**Minimum brief requirement:** 3 sources with specific data points or quotes identified. + +**Source quality hierarchy:** +1. Original research (surveys, studies, experiments you conducted) +2. Credible third-party research (academic papers, industry reports from named organizations) +3. Expert quotes (attributed, verifiable) +4. Strong case studies with specific metrics +5. Official documentation or standards + +**Red flag sources:** Anything that cites "a study" without naming it. Anything more than 5 years old in a fast-moving category. Competitor blog posts (they're also making stuff up). + +--- + +## Internal Linking: Plan It Before, Not After + +Most writers add internal links as an afterthought. This produces one problem: they link to whatever they remember, not what's most valuable. + +The brief should specify: +- 2-3 existing pieces this article should link to (and what anchor text to use) +- 1-2 existing pages that should link back to this article once published + +This prevents both orphaned content and missed link equity. + +--- + +## Success Criteria: If You Don't Define It, You Can't Measure It + +Every brief should answer: how will we know this piece worked? + +Not vague ("gets traffic") — specific: +- Ranks in top 5 for [keyword] within [timeframe] +- Drives X leads per month +- Achieves X% conversion rate on the CTA +- Gets cited / linked by [type of site] + +Define it now so you don't change the definition later. + +--- + +## Brief Anti-Patterns + +| Anti-pattern | Problem | Fix | +|---|---|---| +| "Write a comprehensive guide" | No angle, no differentiation | Define the specific take | +| Missing audience definition | Writer guesses; often wrong | Name the exact reader job title and pain | +| No sources listed | Writer invents facts | Find 3 sources before briefing | +| Vague keyword ("marketing") | No SEO targeting | Get specific: "email marketing for B2B SaaS" | +| H2s that are just topic labels | No promise, no structure | Rewrite as complete-thought headers | +| No internal links specified | Orphaned content | List 2-3 links before writing | +| No success criteria | Can't evaluate performance | Define at least one measurable outcome | diff --git a/marketing-skill/content-production/references/optimization-checklist.md b/marketing-skill/content-production/references/optimization-checklist.md new file mode 100644 index 0000000..0153189 --- /dev/null +++ b/marketing-skill/content-production/references/optimization-checklist.md @@ -0,0 +1,139 @@ +# Pre-Publish Optimization Checklist + +Run this before every piece goes live. Each section is a gate — fail a gate, fix it before moving on. + +--- + +## Gate 1: SEO Signals + +### Title & Headers +- [ ] H1 contains primary keyword (naturally, not forced) +- [ ] H1 is ≤70 characters +- [ ] At least 2 H2s contain secondary keywords or related phrases +- [ ] No two H2s are duplicates or near-duplicates +- [ ] H1 differs from the title tag (they can overlap but shouldn't be identical) + +### Keyword Presence +- [ ] Primary keyword appears in the first 100 words +- [ ] Primary keyword appears 3-5 times total (not more — stuffing tanks rankings) +- [ ] Keyword variations appear naturally throughout +- [ ] No keyword stuffing (reading it aloud sounds natural) + +### Meta & Technical +- [ ] Title tag: 50-60 characters, keyword-first where possible +- [ ] Meta description: 150-160 characters, includes keyword, ends with hook or action +- [ ] URL slug: short, keyword-first, lowercase, hyphens not underscores +- [ ] Canonical URL is set +- [ ] OG title and OG description written for social sharing + +### Images & Media +- [ ] At least one image present +- [ ] All images have descriptive alt text (keyword included where natural) +- [ ] Images are compressed (under 200KB each) +- [ ] Image filenames are descriptive (not IMG_4832.jpg) + +--- + +## Gate 2: Readability + +### Score +- [ ] Flesch Reading Ease score ≄ 60 (aim for 60-70 for professional audience; 70+ for general) +- [ ] Run `scripts/content_scorer.py` — overall score ≄ 70 + +### Sentence & Paragraph Structure +- [ ] Average sentence length ≤ 20 words +- [ ] No single paragraph exceeds 4 sentences +- [ ] No sentence exceeds 35 words (check and break if found) +- [ ] Sentence length varies — not all short, not all long + +### Voice & Clarity +- [ ] Active voice dominant (passive voice < 20% of sentences) +- [ ] No weasel words ("very," "really," "quite," "somewhat") +- [ ] No jargon without explanation (for non-expert audiences) +- [ ] All acronyms spelled out on first use +- [ ] Contractions used where natural (improves readability) + +--- + +## Gate 3: Structure & Content Quality + +### Opening +- [ ] Intro is ≤150 words +- [ ] Intro does not start with "In today's..." or "Welcome to..." +- [ ] Intro names the reader's problem or situation within the first 2 sentences +- [ ] Intro clearly signals what the reader will get from this piece +- [ ] No false promise in the intro (piece delivers what it hints at) + +### Body +- [ ] Every H2 section leads with its main point (buried leads = reader drop-off) +- [ ] At least 2 concrete examples, case studies, or data points +- [ ] All statistics and specific claims have citations or are labeled as estimates +- [ ] No fluff paragraphs (every paragraph earns its place — if removing it changes nothing, cut it) +- [ ] Visual break (table, list, callout, image) at least every 400 words + +### Conclusion +- [ ] Conclusion ≤150 words +- [ ] Summarizes the core argument (not just "in conclusion...") +- [ ] Includes one clear next step or CTA +- [ ] Doesn't introduce new arguments or ideas + +--- + +## Gate 4: Internal Linking + +- [ ] 2-4 internal links to existing content on the site +- [ ] Anchor text describes the destination (not "click here" or "this article") +- [ ] Links tested and confirmed working (no 404s) +- [ ] No excessive linking to the same page multiple times +- [ ] At least one high-traffic page links to this piece (plan this before publishing) + +--- + +## Gate 5: Factual Accuracy + +- [ ] Every statistic cited with source (year + organization) +- [ ] All external links go to credible sources (not competitors, not thin content) +- [ ] No claims made without evidence or without "in my experience" qualifier +- [ ] All product/feature mentions are accurate (check with product team if needed) +- [ ] Quotes are attributed correctly and not paraphrased beyond recognition +- [ ] No outdated information — check date-sensitive claims (pricing, regulations, stats) + +--- + +## Gate 6: Brand & Voice + +- [ ] Matches brand voice (check `marketing-context.md` if available) +- [ ] Consistent POV throughout (first person, second person, or third — pick one) +- [ ] Consistent tense (present or past — don't mix) +- [ ] No off-brand claims (anything that overpromises, contradicts other content, or sounds unlike us) +- [ ] CTA aligns with piece goal (don't pitch demo on an informational piece for beginners) + +--- + +## Gate 7: Final Readthrough + +Run a final read-aloud. Catch what scanning misses. + +- [ ] Read the full piece aloud — anything that makes you stumble, fix it +- [ ] The piece flows — section to section makes sense without re-reading +- [ ] The headline still feels earned after reading the piece +- [ ] You'd share this piece yourself (if not, it's not done) +- [ ] No placeholder text, formatting artifacts, or draft notes left in + +--- + +## Scoring Summary + +| Gate | Status | Notes | +|---|---|---| +| SEO Signals | āœ… / āŒ | | +| Readability | āœ… / āŒ | | +| Structure & Quality | āœ… / āŒ | | +| Internal Linking | āœ… / āŒ | | +| Factual Accuracy | āœ… / āŒ | | +| Brand & Voice | āœ… / āŒ | | +| Final Readthrough | āœ… / āŒ | | + +**Publish only when all 7 gates are green.** + +If you're skipping a gate, document why. Conscious tradeoffs are fine. Unconscious shortcuts aren't. diff --git a/marketing-skill/content-creator/scripts/brand_voice_analyzer.py b/marketing-skill/content-production/scripts/brand_voice_analyzer.py similarity index 100% rename from marketing-skill/content-creator/scripts/brand_voice_analyzer.py rename to marketing-skill/content-production/scripts/brand_voice_analyzer.py diff --git a/marketing-skill/content-production/scripts/content_scorer.py b/marketing-skill/content-production/scripts/content_scorer.py new file mode 100644 index 0000000..f87fbf0 --- /dev/null +++ b/marketing-skill/content-production/scripts/content_scorer.py @@ -0,0 +1,446 @@ +#!/usr/bin/env python3 +"""content_scorer.py — scores content 0-100 on readability, SEO, structure, and engagement.""" + +import sys +import re +import json +import math +from collections import Counter + +# ── Sample content for zero-config demo run ────────────────────────────────── +SAMPLE_CONTENT = """ +Title: How to Reduce Churn in SaaS: 7 Proven Tactics That Actually Work + +Introduction + +Most SaaS companies discover their churn problem too late — after the customer has already left. By then, the damage is done. In this guide, you'll learn seven tactics to reduce churn before it happens, backed by data from 200+ SaaS companies. + +## Why Customers Churn (It's Not What You Think) + +Customers don't churn because your product is bad. They churn because they never saw value. A study by Mixpanel found that 60% of users who churn never completed onboarding. That's a product adoption problem, not a satisfaction problem. + +Fix the adoption gap first. Everything else is downstream. + +## Tactic 1: Instrument Your Activation Funnel + +You can't fix what you can't see. Start by identifying your activation event — the moment users first experience your product's core value. For Slack, it's sending 2,000 messages. For Dropbox, it's saving a first file. + +Map the funnel from signup to activation. Find where users drop off. That's your highest-leverage intervention point. + +## Tactic 2: Segment Your Churn by Cohort + +Not all churn is equal. A user who churns in week one is a different problem than a user who churns in month six. Cohort analysis breaks this apart. + +Compare cohorts by: acquisition channel, onboarding path, company size, and feature usage. You'll find that certain cohorts churn 3-4x more than others. Focus retention efforts on your best cohorts first — don't try to save everyone. + +## Tactic 3: Build a Customer Health Score + +A health score is a composite signal that predicts churn before it happens. Common inputs include: login frequency, feature adoption rate, support ticket volume, and NPS response. + +Weight each signal by its correlation with retention in your historical data. A score below 40 should trigger a customer success outreach. Don't wait for the cancellation request. + +## Conclusion + +Churn is a lagging indicator. By the time you see it, the problem happened weeks ago. Build systems that surface early signals — activation gaps, usage drops, health score declines — and act on them before customers decide to leave. + +Start with one tactic. Instrument your activation funnel this week. +""" + +SAMPLE_KEYWORD = "reduce churn" +SAMPLE_TITLE = "How to Reduce Churn in SaaS: 7 Proven Tactics That Actually Work" + + +# ── Scoring functions ───────────────────────────────────────────────────────── + +def count_syllables(word: str) -> int: + """Approximate syllable count using vowel-group heuristic.""" + word = word.lower().strip(".,!?;:") + if not word: + return 0 + vowels = "aeiouy" + count = 0 + prev_vowel = False + for ch in word: + is_vowel = ch in vowels + if is_vowel and not prev_vowel: + count += 1 + prev_vowel = is_vowel + # Adjust for silent e + if word.endswith("e") and len(word) > 2: + count = max(1, count - 1) + return max(1, count) + + +def flesch_reading_ease(text: str) -> float: + """ + Flesch Reading Ease score. + 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words) + Higher = easier. Target: 60-70 for professional content. + """ + sentences = re.split(r'[.!?]+', text) + sentences = [s.strip() for s in sentences if s.strip()] + n_sentences = max(1, len(sentences)) + + words = re.findall(r'\b[a-zA-Z]+\b', text) + n_words = max(1, len(words)) + + n_syllables = sum(count_syllables(w) for w in words) + + asl = n_words / n_sentences # avg sentence length + asw = n_syllables / n_words # avg syllables per word + + score = 206.835 - (1.015 * asl) - (84.6 * asw) + return round(max(0.0, min(100.0, score)), 1) + + +def score_readability(text: str) -> dict: + """Score readability 0-25 (25% of total).""" + fre = flesch_reading_ease(text) + + # FRE → points (target 60-70 for B2B) + if fre >= 65: + fre_points = 15 + elif fre >= 55: + fre_points = 12 + elif fre >= 45: + fre_points = 8 + elif fre >= 35: + fre_points = 4 + else: + fre_points = 0 + + # Sentence length variance + sentences = re.split(r'[.!?]+', text) + sentences = [s.strip() for s in sentences if len(s.split()) > 2] + lengths = [len(s.split()) for s in sentences] + if len(lengths) > 1: + mean_len = sum(lengths) / len(lengths) + variance = sum((l - mean_len) ** 2 for l in lengths) / len(lengths) + std_dev = math.sqrt(variance) + variance_points = min(10, int(std_dev)) # good variance = high std dev + else: + variance_points = 0 + + total = min(25, fre_points + variance_points) + return { + "score": total, + "max": 25, + "flesch_reading_ease": fre, + "sentence_length_std_dev": round(math.sqrt(variance) if len(lengths) > 1 else 0, 1) + } + + +def score_seo(text: str, title: str = "", keyword: str = "") -> dict: + """Score SEO signals 0-25 (25% of total).""" + text_lower = text.lower() + title_lower = title.lower() + keyword_lower = keyword.lower() + + points = 0 + signals = {} + + # Title contains keyword + if keyword_lower and keyword_lower in title_lower: + points += 7 + signals["keyword_in_title"] = True + else: + signals["keyword_in_title"] = False + + # Keyword in first 100 words + first_100 = " ".join(re.findall(r'\b\w+\b', text_lower)[:100]) + if keyword_lower and keyword_lower in first_100: + points += 5 + signals["keyword_in_intro"] = True + else: + signals["keyword_in_intro"] = False + + # Keyword density (target 0.5-2%) + words = re.findall(r'\b\w+\b', text_lower) + n_words = max(1, len(words)) + kw_words = keyword_lower.split() + kw_count = 0 + for i in range(len(words) - len(kw_words) + 1): + if words[i:i+len(kw_words)] == kw_words: + kw_count += 1 + density = (kw_count * len(kw_words)) / n_words * 100 + signals["keyword_density_pct"] = round(density, 2) + signals["keyword_occurrences"] = kw_count + if 0.5 <= density <= 2.5: + points += 5 + elif kw_count > 0: + points += 2 + + # H2 headings present + h2_count = len(re.findall(r'^## .+', text, re.MULTILINE)) + signals["h2_count"] = h2_count + if h2_count >= 3: + points += 5 + elif h2_count >= 1: + points += 2 + + # Title length + signals["title_length"] = len(title) + if 30 <= len(title) <= 65: + points += 3 + + total = min(25, points) + return {"score": total, "max": 25, **signals} + + +def score_structure(text: str) -> dict: + """Score structure 0-25 (25% of total).""" + points = 0 + signals = {} + + lines = text.strip().split('\n') + + # Intro: first non-empty paragraph + paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()] + signals["paragraph_count"] = len(paragraphs) + + # Has intro (first paragraph isn't a heading) + if paragraphs and not paragraphs[0].startswith('#'): + intro_words = len(paragraphs[0].split()) + signals["intro_word_count"] = intro_words + if 30 <= intro_words <= 200: + points += 7 + elif intro_words > 0: + points += 3 + else: + signals["intro_word_count"] = 0 + + # Has H2 sections + h2s = [l for l in lines if l.startswith('## ')] + signals["h2_count"] = len(h2s) + if len(h2s) >= 4: + points += 8 + elif len(h2s) >= 2: + points += 5 + elif len(h2s) >= 1: + points += 2 + + # Has conclusion (last substantial paragraph) + last_para = paragraphs[-1] if paragraphs else "" + conclusion_words = len(last_para.split()) + signals["conclusion_word_count"] = conclusion_words + conclusion_signals = ['conclusion', 'summary', 'final', 'start ', 'next step', 'action'] + if any(sig in last_para.lower() for sig in conclusion_signals) and conclusion_words >= 20: + points += 7 + elif conclusion_words >= 30: + points += 4 + + # Average paragraph length (web = shorter is better) + para_lengths = [len(p.split()) for p in paragraphs if not p.startswith('#')] + if para_lengths: + avg_para_len = sum(para_lengths) / len(para_lengths) + signals["avg_paragraph_word_count"] = round(avg_para_len, 1) + if avg_para_len <= 80: + points += 3 + else: + signals["avg_paragraph_word_count"] = 0 + + total = min(25, points) + return {"score": total, "max": 25, **signals} + + +def score_engagement(text: str) -> dict: + """Score engagement signals 0-25 (25% of total).""" + points = 0 + signals = {} + text_lower = text.lower() + + # Questions (engage readers, prompt thought) + question_count = len(re.findall(r'\?', text)) + signals["question_count"] = question_count + if question_count >= 3: + points += 6 + elif question_count >= 1: + points += 3 + + # Specific numbers / data points + number_count = len(re.findall(r'\b\d+(?:\.\d+)?%?\b', text)) + signals["numbers_and_stats"] = number_count + if number_count >= 5: + points += 7 + elif number_count >= 2: + points += 4 + elif number_count >= 1: + points += 2 + + # Example signals + example_phrases = ['for example', 'for instance', 'such as', 'like ', 'e.g.', 'case study', + 'imagine', 'consider', 'let\'s say', 'here\'s', 'specifically'] + example_count = sum(text_lower.count(p) for p in example_phrases) + signals["example_signals"] = example_count + if example_count >= 3: + points += 6 + elif example_count >= 1: + points += 3 + + # Lists (bulleted or numbered) + list_items = len(re.findall(r'^\s*[-*•]\s+.+|^\s*\d+\.\s+.+', text, re.MULTILINE)) + signals["list_items"] = list_items + if list_items >= 5: + points += 6 + elif list_items >= 2: + points += 3 + + total = min(25, points) + return {"score": total, "max": 25, **signals} + + +# ── Main ────────────────────────────────────────────────────────────────────── + +def score_content(text: str, title: str = "", keyword: str = "") -> dict: + readability = score_readability(text) + seo = score_seo(text, title, keyword) + structure = score_structure(text) + engagement = score_engagement(text) + + total = readability["score"] + seo["score"] + structure["score"] + engagement["score"] + + grade = "D" + if total >= 90: + grade = "A+" + elif total >= 80: + grade = "A" + elif total >= 70: + grade = "B" + elif total >= 60: + grade = "C" + + return { + "total_score": total, + "grade": grade, + "sections": { + "readability": readability, + "seo": seo, + "structure": structure, + "engagement": engagement, + } + } + + +def print_report(result: dict, title: str, keyword: str) -> None: + total = result["total_score"] + grade = result["grade"] + s = result["sections"] + + bar_filled = int(total / 5) + bar = "ā–ˆ" * bar_filled + "ā–‘" * (20 - bar_filled) + + print() + print("╔══════════════════════════════════════════╗") + print("ā•‘ CONTENT SCORER — REPORT ā•‘") + print("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•") + print(f" Title: {title[:55] or '(not provided)'}") + print(f" Keyword: {keyword or '(not provided)'}") + print() + print(f" TOTAL SCORE: {total}/100 [{grade}]") + print(f" [{bar}]") + print() + print(" ── Section Breakdown ──────────────────────") + + sections = [ + ("Readability", s["readability"]), + ("SEO Signals", s["seo"]), + ("Structure", s["structure"]), + ("Engagement", s["engagement"]), + ] + for label, section in sections: + sc = section["score"] + mx = section["max"] + bar2_filled = int(sc / mx * 10) + bar2 = "ā–ˆ" * bar2_filled + "ā–‘" * (10 - bar2_filled) + print(f" {label:<14} {sc:>2}/{mx} [{bar2}]") + + print() + print(" ── Key Signals ────────────────────────────") + + r = s["readability"] + print(f" Flesch Reading Ease: {r['flesch_reading_ease']} (target: 60-70)") + print(f" Sentence length StDev: {r['sentence_length_std_dev']} (higher = more varied)") + + seo_d = s["seo"] + print(f" Keyword in title: {'āœ…' if seo_d.get('keyword_in_title') else 'āŒ'}") + print(f" Keyword in intro: {'āœ…' if seo_d.get('keyword_in_intro') else 'āŒ'}") + print(f" Keyword density: {seo_d.get('keyword_density_pct', 0)}% (target: 0.5-2.5%)") + print(f" H2 sections: {seo_d.get('h2_count', 0)}") + + st = s["structure"] + print(f" Intro word count: {st.get('intro_word_count', 0)} (target: 30-200)") + print(f" Avg paragraph length: {st.get('avg_paragraph_word_count', 0)} words (target: ≤80)") + + en = s["engagement"] + print(f" Questions: {en.get('question_count', 0)}") + print(f" Stats/numbers: {en.get('numbers_and_stats', 0)}") + print(f" Examples: {en.get('example_signals', 0)}") + + print() + print(" ── Recommendations ────────────────────────") + if r["flesch_reading_ease"] < 55: + print(" ⚠ Readability is low — shorten sentences and use simpler words") + if not seo_d.get("keyword_in_title"): + print(" ⚠ Primary keyword missing from title — add it naturally") + if not seo_d.get("keyword_in_intro"): + print(" ⚠ Primary keyword missing from first 100 words") + if seo_d.get("h2_count", 0) < 3: + print(" ⚠ Add more H2 sections — aim for at least 4") + if st.get("avg_paragraph_word_count", 0) > 100: + print(" ⚠ Paragraphs too long for web — break them up") + if en.get("question_count", 0) == 0: + print(" ⚠ Add at least one question to engage readers") + if en.get("numbers_and_stats", 0) < 2: + print(" ⚠ Thin on data — add specific numbers or stats") + if total >= 70: + print(" āœ… Content is publish-ready (score ≄ 70)") + else: + print(f" āŒ Score below 70 — address recommendations before publishing") + + print() + + +def main(): + title = "" + keyword = "" + text = "" + + if len(sys.argv) == 1: + # Demo mode — use embedded sample + print("[Demo mode — using embedded sample content]") + text = SAMPLE_CONTENT + title = SAMPLE_TITLE + keyword = SAMPLE_KEYWORD + else: + # Read from file + filepath = sys.argv[1] + keyword = sys.argv[2] if len(sys.argv) > 2 else "" + try: + with open(filepath, 'r', encoding='utf-8') as f: + text = f.read() + except FileNotFoundError: + print(f"Error: file not found: {filepath}", file=sys.stderr) + sys.exit(1) + + # Extract title from first H1 or first line + for line in text.split('\n'): + line = line.strip() + if line.startswith('# '): + title = line[2:].strip() + break + elif line.startswith('Title:'): + title = line[6:].strip() + break + if not title and text: + title = text.split('\n')[0][:80] + + result = score_content(text, title, keyword) + print_report(result, title, keyword) + + # JSON output for programmatic use + if "--json" in sys.argv: + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/content-creator/scripts/seo_optimizer.py b/marketing-skill/content-production/scripts/seo_optimizer.py similarity index 100% rename from marketing-skill/content-creator/scripts/seo_optimizer.py rename to marketing-skill/content-production/scripts/seo_optimizer.py diff --git a/marketing-skill/content-production/templates/content-brief-template.md b/marketing-skill/content-production/templates/content-brief-template.md new file mode 100644 index 0000000..c70d4a0 --- /dev/null +++ b/marketing-skill/content-production/templates/content-brief-template.md @@ -0,0 +1,126 @@ +# Content Brief Template + +> Fill in every field before writing starts. Blank fields mean assumptions. Assumptions mean rewrites. + +--- + +## Basic Info + +| Field | Value | +|---|---| +| **Working Title** | | +| **Target Publish Date** | | +| **Author / Owner** | | +| **Content Type** | Blog post / Guide / Case study / Comparison / Listicle | +| **Target Length** | ~___ words | +| **Goal** | Awareness / Lead gen / SEO / Thought leadership / Product education | + +--- + +## SEO Targeting + +| Field | Value | +|---|---| +| **Primary Keyword** | | +| **Monthly Search Volume** | | +| **Keyword Difficulty** | | +| **Secondary Keywords** (2-4) | | +| **Search Intent** | Informational / Commercial / Navigational | +| **SERP Features to Target** | Featured snippet / FAQ / People Also Ask | + +--- + +## Audience + +**Who is reading this?** +(Job title, company stage, pain point they're searching from) + +**What do they already know?** +(Level: beginner / intermediate / expert) + +**What do they want to walk away with?** +(The specific outcome or answer) + +**What's their biggest objection or doubt?** +(What might make them click away?) + +--- + +## Angle & POV + +**The core argument / unique angle:** +(One sentence — what's our take that's different from the competition?) + +**Why should they trust us on this?** +(Our authority, experience, or data that backs the angle) + +**What's the competition missing?** +(Specific gap in top-ranking content we're exploiting) + +--- + +## Structure + +**H1 (draft):** + +**Intro approach:** +(Hook type: stat / story / counterintuitive claim / problem statement) + +**H2 Outline:** +1. +2. +3. +4. +5. +(Add more as needed) + +**Conclusion approach:** +(Summary + CTA or next step) + +--- + +## Sources & Research + +| Source | Type | Key Claim / Data Point | +|---|---|---| +| | Study / Report | | +| | Expert quote | | +| | Official docs | | +| | Data / survey | | + +**Minimum 3 sources required before drafting.** + +--- + +## Internal Linking + +**Links FROM this piece (to existing content):** +- [Anchor text] → [URL / page title] +- [Anchor text] → [URL / page title] + +**Links TO this piece (from existing content):** +- [Existing page] → link to this once published + +--- + +## Competitive Pieces to Beat + +| URL | Word Count | What They Do Well | What They Miss | +|---|---|---|---| +| | | | | +| | | | | + +--- + +## Success Criteria + +- [ ] Ranks on page 1 for primary keyword within 6 months +- [ ] Achieves target engagement (avg time on page > ___ min) +- [ ] Generates ___ leads / clicks to product within 30 days +- [ ] Other: ___ + +--- + +## Notes / Special Instructions + +(Brand voice requirements, topics to avoid, tone calibration, product mentions) diff --git a/marketing-skill/content-strategy/SKILL.md b/marketing-skill/content-strategy/SKILL.md new file mode 100644 index 0000000..5c6993c --- /dev/null +++ b/marketing-skill/content-strategy/SKILL.md @@ -0,0 +1,401 @@ +--- +name: content-strategy +description: "When the user wants to plan a content strategy, decide what content to create, or figure out what topics to cover. Also use when the user mentions \"content strategy,\" \"what should I write about,\" \"content ideas,\" \"blog strategy,\" \"topic clusters,\" or \"content planning.\" For writing individual pieces, see copywriting. For SEO-specific audits, see seo-audit." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Content Strategy + +You are a content strategist. Your goal is to help plan content that drives traffic, builds authority, and generates leads by being either searchable, shareable, or both. + +## Before Planning + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Gather this context (ask if not provided): + +### 1. Business Context +- What does the company do? +- Who is the ideal customer? +- What's the primary goal for content? (traffic, leads, brand awareness, thought leadership) +- What problems does your product solve? + +### 2. Customer Research +- What questions do customers ask before buying? +- What objections come up in sales calls? +- What topics appear repeatedly in support tickets? +- What language do customers use to describe their problems? + +### 3. Current State +- Do you have existing content? What's working? +- What resources do you have? (writers, budget, time) +- What content formats can you produce? (written, video, audio) + +### 4. Competitive Landscape +- Who are your main competitors? +- What content gaps exist in your market? + +--- + +## Searchable vs Shareable + +Every piece of content must be searchable, shareable, or both. Prioritize in that order—search traffic is the foundation. + +**Searchable content** captures existing demand. Optimized for people actively looking for answers. + +**Shareable content** creates demand. Spreads ideas and gets people talking. + +### When Writing Searchable Content + +- Target a specific keyword or question +- Match search intent exactly—answer what the searcher wants +- Use clear titles that match search queries +- Structure with headings that mirror search patterns +- Place keywords in title, headings, first paragraph, URL +- Provide comprehensive coverage (don't leave questions unanswered) +- Include data, examples, and links to authoritative sources +- Optimize for AI/LLM discovery: clear positioning, structured content, brand consistency across the web + +### When Writing Shareable Content + +- Lead with a novel insight, original data, or counterintuitive take +- Challenge conventional wisdom with well-reasoned arguments +- Tell stories that make people feel something +- Create content people want to share to look smart or help others +- Connect to current trends or emerging problems +- Share vulnerable, honest experiences others can learn from + +--- + +## Content Types + +### Searchable Content Types + +**Use-Case Content** +Formula: [persona] + [use-case]. Targets long-tail keywords. +- "Project management for designers" +- "Task tracking for developers" +- "Client collaboration for freelancers" + +**Hub and Spoke** +Hub = comprehensive overview. Spokes = related subtopics. +``` +/topic (hub) +ā”œā”€ā”€ /topic/subtopic-1 (spoke) +ā”œā”€ā”€ /topic/subtopic-2 (spoke) +└── /topic/subtopic-3 (spoke) +``` +Create hub first, then build spokes. Interlink strategically. + +**Note:** Most content works fine under `/blog`. Only use dedicated hub/spoke URL structures for major topics with layered depth (e.g., Atlassian's `/agile` guide). For typical blog posts, `/blog/post-title` is sufficient. + +**Template Libraries** +High-intent keywords + product adoption. +- Target searches like "marketing plan template" +- Provide immediate standalone value +- Show how product enhances the template + +### Shareable Content Types + +**Thought Leadership** +- Articulate concepts everyone feels but hasn't named +- Challenge conventional wisdom with evidence +- Share vulnerable, honest experiences + +**Data-Driven Content** +- Product data analysis (anonymized insights) +- Public data analysis (uncover patterns) +- Original research (run experiments, share results) + +**Expert Roundups** +15-30 experts answering one specific question. Built-in distribution. + +**Case Studies** +Structure: Challenge → Solution → Results → Key learnings + +**Meta Content** +Behind-the-scenes transparency. "How We Got Our First $5k MRR," "Why We Chose Debt Over VC." + +For programmatic content at scale, see **programmatic-seo** skill. + +--- + +## Content Pillars and Topic Clusters + +Content pillars are the 3-5 core topics your brand will own. Each pillar spawns a cluster of related content. + +Most of the time, all content can live under `/blog` with good internal linking between related posts. Dedicated pillar pages with custom URL structures (like `/guides/topic`) are only needed when you're building comprehensive resources with multiple layers of depth. + +### How to Identify Pillars + +1. **Product-led**: What problems does your product solve? +2. **Audience-led**: What does your ICP need to learn? +3. **Search-led**: What topics have volume in your space? +4. **Competitor-led**: What are competitors ranking for? + +### Pillar Structure + +``` +Pillar Topic (Hub) +ā”œā”€ā”€ Subtopic Cluster 1 +│ ā”œā”€ā”€ Article A +│ ā”œā”€ā”€ Article B +│ └── Article C +ā”œā”€ā”€ Subtopic Cluster 2 +│ ā”œā”€ā”€ Article D +│ ā”œā”€ā”€ Article E +│ └── Article F +└── Subtopic Cluster 3 + ā”œā”€ā”€ Article G + ā”œā”€ā”€ Article H + └── Article I +``` + +### Pillar Criteria + +Good pillars should: +- Align with your product/service +- Match what your audience cares about +- Have search volume and/or social interest +- Be broad enough for many subtopics + +--- + +## Keyword Research by Buyer Stage + +Map topics to the buyer's journey using proven keyword modifiers: + +### Awareness Stage +Modifiers: "what is," "how to," "guide to," "introduction to" + +Example: If customers ask about project management basics: +- "What is Agile Project Management" +- "Guide to Sprint Planning" +- "How to Run a Standup Meeting" + +### Consideration Stage +Modifiers: "best," "top," "vs," "alternatives," "comparison" + +Example: If customers evaluate multiple tools: +- "Best Project Management Tools for Remote Teams" +- "Asana vs Trello vs Monday" +- "Basecamp Alternatives" + +### Decision Stage +Modifiers: "pricing," "reviews," "demo," "trial," "buy" + +Example: If pricing comes up in sales calls: +- "Project Management Tool Pricing Comparison" +- "How to Choose the Right Plan" +- "[Product] Reviews" + +### Implementation Stage +Modifiers: "templates," "examples," "tutorial," "how to use," "setup" + +Example: If support tickets show implementation struggles: +- "Project Template Library" +- "Step-by-Step Setup Tutorial" +- "How to Use [Feature]" + +--- + +## Content Ideation Sources + +### 1. Keyword Data + +If user provides keyword exports (Ahrefs, SEMrush, GSC), analyze for: +- Topic clusters (group related keywords) +- Buyer stage (awareness/consideration/decision/implementation) +- Search intent (informational, commercial, transactional) +- Quick wins (low competition + decent volume + high relevance) +- Content gaps (keywords competitors rank for that you don't) + +Output as prioritized table: +| Keyword | Volume | Difficulty | Buyer Stage | Content Type | Priority | + +### 2. Call Transcripts + +If user provides sales or customer call transcripts, extract: +- Questions asked → FAQ content or blog posts +- Pain points → problems in their own words +- Objections → content to address proactively +- Language patterns → exact phrases to use (voice of customer) +- Competitor mentions → what they compared you to + +Output content ideas with supporting quotes. + +### 3. Survey Responses + +If user provides survey data, mine for: +- Open-ended responses (topics and language) +- Common themes (30%+ mention = high priority) +- Resource requests (what they wish existed) +- Content preferences (formats they want) + +### 4. Forum Research + +Use web search to find content ideas: + +**Reddit:** `site:reddit.com [topic]` +- Top posts in relevant subreddits +- Questions and frustrations in comments +- Upvoted answers (validates what resonates) + +**Quora:** `site:quora.com [topic]` +- Most-followed questions +- Highly upvoted answers + +**Other:** Indie Hackers, Hacker News, Product Hunt, industry Slack/Discord + +Extract: FAQs, misconceptions, debates, problems being solved, terminology used. + +### 5. Competitor Analysis + +Use web search to analyze competitor content: + +**Find their content:** `site:competitor.com/blog` + +**Analyze:** +- Top-performing posts (comments, shares) +- Topics covered repeatedly +- Gaps they haven't covered +- Case studies (customer problems, use cases, results) +- Content structure (pillars, categories, formats) + +**Identify opportunities:** +- Topics you can cover better +- Angles they're missing +- Outdated content to improve on + +### 6. Sales and Support Input + +Extract from customer-facing teams: +- Common objections +- Repeated questions +- Support ticket patterns +- Success stories +- Feature requests and underlying problems + +--- + +## Prioritizing Content Ideas + +Score each idea on four factors: + +### 1. Customer Impact (40%) +- How frequently did this topic come up in research? +- What percentage of customers face this challenge? +- How emotionally charged was this pain point? +- What's the potential LTV of customers with this need? + +### 2. Content-Market Fit (30%) +- Does this align with problems your product solves? +- Can you offer unique insights from customer research? +- Do you have customer stories to support this? +- Will this naturally lead to product interest? + +### 3. Search Potential (20%) +- What's the monthly search volume? +- How competitive is this topic? +- Are there related long-tail opportunities? +- Is search interest growing or declining? + +### 4. Resource Requirements (10%) +- Do you have expertise to create authoritative content? +- What additional research is needed? +- What assets (graphics, data, examples) will you need? + +### Scoring Template + +| Idea | Customer Impact (40%) | Content-Market Fit (30%) | Search Potential (20%) | Resources (10%) | Total | +|------|----------------------|-------------------------|----------------------|-----------------|-------| +| Topic A | 8 | 9 | 7 | 6 | 8.0 | +| Topic B | 6 | 7 | 9 | 8 | 7.1 | + +--- + +## Output Format + +When creating a content strategy, provide: + +### 1. Content Pillars +- 3-5 pillars with rationale +- Subtopic clusters for each pillar +- How pillars connect to product + +### 2. Priority Topics +For each recommended piece: +- Topic/title +- Searchable, shareable, or both +- Content type (use-case, hub/spoke, thought leadership, etc.) +- Target keyword and buyer stage +- Why this topic (customer research backing) + +### 3. Topic Cluster Map +Visual or structured representation of how content interconnects. + +--- + +## Task-Specific Questions + +1. What patterns emerge from your last 10 customer conversations? +2. What questions keep coming up in sales calls? +3. Where are competitors' content efforts falling short? +4. What unique insights from customer research aren't being shared elsewhere? +5. Which existing content drives the most conversions, and why? + +--- + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- **No content plan exists** → Immediately propose a 3-pillar starter strategy with 10 seed topics before asking more questions. +- **User has content but low traffic** → Flag the searchable vs. shareable imbalance; run a quick audit of existing titles against keyword intent. +- **User is writing content without a keyword target** → Warn that effort may be wasted; offer to identify the right keyword before they start writing. +- **Content covers too many audiences** → Flag ICP dilution; recommend splitting pillars by persona or use-case. +- **Competitor content clearly outranks them on core topics** → Trigger a gap analysis and surface quick-win opportunities where competition is lower. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| A content strategy | 3-5 pillars with rationale, subtopic clusters per pillar, product-content connection map | +| Topic ideation | Prioritized topic table (keyword, volume, difficulty, buyer stage, content type, score) | +| A content calendar | Weekly/monthly plan with topic, format, target keyword, and distribution channel | +| Competitor analysis | Gap table showing competitor coverage vs. your coverage with opportunity ratings | +| A content brief | Single-page brief: goal, audience, keyword, outline, CTA, internal links, proof points | + +--- + +## Communication + +All output follows the structured communication standard: + +- **Bottom line first** — recommendation before rationale +- **What + Why + How** — every strategy has all three +- **Actions have owners and deadlines** — no "you might consider" +- **Confidence tagging** — 🟢 high confidence / 🟔 medium / šŸ”“ assumption + +Output format defaults: tables for prioritization, bullet lists for options, prose for rationale. Match depth to request — a quick question gets a quick answer, not a strategy doc. + +--- + +## Related Skills + +- **marketing-context**: USE as the foundation before any strategy work — reads product, audience, and brand context. NOT a substitute for this skill. +- **copywriting**: USE when a topic is approved and it's time to write the actual piece. NOT for deciding what to write about. +- **copy-editing**: USE to polish content drafts after writing. NOT for planning or strategy decisions. +- **social-content**: USE when distributing approved content to social platforms. NOT for organic search strategy. +- **marketing-ideas**: USE when brainstorming growth channels beyond content. NOT for deep keyword or topic planning. +- **seo-audit**: USE when auditing existing content for technical and on-page issues. NOT for creating new strategy from scratch. +- **content-production**: USE when scaling content volume with a repeatable production workflow. NOT for initial strategy definition. +- **content-humanizer**: USE when AI-generated content needs to sound more authentic. NOT for topic selection. diff --git a/marketing-skill/content-strategy/scripts/topic_cluster_mapper.py b/marketing-skill/content-strategy/scripts/topic_cluster_mapper.py new file mode 100755 index 0000000..268c160 --- /dev/null +++ b/marketing-skill/content-strategy/scripts/topic_cluster_mapper.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +""" +topic_cluster_mapper.py — Groups keywords/topics into content clusters +Usage: + python3 topic_cluster_mapper.py --file keywords.txt + python3 topic_cluster_mapper.py --json + python3 topic_cluster_mapper.py # demo mode (20 marketing topics) +""" + +import argparse +import json +import re +import sys +from collections import defaultdict + + +# --------------------------------------------------------------------------- +# Simple stemmer (no nltk) +# --------------------------------------------------------------------------- + +STOP_WORDS = { + "a", "an", "the", "and", "or", "but", "in", "on", "at", "to", "for", + "of", "with", "by", "from", "is", "are", "was", "were", "be", "been", + "how", "what", "why", "when", "where", "who", "which", "that", "this", + "it", "its", "do", "does", "your", "our", "my", "their", "we", "you", + "get", "make", "use", "using", "used", "can", "will", "should", "best", +} + + +def simple_stem(word: str) -> str: + """Very simple suffix-stripping stemmer.""" + w = word.lower() + if len(w) <= 3: + return w + # Order matters — try longer suffixes first + suffixes = [ + "ization", "isation", "ational", "fulness", "ousness", "iveness", + "iveness", "ingness", "ations", "nesses", "ators", "ation", + "ating", "alism", "ality", "alize", "alise", "ation", "ator", + "ness", "ment", "less", "tion", "sion", "tion", "ing", "ers", + "ies", "ied", "ily", "ful", "ous", "ive", "ize", "ise", "est", + "ed", "er", "ly", "al", "ic", "s", + ] + for sfx in suffixes: + if w.endswith(sfx) and len(w) - len(sfx) >= 3: + return w[: -len(sfx)] + return w + + +def extract_stems(topic: str) -> set: + words = re.findall(r"\b[a-zA-Z]+\b", topic.lower()) + return {simple_stem(w) for w in words if w not in STOP_WORDS and len(w) > 2} + + +# --------------------------------------------------------------------------- +# Clustering +# --------------------------------------------------------------------------- + +def compute_similarity(stems_a: set, stems_b: set) -> float: + """Jaccard similarity between two stem sets.""" + if not stems_a or not stems_b: + return 0.0 + intersection = stems_a & stems_b + union = stems_a | stems_b + return len(intersection) / len(union) + + +def build_clusters(topics: list, threshold: float = 0.15) -> list: + """ + Greedy clustering: assign each topic to the first cluster it's + similar-enough to; else start a new cluster. + """ + # Pre-compute stems + topic_stems = {t: extract_stems(t) for t in topics} + + clusters = [] # list of {"pillar": str, "topics": [str], "stems": set} + + for topic in topics: + t_stems = topic_stems[topic] + best_cluster = None + best_score = 0.0 + + for cluster in clusters: + sim = compute_similarity(t_stems, cluster["stems"]) + if sim > best_score: + best_score = sim + best_cluster = cluster + + if best_cluster and best_score >= threshold: + best_cluster["topics"].append(topic) + best_cluster["stems"] |= t_stems # grow cluster centroid + else: + clusters.append({ + "pillar": topic, + "topics": [topic], + "stems": set(t_stems), + }) + + # Identify best pillar: topic with most shared stems to others in cluster + for cluster in clusters: + if len(cluster["topics"]) == 1: + continue + all_stems = [topic_stems[t] for t in cluster["topics"]] + best_topic = cluster["topics"][0] + best_conn = 0 + for i, topic in enumerate(cluster["topics"]): + conn = sum( + len(topic_stems[topic] & topic_stems[other]) + for j, other in enumerate(cluster["topics"]) if i != j + ) + if conn > best_conn: + best_conn = conn + best_topic = topic + cluster["pillar"] = best_topic + + return clusters + + +def build_output(topics: list, clusters: list) -> dict: + cluster_output = [] + for i, c in enumerate(clusters, 1): + supporting = [t for t in c["topics"] if t != c["pillar"]] + cluster_output.append({ + "cluster_id": i, + "pillar_topic": c["pillar"], + "size": len(c["topics"]), + "supporting_topics": supporting, + "suggested_url_slug": re.sub(r"[^a-z0-9]+", "-", c["pillar"].lower()).strip("-"), + }) + + # Sort by cluster size desc + cluster_output.sort(key=lambda x: -x["size"]) + + return { + "total_topics": len(topics), + "total_clusters": len(clusters), + "clusters": cluster_output, + "recommendations": _make_recommendations(cluster_output), + } + + +def _make_recommendations(clusters: list) -> list: + recs = [] + large = [c for c in clusters if c["size"] >= 3] + singletons = [c for c in clusters if c["size"] == 1] + + if large: + recs.append(f"Create {len(large)} pillar page(s) for clusters with 3+ topics") + if singletons: + recs.append( + f"{len(singletons)} singleton topic(s) — consider merging or expanding to form mini-clusters" + ) + if clusters: + biggest = clusters[0] + recs.append( + f"Highest-priority cluster: '{biggest['pillar_topic']}' " + f"({biggest['size']} related topics) — start content here" + ) + return recs + + +# --------------------------------------------------------------------------- +# Demo topics +# --------------------------------------------------------------------------- + +DEMO_TOPICS = [ + "email marketing strategy", + "email subject line tips", + "email open rate optimization", + "email automation workflows", + "SEO keyword research", + "on-page SEO optimization", + "SEO content strategy", + "technical SEO audit", + "social media marketing", + "social media content calendar", + "Instagram marketing tips", + "LinkedIn marketing for B2B", + "content marketing ROI", + "content strategy planning", + "blog content ideas", + "landing page conversion rate", + "conversion rate optimization", + "A/B testing landing pages", + "paid ads budget allocation", + "Google Ads campaign setup", +] + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="Topic cluster mapper — groups keywords into content clusters." + ) + parser.add_argument("--file", help="Text file with one topic/keyword per line") + parser.add_argument("--threshold", type=float, default=0.15, + help="Similarity threshold for clustering (default: 0.15)") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r", encoding="utf-8") as f: + topics = [line.strip() for line in f if line.strip()] + else: + topics = DEMO_TOPICS + if not args.json: + print("No input provided — running in demo mode with 20 marketing topics.\n") + + if not topics: + print("No topics found.", file=sys.stderr) + sys.exit(1) + + clusters = build_clusters(topics, threshold=args.threshold) + output = build_output(topics, clusters) + + if args.json: + print(json.dumps(output, indent=2)) + return + + print("=" * 62) + print(f" TOPIC CLUSTER MAP {output['total_topics']} topics → {output['total_clusters']} clusters") + print("=" * 62) + + for cluster in output["clusters"]: + print(f"\n Cluster {cluster['cluster_id']} ({cluster['size']} topics)") + print(f" ā”Œā”€ PILLAR: {cluster['pillar_topic']}") + print(f" │ Slug: /{cluster['suggested_url_slug']}") + for st in cluster["supporting_topics"]: + print(f" └─ Supporting: {st}") + + print("\n" + "=" * 62) + print(" RECOMMENDATIONS") + print("=" * 62) + for rec in output["recommendations"]: + print(f" • {rec}") + print() + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/copy-editing/SKILL.md b/marketing-skill/copy-editing/SKILL.md new file mode 100644 index 0000000..bb95464 --- /dev/null +++ b/marketing-skill/copy-editing/SKILL.md @@ -0,0 +1,491 @@ +--- +name: copy-editing +description: "When the user wants to edit, review, or improve existing marketing copy. Also use when the user mentions 'edit this copy,' 'review my copy,' 'copy feedback,' 'proofread,' 'polish this,' 'make this better,' or 'copy sweep.' This skill provides a systematic approach to editing marketing copy through multiple focused passes." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Copy Editing + +You are an expert copy editor specializing in marketing and conversion copy. Your goal is to systematically improve existing copy through focused editing passes while preserving the core message. + +## Core Philosophy + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before editing. Use brand voice and customer language from that context to guide your edits. + +Good copy editing isn't about rewriting—it's about enhancing. Each pass focuses on one dimension, catching issues that get missed when you try to fix everything at once. + +**Key principles:** +- Don't change the core message; focus on enhancing it +- Multiple focused passes beat one unfocused review +- Each edit should have a clear reason +- Preserve the author's voice while improving clarity + +--- + +## The Seven Sweeps Framework + +Edit copy through seven sequential passes, each focusing on one dimension. After each sweep, loop back to check previous sweeps aren't compromised. + +### Sweep 1: Clarity + +**Focus:** Can the reader understand what you're saying? + +**What to check:** +- Confusing sentence structures +- Unclear pronoun references +- Jargon or insider language +- Ambiguous statements +- Missing context + +**Common clarity killers:** +- Sentences trying to say too much +- Abstract language instead of concrete +- Assuming reader knowledge they don't have +- Burying the point in qualifications + +**Process:** +1. Read through quickly, highlighting unclear parts +2. Don't correct yet—just note problem areas +3. After marking issues, recommend specific edits +4. Verify edits maintain the original intent + +**After this sweep:** Confirm the "Rule of One" (one main idea per section) and "You Rule" (copy speaks to the reader) are intact. + +--- + +### Sweep 2: Voice and Tone + +**Focus:** Is the copy consistent in how it sounds? + +**What to check:** +- Shifts between formal and casual +- Inconsistent brand personality +- Mood changes that feel jarring +- Word choices that don't match the brand + +**Common voice issues:** +- Starting casual, becoming corporate +- Mixing "we" and "the company" references +- Humor in some places, serious in others (unintentionally) +- Technical language appearing randomly + +**Process:** +1. Read aloud to hear inconsistencies +2. Mark where tone shifts unexpectedly +3. Recommend edits that smooth transitions +4. Ensure personality remains throughout + +**After this sweep:** Return to Clarity Sweep to ensure voice edits didn't introduce confusion. + +--- + +### Sweep 3: So What + +**Focus:** Does every claim answer "why should I care?" + +**What to check:** +- Features without benefits +- Claims without consequences +- Statements that don't connect to reader's life +- Missing "which means..." bridges + +**The So What test:** +For every statement, ask "Okay, so what?" If the copy doesn't answer that question with a deeper benefit, it needs work. + +āŒ "Our platform uses AI-powered analytics" +*So what?* +āœ… "Our AI-powered analytics surface insights you'd miss manually—so you can make better decisions in half the time" + +**Common So What failures:** +- Feature lists without benefit connections +- Impressive-sounding claims that don't land +- Technical capabilities without outcomes +- Company achievements that don't help the reader + +**Process:** +1. Read each claim and literally ask "so what?" +2. Highlight claims missing the answer +3. Add the benefit bridge or deeper meaning +4. Ensure benefits connect to real reader desires + +**After this sweep:** Return to Voice and Tone, then Clarity. + +--- + +### Sweep 4: Prove It + +**Focus:** Is every claim supported with evidence? + +**What to check:** +- Unsubstantiated claims +- Missing social proof +- Assertions without backup +- "Best" or "leading" without evidence + +**Types of proof to look for:** +- Testimonials with names and specifics +- Case study references +- Statistics and data +- Third-party validation +- Guarantees and risk reversals +- Customer logos +- Review scores + +**Common proof gaps:** +- "Trusted by thousands" (which thousands?) +- "Industry-leading" (according to whom?) +- "Customers love us" (show them saying it) +- Results claims without specifics + +**Process:** +1. Identify every claim that needs proof +2. Check if proof exists nearby +3. Flag unsupported assertions +4. Recommend adding proof or softening claims + +**After this sweep:** Return to So What, Voice and Tone, then Clarity. + +--- + +### Sweep 5: Specificity + +**Focus:** Is the copy concrete enough to be compelling? + +**What to check:** +- Vague language ("improve," "enhance," "optimize") +- Generic statements that could apply to anyone +- Round numbers that feel made up +- Missing details that would make it real + +**Specificity upgrades:** + +| Vague | Specific | +|-------|----------| +| Save time | Save 4 hours every week | +| Many customers | 2,847 teams | +| Fast results | Results in 14 days | +| Improve your workflow | Cut your reporting time in half | +| Great support | Response within 2 hours | + +**Common specificity issues:** +- Adjectives doing the work nouns should do +- Benefits without quantification +- Outcomes without timeframes +- Claims without concrete examples + +**Process:** +1. Highlight vague words and phrases +2. Ask "Can this be more specific?" +3. Add numbers, timeframes, or examples +4. Remove content that can't be made specific (it's probably filler) + +**After this sweep:** Return to Prove It, So What, Voice and Tone, then Clarity. + +--- + +### Sweep 6: Heightened Emotion + +**Focus:** Does the copy make the reader feel something? + +**What to check:** +- Flat, informational language +- Missing emotional triggers +- Pain points mentioned but not felt +- Aspirations stated but not evoked + +**Emotional dimensions to consider:** +- Pain of the current state +- Frustration with alternatives +- Fear of missing out +- Desire for transformation +- Pride in making smart choices +- Relief from solving the problem + +**Techniques for heightening emotion:** +- Paint the "before" state vividly +- Use sensory language +- Tell micro-stories +- Reference shared experiences +- Ask questions that prompt reflection + +**Process:** +1. Read for emotional impact—does it move you? +2. Identify flat sections that should resonate +3. Add emotional texture while staying authentic +4. Ensure emotion serves the message (not manipulation) + +**After this sweep:** Return to Specificity, Prove It, So What, Voice and Tone, then Clarity. + +--- + +### Sweep 7: Zero Risk + +**Focus:** Have we removed every barrier to action? + +**What to check:** +- Friction near CTAs +- Unanswered objections +- Missing trust signals +- Unclear next steps +- Hidden costs or surprises + +**Risk reducers to look for:** +- Money-back guarantees +- Free trials +- "No credit card required" +- "Cancel anytime" +- Social proof near CTA +- Clear expectations of what happens next +- Privacy assurances + +**Common risk issues:** +- CTA asks for commitment without earning trust +- Objections raised but not addressed +- Fine print that creates doubt +- Vague "Contact us" instead of clear next step + +**Process:** +1. Focus on sections near CTAs +2. List every reason someone might hesitate +3. Check if the copy addresses each concern +4. Add risk reversals or trust signals as needed + +**After this sweep:** Return through all previous sweeps one final time: Heightened Emotion, Specificity, Prove It, So What, Voice and Tone, Clarity. + +--- + +## Quick-Pass Editing Checks + +Use these for faster reviews when a full seven-sweep process isn't needed. + +### Word-Level Checks + +**Cut these words:** +- Very, really, extremely, incredibly (weak intensifiers) +- Just, actually, basically (filler) +- In order to (use "to") +- That (often unnecessary) +- Things, stuff (vague) + +**Replace these:** + +| Weak | Strong | +|------|--------| +| Utilize | Use | +| Implement | Set up | +| Leverage | Use | +| Facilitate | Help | +| Innovative | New | +| Robust | Strong | +| Seamless | Smooth | +| Cutting-edge | New/Modern | + +**Watch for:** +- Adverbs (usually unnecessary) +- Passive voice (switch to active) +- Nominalizations (verb → noun: "make a decision" → "decide") + +### Sentence-Level Checks + +- One idea per sentence +- Vary sentence length (mix short and long) +- Front-load important information +- Max 3 conjunctions per sentence +- No more than 25 words (usually) + +### Paragraph-Level Checks + +- One topic per paragraph +- Short paragraphs (2-4 sentences for web) +- Strong opening sentences +- Logical flow between paragraphs +- White space for scannability + +--- + +## Copy Editing Checklist + +### Before You Start +- [ ] Understand the goal of this copy +- [ ] Know the target audience +- [ ] Identify the desired action +- [ ] Read through once without editing + +### Clarity (Sweep 1) +- [ ] Every sentence is immediately understandable +- [ ] No jargon without explanation +- [ ] Pronouns have clear references +- [ ] No sentences trying to do too much + +### Voice & Tone (Sweep 2) +- [ ] Consistent formality level throughout +- [ ] Brand personality maintained +- [ ] No jarring shifts in mood +- [ ] Reads well aloud + +### So What (Sweep 3) +- [ ] Every feature connects to a benefit +- [ ] Claims answer "why should I care?" +- [ ] Benefits connect to real desires +- [ ] No impressive-but-empty statements + +### Prove It (Sweep 4) +- [ ] Claims are substantiated +- [ ] Social proof is specific and attributed +- [ ] Numbers and stats have sources +- [ ] No unearned superlatives + +### Specificity (Sweep 5) +- [ ] Vague words replaced with concrete ones +- [ ] Numbers and timeframes included +- [ ] Generic statements made specific +- [ ] Filler content removed + +### Heightened Emotion (Sweep 6) +- [ ] Copy evokes feeling, not just information +- [ ] Pain points feel real +- [ ] Aspirations feel achievable +- [ ] Emotion serves the message authentically + +### Zero Risk (Sweep 7) +- [ ] Objections addressed near CTA +- [ ] Trust signals present +- [ ] Next steps are crystal clear +- [ ] Risk reversals stated (guarantee, trial, etc.) + +### Final Checks +- [ ] No typos or grammatical errors +- [ ] Consistent formatting +- [ ] Links work (if applicable) +- [ ] Core message preserved through all edits + +--- + +## Common Copy Problems & Fixes + +### Problem: Wall of Features +**Symptom:** List of what the product does without why it matters +**Fix:** Add "which means..." after each feature to bridge to benefits + +### Problem: Corporate Speak +**Symptom:** "Leverage synergies to optimize outcomes" +**Fix:** Ask "How would a human say this?" and use those words + +### Problem: Weak Opening +**Symptom:** Starting with company history or vague statements +**Fix:** Lead with the reader's problem or desired outcome + +### Problem: Buried CTA +**Symptom:** The ask comes after too much buildup, or isn't clear +**Fix:** Make the CTA obvious, early, and repeated + +### Problem: No Proof +**Symptom:** "Customers love us" with no evidence +**Fix:** Add specific testimonials, numbers, or case references + +### Problem: Generic Claims +**Symptom:** "We help businesses grow" +**Fix:** Specify who, how, and by how much + +### Problem: Mixed Audiences +**Symptom:** Copy tries to speak to everyone, resonates with no one +**Fix:** Pick one audience and write directly to them + +### Problem: Feature Overload +**Symptom:** Listing every capability, overwhelming the reader +**Fix:** Focus on 3-5 key benefits that matter most to the audience + +--- + +## Working with Copy Sweeps + +When editing collaboratively: + +1. **Run a sweep and present findings** - Show what you found, why it's an issue +2. **Recommend specific edits** - Don't just identify problems; propose solutions +3. **Request the updated copy** - Let the author make final decisions +4. **Verify previous sweeps** - After each round of edits, re-check earlier sweeps +5. **Repeat until clean** - Continue until a full sweep finds no new issues + +This iterative process ensures each edit doesn't create new problems while respecting the author's ownership of the copy. + +--- + +## References + +- [Plain English Alternatives](references/plain-english-alternatives.md): Replace complex words with simpler alternatives + +--- + +## Task-Specific Questions + +1. What's the goal of this copy? (Awareness, conversion, retention) +2. What action should readers take? +3. Are there specific concerns or known issues? +4. What proof/evidence do you have available? + +--- + +## When to Use Each Skill + +| Task | Skill to Use | +|------|--------------| +| Writing new page copy from scratch | copywriting | +| Reviewing and improving existing copy | copy-editing (this skill) | +| Editing copy you just wrote | copy-editing (this skill) | +| Structural or strategic page changes | page-cro | + +--- + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- **Copy is submitted for editing without a stated goal** → Ask for the target action and audience before starting any sweeps; editing without this context guarantees misaligned feedback. +- **Multiple tone shifts detected** → Flag Sweep 2 failure immediately; note the specific lines where voice breaks and propose fixes before continuing. +- **Features outnumber benefits 2:1 or more** → Raise the "So What" alarm early in the review; this is the single most common conversion killer. +- **Superlatives without proof** ("best," "leading," "most trusted") → Flag each instance in Sweep 4 and request the evidence or softer language alternatives. +- **CTA is vague or buried** → Call this out in Sweep 7 before delivering any other feedback — it's the highest-impact fix. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| A full copy review | Seven-sweep structured report with specific issues, proposed edits, and rationale for each change | +| A quick copy pass | Word- and sentence-level edits with tracked-change style annotations | +| A copy editing checklist run | Completed checklist with pass/fail per section and priority fixes | +| Specific sweep only (e.g., Clarity) | Focused report for that sweep with before/after examples | +| Final polish | Clean edited version of the copy with a summary of all changes made | + +--- + +## Communication + +All output follows the structured communication standard: + +- **Bottom line first** — state the overall copy health before diving into issues +- **What + Why + How** — every flagged issue gets: what's wrong, why it hurts conversion, how to fix it +- **Edits have reasons** — never change words without explaining the principle +- **Confidence tagging** — 🟢 clear improvement / 🟔 judgment call / šŸ”“ needs author input + +Deliver findings sweep-by-sweep. Don't dump all issues at once. Prioritize by conversion impact, not writing preference. + +--- + +## Related Skills + +- **marketing-context**: USE as foundation before editing — provides brand voice, ICP, and tone benchmarks. NOT a substitute for reading the copy itself. +- **copywriting**: USE when the copy needs to be rewritten from scratch rather than edited. NOT for polishing existing drafts. +- **content-strategy**: USE when the problem is what to say, not how to say it. NOT for line-level improvements. +- **social-content**: USE when edited copy needs to be adapted for social platforms. NOT for page-level editing. +- **marketing-ideas**: USE when the client needs a new marketing angle entirely. NOT for editorial improvement. +- **content-humanizer**: USE when AI-generated copy needs to pass the human test before copy editing begins. NOT for structural review. +- **ab-test-setup**: USE when disagreement on copy variants needs data to resolve. NOT for the editing process itself. diff --git a/marketing-skill/copy-editing/references/plain-english-alternatives.md b/marketing-skill/copy-editing/references/plain-english-alternatives.md new file mode 100644 index 0000000..18db3b0 --- /dev/null +++ b/marketing-skill/copy-editing/references/plain-english-alternatives.md @@ -0,0 +1,376 @@ +# Plain English Alternatives + +Replace complex or pompous words with plain English alternatives. + +Source: Plain English Campaign A-Z of Alternative Words (2001), Australian Government Style Manual (2024), plainlanguage.gov + +--- + +## A + +| Complex | Plain Alternative | +|---------|-------------------| +| (an) absence of | no, none | +| abundance | enough, plenty, many | +| accede to | allow, agree to | +| accelerate | speed up | +| accommodate | meet, hold, house | +| accomplish | do, finish, complete | +| accordingly | so, therefore | +| acknowledge | thank you for, confirm | +| acquire | get, buy, obtain | +| additional | extra, more | +| adjacent | next to | +| advantageous | useful, helpful | +| advise | tell, say, inform | +| aforesaid | this, earlier | +| aggregate | total | +| alleviate | ease, reduce | +| allocate | give, share, assign | +| alternative | other, choice | +| ameliorate | improve | +| anticipate | expect | +| apparent | clear, obvious | +| appreciable | large, noticeable | +| appropriate | proper, right, suitable | +| approximately | about, roughly | +| ascertain | find out | +| assistance | help | +| at the present time | now | +| attempt | try | +| authorise | allow, let | + +--- + +## B + +| Complex | Plain Alternative | +|---------|-------------------| +| belated | late | +| beneficial | helpful, useful | +| bestow | give | +| by means of | by | + +--- + +## C + +| Complex | Plain Alternative | +|---------|-------------------| +| calculate | work out | +| cease | stop, end | +| circumvent | avoid, get around | +| clarification | explanation | +| commence | start, begin | +| communicate | tell, talk, write | +| competent | able | +| compile | collect, make | +| complete | fill in, finish | +| component | part | +| comprise | include, make up | +| (it is) compulsory | (you) must | +| conceal | hide | +| concerning | about | +| consequently | so | +| considerable | large, great, much | +| constitute | make up, form | +| consult | ask, talk to | +| consumption | use | +| currently | now | + +--- + +## D + +| Complex | Plain Alternative | +|---------|-------------------| +| deduct | take off | +| deem | treat as, consider | +| defer | delay, put off | +| deficiency | lack | +| delete | remove, cross out | +| demonstrate | show, prove | +| denote | show, mean | +| designate | name, appoint | +| despatch/dispatch | send | +| determine | decide, find out | +| detrimental | harmful | +| diminish | reduce, lessen | +| discontinue | stop | +| disseminate | spread, distribute | +| documentation | papers, documents | +| due to the fact that | because | +| duration | time, length | +| dwelling | home | + +--- + +## E + +| Complex | Plain Alternative | +|---------|-------------------| +| economical | cheap, good value | +| eligible | allowed, qualified | +| elucidate | explain | +| enable | allow | +| encounter | meet | +| endeavour | try | +| enquire | ask | +| ensure | make sure | +| entitlement | right | +| envisage | expect | +| equivalent | equal, the same | +| erroneous | wrong | +| establish | set up, show | +| evaluate | assess, test | +| excessive | too much | +| exclusively | only | +| exempt | free from | +| expedite | speed up | +| expenditure | spending | +| expire | run out | + +--- + +## F + +| Complex | Plain Alternative | +|---------|-------------------| +| fabricate | make | +| facilitate | help, make possible | +| finalise | finish, complete | +| following | after | +| for the purpose of | to, for | +| for the reason that | because | +| forthwith | now, at once | +| forward | send | +| frequently | often | +| furnish | give, provide | +| furthermore | also, and | + +--- + +## G-H + +| Complex | Plain Alternative | +|---------|-------------------| +| generate | produce, create | +| henceforth | from now on | +| hitherto | until now | + +--- + +## I + +| Complex | Plain Alternative | +|---------|-------------------| +| if and when | if, when | +| illustrate | show | +| immediately | at once, now | +| implement | carry out, do | +| imply | suggest | +| in accordance with | under, following | +| in addition to | and, also | +| in conjunction with | with | +| in excess of | more than | +| in lieu of | instead of | +| in order to | to | +| in receipt of | receive | +| in relation to | about | +| in respect of | about, for | +| in the event of | if | +| in the majority of instances | most, usually | +| in the near future | soon | +| in view of the fact that | because | +| inception | start | +| indicate | show, suggest | +| inform | tell | +| initiate | start, begin | +| insert | put in | +| instances | cases | +| irrespective of | despite | +| issue | give, send | + +--- + +## L-M + +| Complex | Plain Alternative | +|---------|-------------------| +| (a) large number of | many | +| liaise with | work with, talk to | +| locality | place, area | +| locate | find | +| magnitude | size | +| (it is) mandatory | (you) must | +| manner | way | +| modification | change | +| moreover | also, and | + +--- + +## N-O + +| Complex | Plain Alternative | +|---------|-------------------| +| negligible | small | +| nevertheless | but, however | +| notify | tell | +| notwithstanding | despite, even if | +| numerous | many | +| objective | aim, goal | +| (it is) obligatory | (you) must | +| obtain | get | +| occasioned by | caused by | +| on behalf of | for | +| on numerous occasions | often | +| on receipt of | when you get | +| on the grounds that | because | +| operate | work, run | +| optimum | best | +| option | choice | +| otherwise | or | +| outstanding | unpaid | +| owing to | because | + +--- + +## P + +| Complex | Plain Alternative | +|---------|-------------------| +| partially | partly | +| participate | take part | +| particulars | details | +| per annum | a year | +| perform | do | +| permit | let, allow | +| personnel | staff, people | +| peruse | read | +| possess | have, own | +| practically | almost | +| predominant | main | +| prescribe | set | +| preserve | keep | +| previous | earlier, before | +| principal | main | +| prior to | before | +| proceed | go ahead | +| procure | get | +| prohibit | ban, stop | +| promptly | quickly | +| provide | give | +| provided that | if | +| provisions | rules, terms | +| proximity | nearness | +| purchase | buy | +| pursuant to | under | + +--- + +## R + +| Complex | Plain Alternative | +|---------|-------------------| +| reconsider | think again | +| reduction | cut | +| referred to as | called | +| regarding | about | +| reimburse | repay | +| reiterate | repeat | +| relating to | about | +| remain | stay | +| remainder | rest | +| remuneration | pay | +| render | make, give | +| represent | stand for | +| request | ask | +| require | need | +| residence | home | +| retain | keep | +| revised | changed, new | + +--- + +## S + +| Complex | Plain Alternative | +|---------|-------------------| +| scrutinise | examine, check | +| select | choose | +| solely | only | +| specified | given, stated | +| state | say | +| statutory | legal, by law | +| subject to | depending on | +| submit | send, give | +| subsequent to | after | +| subsequently | later | +| substantial | large, much | +| sufficient | enough | +| supplement | add to | +| supplementary | extra | + +--- + +## T-U + +| Complex | Plain Alternative | +|---------|-------------------| +| terminate | end, stop | +| thereafter | then | +| thereby | by this | +| thus | so | +| to date | so far | +| transfer | move | +| transmit | send | +| ultimately | in the end | +| undertake | agree, do | +| uniform | same | +| utilise | use | + +--- + +## V-Z + +| Complex | Plain Alternative | +|---------|-------------------| +| variation | change | +| virtually | almost | +| visualise | imagine, see | +| ways and means | ways | +| whatsoever | any | +| with a view to | to | +| with effect from | from | +| with reference to | about | +| with regard to | about | +| with respect to | about | +| zone | area | + +--- + +## Phrases to Remove Entirely + +These phrases often add nothing. Delete them: + +- a total of +- absolutely +- actually +- all things being equal +- as a matter of fact +- at the end of the day +- at this moment in time +- basically +- currently (when "now" or nothing works) +- I am of the opinion that (use: I think) +- in due course (use: soon, or say when) +- in the final analysis +- it should be understood +- last but not least +- obviously +- of course +- quite +- really +- the fact of the matter is +- to all intents and purposes +- very diff --git a/marketing-skill/copy-editing/scripts/readability_scorer.py b/marketing-skill/copy-editing/scripts/readability_scorer.py new file mode 100755 index 0000000..882e70a --- /dev/null +++ b/marketing-skill/copy-editing/scripts/readability_scorer.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 +""" +readability_scorer.py — Readability metrics for marketing copy +Usage: + python3 readability_scorer.py --file copy.txt + echo "Your text here" | python3 readability_scorer.py + python3 readability_scorer.py # demo mode + python3 readability_scorer.py --json +""" + +import argparse +import json +import math +import re +import sys + + +# --------------------------------------------------------------------------- +# Word lists +# --------------------------------------------------------------------------- + +FILLER_WORDS = [ + "very", "really", "just", "actually", "basically", "literally", + "honestly", "totally", "absolutely", "definitely", "certainly", + "obviously", "clearly", "quite", "rather", "somewhat", "fairly", + "pretty", "simply", "truly", "genuinely", "essentially", +] + +# Simple passive voice detection: "was/were/is/are/been/being + past participle" +PASSIVE_PATTERN = re.compile( + r"\b(was|were|is|are|been|being|be|am)\s+(\w+ed|known|written|built|made|done|seen|given|taken|brought|thought|found|put|set|cut|read|let|hit|hurt|cost|led|felt|kept|left|meant|sent|spent|stood|told|wore|won|beat|lost|broke|chose|drove|flew|froze|grew|hid|rang|rode|rose|ran|sank|sang|spoke|swore|swam|threw|woke|wrote)\b", + re.IGNORECASE, +) + +ADVERB_PATTERN = re.compile(r"\b\w+ly\b", re.IGNORECASE) + +# Syllable estimation: count vowel groups +def count_syllables(word: str) -> int: + word = word.lower().strip(".,!?;:\"'") + if not word: + return 0 + # Silent e + if word.endswith("e") and len(word) > 2: + word = word[:-1] + count = len(re.findall(r"[aeiou]+", word)) + return max(1, count) + + +def split_sentences(text: str) -> list: + # Split on sentence-ending punctuation + parts = re.split(r"(?<=[.!?])\s+", text.strip()) + return [p.strip() for p in parts if p.strip()] + + +def split_words(text: str) -> list: + return re.findall(r"\b[a-zA-Z]+\b", text) + + +# --------------------------------------------------------------------------- +# Metrics +# --------------------------------------------------------------------------- + +def flesch_reading_ease(avg_sentence_len: float, avg_syllables: float) -> float: + """Flesch Reading Ease formula.""" + score = 206.835 - (1.015 * avg_sentence_len) - (84.6 * avg_syllables) + return round(max(0.0, min(100.0, score)), 1) + + +def flesch_kincaid_grade(avg_sentence_len: float, avg_syllables: float) -> float: + """Flesch-Kincaid Grade Level formula.""" + grade = (0.39 * avg_sentence_len) + (11.8 * avg_syllables) - 15.59 + return round(max(0.0, grade), 1) + + +def ease_label(score: float) -> str: + if score >= 90: return "Very Easy (5th grade)" + if score >= 80: return "Easy (6th grade)" + if score >= 70: return "Fairly Easy (7th grade)" + if score >= 60: return "Standard (8-9th grade)" + if score >= 50: return "Fairly Difficult (10-12th grade)" + if score >= 30: return "Difficult (College)" + return "Very Confusing (Professional)" + + +def analyze_text(text: str) -> dict: + sentences = split_sentences(text) + words = split_words(text) + + if not words: + return {"error": "No readable text found."} + + num_sentences = max(1, len(sentences)) + num_words = len(words) + + # Syllables + syllable_counts = [count_syllables(w) for w in words] + total_syllables = sum(syllable_counts) + + avg_sentence_len = num_words / num_sentences + avg_word_len = sum(len(w) for w in words) / num_words + avg_syllables_per_word = total_syllables / num_words + + fre = flesch_reading_ease(avg_sentence_len, avg_syllables_per_word) + fk_grade = flesch_kincaid_grade(avg_sentence_len, avg_syllables_per_word) + + # Passive voice + passive_matches = PASSIVE_PATTERN.findall(text) + passive_count = len(passive_matches) + passive_pct = round(passive_count / num_sentences * 100, 1) + + # Adverbs + adverb_matches = ADVERB_PATTERN.findall(text) + # Filter obvious non-adverbs + non_adverb = {"family", "early", "only", "likely", "nearly", "really", + "daily", "weekly", "monthly", "yearly", "friendly", "lovely", + "lonely", "lively", "elderly", "costly"} + adverbs = [a for a in adverb_matches if a.lower() not in non_adverb] + adverb_density = round(len(adverbs) / num_words * 100, 1) + + # Filler words + text_lower = text.lower() + word_tokens_lower = [w.lower() for w in words] + filler_found = {fw: word_tokens_lower.count(fw) for fw in FILLER_WORDS if fw in word_tokens_lower} + filler_total = sum(filler_found.values()) + + # Scoring: + # FRE already 0-100 (higher = easier = better for marketing copy) + # Target for marketing: 60-80 range + fre_score = fre # use as-is + + return { + "stats": { + "word_count": num_words, + "sentence_count": num_sentences, + "avg_sentence_length": round(avg_sentence_len, 1), + "avg_word_length": round(avg_word_len, 1), + "avg_syllables_per_word": round(avg_syllables_per_word, 2), + }, + "flesch_reading_ease": { + "score": fre, + "label": ease_label(fre), + "target": "60-80 for most marketing copy", + }, + "flesch_kincaid_grade": { + "grade_level": fk_grade, + "note": f"Equivalent to grade {fk_grade} reading level", + }, + "passive_voice": { + "count": passive_count, + "percentage": passive_pct, + "target": "<10%", + "pass": passive_pct < 10, + }, + "adverb_density": { + "count": len(adverbs), + "percentage": adverb_density, + "examples": list(set(adverbs))[:8], + "target": "<5%", + "pass": adverb_density < 5, + }, + "filler_words": { + "total_count": filler_total, + "breakdown": filler_found, + "target": "0-3 per 100 words", + "per_100_words": round(filler_total / num_words * 100, 1), + }, + "overall_score": round(fre), + } + + +# --------------------------------------------------------------------------- +# Demo text +# --------------------------------------------------------------------------- + +DEMO_TEXT = """ +Marketing copy needs to be clear, direct, and persuasive. When you write for your audience, +you should always think about what they actually want to hear. Really good copy is basically +about solving problems. It is very important to avoid using overly complicated language that +might confuse the reader. + +The best headlines are written by experts who truly understand their customers. A strong +call-to-action is absolutely essential for any landing page. You need to make sure that +every single word is earning its place on the page. + +Studies show that shorter sentences improve comprehension. The average reader processes +information faster when sentences contain fewer than 20 words. This is genuinely proven +by research. Passive voice constructions are often used by writers who want to sound +authoritative, but they can actually make copy feel distant and unclear. + +Focus on benefits, not features. Tell the reader what they will gain. Use numbers when +you can — "save 3 hours per week" beats "save time" every single time. Specificity +builds trust. Vague promises are ignored. +""" + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="Readability scorer for marketing copy — Flesch, passive voice, filler words." + ) + parser.add_argument("--file", help="Path to text file") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r", encoding="utf-8", errors="replace") as f: + text = f.read() + elif not sys.stdin.isatty(): + text = sys.stdin.read() + if not text.strip(): + text = DEMO_TEXT + if not args.json: + print("No input provided — running in demo mode.\n") + else: + text = DEMO_TEXT + if not args.json: + print("No input provided — running in demo mode.\n") + + result = analyze_text(text) + + if "error" in result: + print(f"Error: {result['error']}", file=sys.stderr) + sys.exit(1) + + if args.json: + print(json.dumps(result, indent=2)) + return + + fre = result["flesch_reading_ease"] + fk = result["flesch_kincaid_grade"] + stats = result["stats"] + passive = result["passive_voice"] + adverbs = result["adverb_density"] + fillers = result["filler_words"] + score = result["overall_score"] + + PASS = "āœ…" + FAIL = "āŒ" + + print("=" * 62) + print(f" READABILITY REPORT Flesch Score: {fre['score']}/100") + print("=" * 62) + print(f" {fre['label']}") + print(f" Target: {fre['target']}") + print() + print(f" šŸ“Š Stats") + print(f" Words: {stats['word_count']}") + print(f" Sentences: {stats['sentence_count']}") + print(f" Avg sentence length:{stats['avg_sentence_length']} words") + print(f" Avg word length: {stats['avg_word_length']} chars") + print(f" Syllables/word: {stats['avg_syllables_per_word']}") + print() + print(f" šŸ“ Flesch-Kincaid Grade Level: {fk['grade_level']}") + print(f" {fk['note']}") + print() + + pv_icon = PASS if passive["pass"] else FAIL + print(f" {pv_icon} Passive Voice: {passive['count']} instances ({passive['percentage']}%)") + print(f" Target: {passive['target']}") + + av_icon = PASS if adverbs["pass"] else FAIL + print(f" {av_icon} Adverb Density: {adverbs['count']} adverbs ({adverbs['percentage']}%)") + if adverbs["examples"]: + print(f" Examples: {', '.join(adverbs['examples'][:5])}") + + filler_ok = fillers["per_100_words"] <= 3 + fw_icon = PASS if filler_ok else FAIL + print(f" {fw_icon} Filler Words: {fillers['total_count']} total ({fillers['per_100_words']} per 100 words)") + if fillers["breakdown"]: + top = sorted(fillers["breakdown"].items(), key=lambda x: -x[1])[:5] + print(f" Top: {', '.join(f'{w}({c})' for w,c in top)}") + + print() + print("=" * 62) + score_bar_len = round(score / 10) + bar = "ā–ˆ" * score_bar_len + "ā–‘" * (10 - score_bar_len) + print(f" Readability Score: [{bar}] {score}/100") + print("=" * 62) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/copywriting/SKILL.md b/marketing-skill/copywriting/SKILL.md new file mode 100644 index 0000000..2d4b789 --- /dev/null +++ b/marketing-skill/copywriting/SKILL.md @@ -0,0 +1,296 @@ +--- +name: copywriting +description: "When the user wants to write, rewrite, or improve marketing copy for any page — including homepage, landing pages, pricing pages, feature pages, about pages, or product pages. Also use when the user says \"write copy for,\" \"improve this copy,\" \"rewrite this page,\" \"marketing copy,\" \"headline help,\" or \"CTA copy.\" For email copy, see email-sequence. For popup copy, see popup-cro." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Copywriting + +You are an expert conversion copywriter. Your goal is to write marketing copy that is clear, compelling, and drives action. + +## Before Writing + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Gather this context (ask if not provided): + +### 1. Page Purpose +- What type of page? (homepage, landing page, pricing, feature, about) +- What is the ONE primary action you want visitors to take? + +### 2. Audience +- Who is the ideal customer? +- What problem are they trying to solve? +- What objections or hesitations do they have? +- What language do they use to describe their problem? + +### 3. Product/Offer +- What are you selling or offering? +- What makes it different from alternatives? +- What's the key transformation or outcome? +- Any proof points (numbers, testimonials, case studies)? + +### 4. Context +- Where is traffic coming from? (ads, organic, email) +- What do visitors already know before arriving? + +--- + +## Copywriting Principles + +### Clarity Over Cleverness +If you have to choose between clear and creative, choose clear. + +### Benefits Over Features +Features: What it does. Benefits: What that means for the customer. + +### Specificity Over Vagueness +- Vague: "Save time on your workflow" +- Specific: "Cut your weekly reporting from 4 hours to 15 minutes" + +### Customer Language Over Company Language +Use words your customers use. Mirror voice-of-customer from reviews, interviews, support tickets. + +### One Idea Per Section +Each section should advance one argument. Build a logical flow down the page. + +--- + +## Writing Style Rules + +### Core Principles + +1. **Simple over complex** — "Use" not "utilize," "help" not "facilitate" +2. **Specific over vague** — Avoid "streamline," "optimize," "innovative" +3. **Active over passive** — "We generate reports" not "Reports are generated" +4. **Confident over qualified** — Remove "almost," "very," "really" +5. **Show over tell** — Describe the outcome instead of using adverbs +6. **Honest over sensational** — Never fabricate statistics or testimonials + +### Quick Quality Check + +- Jargon that could confuse outsiders? +- Sentences trying to do too much? +- Passive voice constructions? +- Exclamation points? (remove them) +- Marketing buzzwords without substance? + +For thorough line-by-line review, use the **copy-editing** skill after your draft. + +--- + +## Best Practices + +### Be Direct +Get to the point. Don't bury the value in qualifications. + +āŒ Slack lets you share files instantly, from documents to images, directly in your conversations + +āœ… Need to share a screenshot? Send as many documents, images, and audio files as your heart desires. + +### Use Rhetorical Questions +Questions engage readers and make them think about their own situation. +- "Hate returning stuff to Amazon?" +- "Tired of chasing approvals?" + +### Use Analogies When Helpful +Analogies make abstract concepts concrete and memorable. + +### Pepper in Humor (When Appropriate) +Puns and wit make copy memorable—but only if it fits the brand and doesn't undermine clarity. + +--- + +## Page Structure Framework + +### Above the Fold + +**Headline** +- Your single most important message +- Communicate core value proposition +- Specific > generic + +**Example formulas:** +- "{Achieve outcome} without {pain point}" +- "The {category} for {audience}" +- "Never {unpleasant event} again" +- "{Question highlighting main pain point}" + +**For comprehensive headline formulas**: See [references/copy-frameworks.md](references/copy-frameworks.md) + +**For natural transition phrases**: See [references/natural-transitions.md](references/natural-transitions.md) + +**Subheadline** +- Expands on headline +- Adds specificity +- 1-2 sentences max + +**Primary CTA** +- Action-oriented button text +- Communicate what they get: "Start Free Trial" > "Sign Up" + +### Core Sections + +| Section | Purpose | +|---------|---------| +| Social Proof | Build credibility (logos, stats, testimonials) | +| Problem/Pain | Show you understand their situation | +| Solution/Benefits | Connect to outcomes (3-5 key benefits) | +| How It Works | Reduce perceived complexity (3-4 steps) | +| Objection Handling | FAQ, comparisons, guarantees | +| Final CTA | Recap value, repeat CTA, risk reversal | + +**For detailed section types and page templates**: See [references/copy-frameworks.md](references/copy-frameworks.md) + +--- + +## CTA Copy Guidelines + +**Weak CTAs (avoid):** +- Submit, Sign Up, Learn More, Click Here, Get Started + +**Strong CTAs (use):** +- Start Free Trial +- Get [Specific Thing] +- See [Product] in Action +- Create Your First [Thing] +- Download the Guide + +**Formula:** [Action Verb] + [What They Get] + [Qualifier if needed] + +Examples: +- "Start My Free Trial" +- "Get the Complete Checklist" +- "See Pricing for My Team" + +--- + +## Page-Specific Guidance + +### Homepage +- Serve multiple audiences without being generic +- Lead with broadest value proposition +- Provide clear paths for different visitor intents + +### Landing Page +- Single message, single CTA +- Match headline to ad/traffic source +- Complete argument on one page + +### Pricing Page +- Help visitors choose the right plan +- Address "which is right for me?" anxiety +- Make recommended plan obvious + +### Feature Page +- Connect feature → benefit → outcome +- Show use cases and examples +- Clear path to try or buy + +### About Page +- Tell the story of why you exist +- Connect mission to customer benefit +- Still include a CTA + +--- + +## Voice and Tone + +Before writing, establish: + +**Formality level:** +- Casual/conversational +- Professional but friendly +- Formal/enterprise + +**Brand personality:** +- Playful or serious? +- Bold or understated? +- Technical or accessible? + +Maintain consistency, but adjust intensity: +- Headlines can be bolder +- Body copy should be clearer +- CTAs should be action-oriented + +--- + +## Output Format + +When writing copy, provide: + +### Page Copy +Organized by section: +- Headline, Subheadline, CTA +- Section headers and body copy +- Secondary CTAs + +### Annotations +For key elements, explain: +- Why you made this choice +- What principle it applies + +### Alternatives +For headlines and CTAs, provide 2-3 options: +- Option A: [copy] — [rationale] +- Option B: [copy] — [rationale] + +### Meta Content (if relevant) +- Page title (for SEO) +- Meta description + +--- + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- **Copy opens with "We" or the company name** → Flag it immediately; reframe to lead with the customer's outcome or problem. +- **Value proposition is vague** (e.g., "the best platform for teams") → Push for specificity: who, what outcome, how long. +- **Features are listed without benefits** → Add "which means..." bridges before delivering the draft. +- **No social proof is provided** → Flag this as a conversion risk and ask for testimonials, numbers, or case study references. +- **CTA uses weak verbs** (Submit, Learn More, Sign Up) → Propose action-outcome alternatives before finalising. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| Homepage copy | Full page copy organized by section: headline, subheadline, CTA, social proof, benefits, how it works, objection handling, final CTA | +| Landing page | Single-focus copy with headline, body, and one CTA — annotated with conversion rationale | +| Headline options | 5 headline variants using different formulas (outcome, pain, question, bold claim, category) | +| CTA copy | 3-5 CTA options with formula and rationale for each | +| Page copy review | Section-by-section feedback on clarity, benefit framing, and CTA strength | + +--- + +## Communication + +All output follows the structured communication standard: + +- **Bottom line first** — deliver the copy, then explain the choices +- **What + Why + How** — every copy decision has a principle behind it +- **Annotations are mandatory** — never ship copy without explaining the key choices +- **Confidence tagging** — 🟢 strong recommendation / 🟔 test this / šŸ”“ needs proof to land + +Always provide alternatives for high-stakes elements (headline, CTA). Never deliver one option and call it done. + +--- + +## Related Skills + +- **marketing-context**: USE as the foundation before writing — loads brand voice, ICP, and positioning context. NOT a substitute for this skill. +- **copy-editing**: USE after your first draft is complete to systematically polish and improve. NOT for writing new copy from scratch. +- **content-strategy**: USE when deciding what topics or pages to create before writing. NOT for the writing itself. +- **social-content**: USE when adapting finished copy for social platforms. NOT for long-form page copy. +- **marketing-ideas**: USE when brainstorming which marketing assets to build. NOT for writing the copy for those assets. +- **content-humanizer**: USE when AI-drafted copy sounds robotic or templated. NOT for strategic decisions. +- **ab-test-setup**: USE to design experiments testing copy variants. NOT for writing the copy itself. +- **email-sequence**: USE for email copywriting specifically. NOT for page or landing page copy. diff --git a/marketing-skill/copywriting/references/copy-frameworks.md b/marketing-skill/copywriting/references/copy-frameworks.md new file mode 100644 index 0000000..9957b96 --- /dev/null +++ b/marketing-skill/copywriting/references/copy-frameworks.md @@ -0,0 +1,338 @@ +# Copy Frameworks Reference + +Headline formulas, page section types, and structural templates. + +## Headline Formulas + +### Outcome-Focused + +**{Achieve desirable outcome} without {pain point}** +> Understand how users are really experiencing your site without drowning in numbers + +**{Achieve desirable outcome} by {how product makes it possible}** +> Generate more leads by seeing which companies visit your site + +**Turn {input} into {outcome}** +> Turn your hard-earned sales into repeat customers + +**[Achieve outcome] in [timeframe]** +> Get your tax refund in 10 days + +--- + +### Problem-Focused + +**Never {unpleasant event} again** +> Never miss a sales opportunity again + +**{Question highlighting the main pain point}** +> Hate returning stuff to Amazon? + +**Stop [pain]. Start [pleasure].** +> Stop chasing invoices. Start getting paid on time. + +--- + +### Audience-Focused + +**{Key feature/product type} for {target audience}** +> Advanced analytics for Shopify e-commerce + +**{Key feature/product type} for {target audience} to {what it's used for}** +> An online whiteboard for teams to ideate and brainstorm together + +**You don't have to {skills or resources} to {achieve desirable outcome}** +> With Ahrefs, you don't have to be an SEO pro to rank higher and get more traffic + +--- + +### Differentiation-Focused + +**The {opposite of usual process} way to {achieve desirable outcome}** +> The easiest way to turn your passion into income + +**The [category] that [key differentiator]** +> The CRM that updates itself + +--- + +### Proof-Focused + +**[Number] [people] use [product] to [outcome]** +> 50,000 marketers use Drip to send better emails + +**{Key benefit of your product}** +> Sound clear in online meetings + +--- + +### Additional Formulas + +**The simple way to {outcome}** +> The simple way to track your time + +**Finally, {category} that {benefit}** +> Finally, accounting software that doesn't suck + +**{Outcome} without {common pain}** +> Build your website without writing code + +**Get {benefit} from your {thing}** +> Get more revenue from your existing traffic + +**{Action verb} your {thing} like {admirable example}** +> Market your SaaS like a Fortune 500 + +**What if you could {desirable outcome}?** +> What if you could close deals 30% faster? + +**Everything you need to {outcome}** +> Everything you need to launch your course + +**The {adjective} {category} built for {audience}** +> The lightweight CRM built for startups + +--- + +## Landing Page Section Types + +### Core Sections + +**Hero (Above the Fold)** +- Headline + subheadline +- Primary CTA +- Supporting visual (product screenshot, hero image) +- Optional: Social proof bar + +**Social Proof Bar** +- Customer logos (recognizable > many) +- Key metric ("10,000+ teams") +- Star rating with review count +- Short testimonial snippet + +**Problem/Pain Section** +- Articulate their problem better than they can +- Create recognition ("that's exactly my situation") +- Hint at cost of not solving it + +**Solution/Benefits Section** +- Bridge from problem to your solution +- 3-5 key benefits (not 10) +- Each: headline + explanation + proof if available + +**How It Works** +- 3-4 numbered steps +- Reduces perceived complexity +- Each step: action + outcome + +**Final CTA Section** +- Recap value proposition +- Repeat primary CTA +- Risk reversal (guarantee, free trial) + +--- + +### Supporting Sections + +**Testimonials** +- Full quotes with names, roles, companies +- Photos when possible +- Specific results over vague praise +- Formats: quote cards, video, tweet embeds + +**Case Studies** +- Problem → Solution → Results +- Specific metrics and outcomes +- Customer name and context +- Can be snippets with "Read more" links + +**Use Cases** +- Different ways product is used +- Helps visitors self-identify +- "For marketers who need X" format + +**Personas / "Built For" Sections** +- Explicitly call out target audience +- "Perfect for [role]" blocks +- Addresses "Is this for me?" question + +**FAQ Section** +- Address common objections +- Good for SEO +- Reduces support burden +- 5-10 most common questions + +**Comparison Section** +- vs. competitors (name them or don't) +- vs. status quo (spreadsheets, manual processes) +- Tables or side-by-side format + +**Integrations / Partners** +- Logos of tools you connect with +- "Works with your stack" messaging +- Builds credibility + +**Founder Story / Manifesto** +- Why you built this +- What you believe +- Emotional connection +- Differentiates from faceless competitors + +**Demo / Product Tour** +- Interactive demos +- Video walkthroughs +- GIF previews +- Shows product in action + +**Pricing Preview** +- Teaser even on non-pricing pages +- Starting price or "from $X/mo" +- Moves decision-makers forward + +**Guarantee / Risk Reversal** +- Money-back guarantee +- Free trial terms +- "Cancel anytime" +- Reduces friction + +**Stats Section** +- Key metrics that build credibility +- "10,000+ customers" +- "4.9/5 rating" +- "$2M saved for customers" + +--- + +## Page Structure Templates + +### Feature-Heavy Page (Weak) + +``` +1. Hero +2. Feature 1 +3. Feature 2 +4. Feature 3 +5. Feature 4 +6. CTA +``` + +This is a list, not a persuasive narrative. + +--- + +### Varied, Engaging Page (Strong) + +``` +1. Hero with clear value prop +2. Social proof bar (logos or stats) +3. Problem/pain section +4. How it works (3 steps) +5. Key benefits (2-3, not 10) +6. Testimonial +7. Use cases or personas +8. Comparison to alternatives +9. Case study snippet +10. FAQ +11. Final CTA with guarantee +``` + +This tells a story and addresses objections. + +--- + +### Compact Landing Page + +``` +1. Hero (headline, subhead, CTA, image) +2. Social proof bar +3. 3 key benefits with icons +4. Testimonial +5. How it works (3 steps) +6. Final CTA with guarantee +``` + +Good for ad landing pages where brevity matters. + +--- + +### Enterprise/B2B Landing Page + +``` +1. Hero (outcome-focused headline) +2. Logo bar (recognizable companies) +3. Problem section (business pain) +4. Solution overview +5. Use cases by role/department +6. Security/compliance section +7. Integration logos +8. Case study with metrics +9. ROI/value section +10. Contact/demo CTA +``` + +Addresses enterprise buyer concerns. + +--- + +### Product Launch Page + +``` +1. Hero with launch announcement +2. Video demo or walkthrough +3. Feature highlights (3-5) +4. Before/after comparison +5. Early testimonials +6. Launch pricing or early access offer +7. CTA with urgency +``` + +Good for ProductHunt, launches, or announcements. + +--- + +## Section Writing Tips + +### Problem Section + +Start with phrases like: +- "You know the feeling..." +- "If you're like most [role]..." +- "Every day, [audience] struggles with..." +- "We've all been there..." + +Then describe: +- The specific frustration +- The time/money wasted +- The impact on their work/life + +### Benefits Section + +For each benefit, include: +- **Headline**: The outcome they get +- **Body**: How it works (1-2 sentences) +- **Proof**: Number, testimonial, or example (optional) + +### How It Works Section + +Each step should be: +- **Numbered**: Creates sense of progress +- **Simple verb**: "Connect," "Set up," "Get" +- **Outcome-oriented**: What they get from this step + +Example: +1. Connect your tools (takes 2 minutes) +2. Set your preferences +3. Get automated reports every Monday + +### Testimonial Selection + +Best testimonials include: +- Specific results ("increased conversions by 32%") +- Before/after context ("We used to spend hours...") +- Role + company for credibility +- Something quotable and specific + +Avoid testimonials that just say: +- "Great product!" +- "Love it!" +- "Easy to use!" diff --git a/marketing-skill/copywriting/references/natural-transitions.md b/marketing-skill/copywriting/references/natural-transitions.md new file mode 100644 index 0000000..929116f --- /dev/null +++ b/marketing-skill/copywriting/references/natural-transitions.md @@ -0,0 +1,252 @@ +# Natural Transitions + +Transitional phrases to guide readers through your content. Good signposting improves readability, user engagement, and helps search engines understand content structure. + +Adapted from: University of Manchester Academic Phrasebank (2023), Plain English Campaign, web content best practices + +--- + +## Previewing Content Structure + +Use to orient readers and set expectations: + +- Here's what we'll cover... +- This guide walks you through... +- Below, you'll find... +- We'll start with X, then move to Y... +- First, let's look at... +- Let's break this down step by step. +- The sections below explain... + +--- + +## Introducing a New Topic + +- When it comes to X,... +- Regarding X,... +- Speaking of X,... +- Now let's talk about X. +- Another key factor is... +- X is worth exploring because... + +--- + +## Referring Back + +Use to connect ideas and reinforce key points: + +- As mentioned earlier,... +- As we covered above,... +- Remember when we discussed X? +- Building on that point,... +- Going back to X,... +- Earlier, we explained that... + +--- + +## Moving Between Sections + +- Now let's look at... +- Next up:... +- Moving on to... +- With that covered, let's turn to... +- Now that you understand X, here's Y. +- That brings us to... + +--- + +## Indicating Addition + +- Also,... +- Plus,... +- On top of that,... +- What's more,... +- Another benefit is... +- Beyond that,... +- In addition,... +- There's also... + +**Note:** Use "moreover" and "furthermore" sparingly. They can sound AI-generated when overused. + +--- + +## Indicating Contrast + +- However,... +- But,... +- That said,... +- On the flip side,... +- In contrast,... +- Unlike X, Y... +- While X is true, Y... +- Despite this,... + +--- + +## Indicating Similarity + +- Similarly,... +- Likewise,... +- In the same way,... +- Just like X, Y also... +- This mirrors... +- The same applies to... + +--- + +## Indicating Cause and Effect + +- So,... +- This means... +- As a result,... +- That's why... +- Because of this,... +- This leads to... +- The outcome?... +- Here's what happens:... + +--- + +## Giving Examples + +- For example,... +- For instance,... +- Here's an example:... +- Take X, for instance. +- Consider this:... +- A good example is... +- To illustrate,... +- Like when... +- Say you want to... + +--- + +## Emphasising Key Points + +- Here's the key takeaway:... +- The important thing is... +- What matters most is... +- Don't miss this:... +- Pay attention to... +- This is critical:... +- The bottom line?... + +--- + +## Providing Evidence + +Use when citing sources, data, or expert opinions: + +### Neutral attribution +- According to [Source],... +- [Source] reports that... +- Research shows that... +- Data from [Source] indicates... +- A study by [Source] found... + +### Expert quotes +- As [Expert] puts it,... +- [Expert] explains,... +- In the words of [Expert],... +- [Expert] notes that... + +### Supporting claims +- This is backed by... +- Evidence suggests... +- The numbers confirm... +- This aligns with findings from... + +--- + +## Summarising Sections + +- To recap,... +- Here's the short version:... +- In short,... +- The takeaway?... +- So what does this mean?... +- Let's pull this together:... +- Quick summary:... + +--- + +## Concluding Content + +- Wrapping up,... +- The bottom line is... +- Here's what to do next:... +- To sum up,... +- Final thoughts:... +- Ready to get started?... +- Now it's your turn. + +**Note:** Avoid "In conclusion" at the start of a paragraph. It's overused and signals AI writing. + +--- + +## Question-Based Transitions + +Useful for conversational tone and featured snippet optimization: + +- So what does this mean for you? +- But why does this matter? +- How do you actually do this? +- What's the catch? +- Sound complicated? It's not. +- Wondering where to start? +- Still not sure? Here's the breakdown. + +--- + +## List Introductions + +For numbered lists and step-by-step content: + +- Here's how to do it: +- Follow these steps: +- The process is straightforward: +- Here's what you need to know: +- Key things to consider: +- The main factors are: + +--- + +## Hedging Language + +For claims that need qualification or aren't absolute: + +- may, might, could +- tends to, generally +- often, usually, typically +- in most cases +- it appears that +- evidence suggests +- this can help +- many experts believe + +--- + +## Best Practice Guidelines + +1. **Match tone to audience**: B2B content can be slightly more formal; B2C often benefits from conversational transitions +2. **Vary your transitions**: Repeating the same phrase gets noticed (and not in a good way) +3. **Don't over-signpost**: Trust your reader; every sentence doesn't need a transition +4. **Use for scannability**: Transitions at paragraph starts help skimmers navigate +5. **Keep it natural**: Read aloud; if it sounds forced, simplify +6. **Front-load key info**: Put the important word or phrase early in the transition + +--- + +## Transitions to Avoid (AI Tells) + +These phrases are overused in AI-generated content: + +- "That being said,..." +- "It's worth noting that..." +- "At its core,..." +- "In today's digital landscape,..." +- "When it comes to the realm of..." +- "This begs the question..." +- "Let's delve into..." + +See the seo-audit skill's `references/ai-writing-detection.md` for a complete list of AI writing tells. diff --git a/marketing-skill/copywriting/scripts/headline_scorer.py b/marketing-skill/copywriting/scripts/headline_scorer.py new file mode 100755 index 0000000..5003bc5 --- /dev/null +++ b/marketing-skill/copywriting/scripts/headline_scorer.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +""" +headline_scorer.py — Scores headlines 0-100 +Usage: + python3 headline_scorer.py "Your headline here" + python3 headline_scorer.py --file headlines.txt + python3 headline_scorer.py --json + python3 headline_scorer.py # demo mode +""" + +import argparse +import json +import re +import sys + + +# --------------------------------------------------------------------------- +# Word lists +# --------------------------------------------------------------------------- + +POWER_WORDS = { + # urgency / scarcity + "now", "today", "instantly", "immediately", "urgent", "limited", + "exclusive", "last", "hurry", "deadline", "expires", "fast", + # value / benefit + "free", "save", "proven", "guaranteed", "results", "boost", + "increase", "grow", "maximize", "unlock", "secret", "revealed", + "transform", "master", "ultimate", "best", "top", "powerful", + # curiosity / intrigue + "discover", "uncover", "surprising", "shocking", "hidden", + "unknown", "insider", "hack", "trick", "truth", + # social proof / authority + "experts", "researchers", "scientists", "officially", "certified", + "award-winning", "world-class", + # ease / simplicity + "easy", "simple", "effortless", "quick", "step-by-step", + "foolproof", "beginner", "without", + # negative triggers (fear/loss) + "avoid", "stop", "never", "mistake", "fail", "warning", "danger", + "worst", "deadly", "risky", +} + +EMOTIONAL_TRIGGERS = { + "love", "hate", "fear", "hope", "joy", "pain", "anger", "envy", + "trust", "doubt", "regret", "pride", "shame", "relief", "success", + "failure", "happiness", "frustration", "excitement", "anxiety", + "lonely", "powerful", "confident", "inspired", +} + +JARGON_WORDS = { + "synergy", "leverage", "disruptive", "paradigm", "scalable", + "bandwidth", "circle back", "ping", "holistic", "ecosystem", + "utilize", "facilitate", "ideate", "incentivize", "stakeholders", + "deliverables", "actionable", "bespoke", "granular", "boil the ocean", + "low-hanging fruit", "move the needle", "thought leader", "deep dive", +} + + +# --------------------------------------------------------------------------- +# Scoring functions +# --------------------------------------------------------------------------- + +def tokenize(headline: str) -> list: + return re.findall(r"\b\w+(?:[-']\w+)*\b", headline.lower()) + + +def score_power_words(tokens: list) -> tuple: + found = [t for t in tokens if t in POWER_WORDS] + # 1 power word = 60pts, 2 = 85, 3+ = 100 + score = min(100, len(found) * 35 + (10 if found else 0)) + return score, found + + +def score_emotional_triggers(tokens: list) -> tuple: + found = [t for t in tokens if t in EMOTIONAL_TRIGGERS] + score = min(100, len(found) * 50) + return score, found + + +def score_numbers(headline: str) -> tuple: + numbers = re.findall(r"\b\d+(?:[,\.]\d+)?%?\b", headline) + score = 100 if numbers else 0 + return score, numbers + + +def score_length(tokens: list) -> tuple: + n = len(tokens) + if 6 <= n <= 12: + score = 100 + note = f"{n} words — optimal (6-12)" + elif n < 6: + score = max(0, 40 + (n - 1) * 12) + note = f"{n} words — too short (6-12 optimal)" + else: + score = max(0, 100 - (n - 12) * 10) + note = f"{n} words — too long (6-12 optimal)" + return score, note + + +def score_specificity(headline: str, tokens: list) -> tuple: + signals = [] + if re.search(r"\b\d+\b", headline): + signals.append("contains number") + if re.search(r"\b(in \d+|within \d+|\d+ days?|\d+ weeks?|\d+ months?|\d+ hours?|\d+ minutes?)\b", headline, re.I): + signals.append("timeframe") + if re.search(r"\b(how to|step|guide|checklist|strategy|system|framework|formula)\b", headline, re.I): + signals.append("concrete format") + if re.search(r"\b\d+%\b", headline): + signals.append("percentage") + score = min(100, len(signals) * 34) + return score, signals + + +def score_clarity(tokens: list) -> tuple: + found_jargon = [t for t in tokens if t in JARGON_WORDS] + score = max(0, 100 - len(found_jargon) * 30) + note = "No jargon detected" if not found_jargon else f"Jargon: {', '.join(found_jargon)}" + return score, note + + +# --------------------------------------------------------------------------- +# Aggregate +# --------------------------------------------------------------------------- + +WEIGHTS = { + "power_words": 0.25, + "emotional_triggers": 0.15, + "numbers": 0.15, + "length": 0.20, + "specificity": 0.15, + "clarity": 0.10, +} + + +def score_headline(headline: str) -> dict: + tokens = tokenize(headline) + + pw_score, pw_found = score_power_words(tokens) + et_score, et_found = score_emotional_triggers(tokens) + num_score, nums = score_numbers(headline) + len_score, len_note = score_length(tokens) + spec_score, spec_signals = score_specificity(headline, tokens) + clar_score, clar_note = score_clarity(tokens) + + breakdown = { + "power_words": {"score": pw_score, "found": pw_found, "weight": "25%"}, + "emotional_triggers": {"score": et_score, "found": et_found, "weight": "15%"}, + "numbers": {"score": num_score, "found": nums, "weight": "15%"}, + "length": {"score": len_score, "note": len_note, "weight": "20%"}, + "specificity": {"score": spec_score, "signals": spec_signals, "weight": "15%"}, + "clarity": {"score": clar_score, "note": clar_note, "weight": "10%"}, + } + + overall = round(sum( + breakdown[k]["score"] * WEIGHTS[k] + for k in WEIGHTS + )) + + grade = "A" if overall >= 85 else "B" if overall >= 70 else "C" if overall >= 55 else "D" if overall >= 40 else "F" + + return { + "headline": headline, + "overall_score": overall, + "grade": grade, + "breakdown": breakdown, + } + + +# --------------------------------------------------------------------------- +# Demo headlines +# --------------------------------------------------------------------------- + +DEMO_HEADLINES = [ + "10 Proven Ways to Double Your Email Open Rates in 30 Days", + "Marketing Tips for Better Results", + "Unlock the Secret Formula That Top Experts Use to Grow Revenue Fast", + "How to Leverage Synergistic Paradigms for Scalable Growth", + "Our New Product Is Now Available", +] + + +# --------------------------------------------------------------------------- +# Output helpers +# --------------------------------------------------------------------------- + +def print_result(result: dict): + h = result["headline"] + score = result["overall_score"] + grade = result["grade"] + print(f"\n{'─' * 60}") + print(f" Headline: {h}") + print(f" Score: {score}/100 Grade: {grade}") + print(f"{'─' * 60}") + bd = result["breakdown"] + rows = [ + ("Power Words", "power_words", lambda r: f"found: {r['found'] or 'none'}"), + ("Emotional Trigger", "emotional_triggers", lambda r: f"found: {r['found'] or 'none'}"), + ("Numbers/Stats", "numbers", lambda r: f"found: {r['found'] or 'none'}"), + ("Length", "length", lambda r: r["note"]), + ("Specificity", "specificity", lambda r: f"signals: {r['signals'] or 'none'}"), + ("Clarity", "clarity", lambda r: r["note"]), + ] + for label, key, detail_fn in rows: + r = bd[key] + bar_len = round(r["score"] / 10) + bar = "ā–ˆ" * bar_len + "ā–‘" * (10 - bar_len) + detail = detail_fn(r) + print(f" {label:<20} [{bar}] {r['score']:>3}/100 {detail}") + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="Headline scorer — rates headlines 0-100 across 6 dimensions." + ) + parser.add_argument("headline", nargs="?", help="Single headline to score") + parser.add_argument("--file", help="Text file with one headline per line") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.headline: + headlines = [args.headline] + elif args.file: + with open(args.file, "r", encoding="utf-8") as f: + headlines = [line.strip() for line in f if line.strip()] + else: + headlines = DEMO_HEADLINES + if not args.json: + print("No input provided — running in demo mode.\n") + print("Demo headlines:") + for h in headlines: + print(f" • {h}") + + results = [score_headline(h) for h in headlines] + + if args.json: + print(json.dumps(results, indent=2)) + return + + for result in results: + print_result(result) + + if len(results) > 1: + avg = round(sum(r["overall_score"] for r in results) / len(results)) + best = max(results, key=lambda r: r["overall_score"]) + print(f"\n{'=' * 60}") + print(f" {len(results)} headlines analyzed | Avg score: {avg}/100") + print(f" Best: \"{best['headline'][:50]}\" ({best['overall_score']}/100)") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/email-sequence/SKILL.md b/marketing-skill/email-sequence/SKILL.md new file mode 100644 index 0000000..4950eb5 --- /dev/null +++ b/marketing-skill/email-sequence/SKILL.md @@ -0,0 +1,340 @@ +--- +name: email-sequence +description: When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions "email sequence," "drip campaign," "nurture sequence," "onboarding emails," "welcome sequence," "re-engagement emails," "email automation," or "lifecycle emails." For in-app onboarding, see onboarding-cro. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Email Sequence Design + +You are an expert in email marketing and automation. Your goal is to create email sequences that nurture relationships, drive action, and move people toward conversion. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before creating a sequence, understand: + +1. **Sequence Type** + - Welcome/onboarding sequence + - Lead nurture sequence + - Re-engagement sequence + - Post-purchase sequence + - Event-based sequence + - Educational sequence + - Sales sequence + +2. **Audience Context** + - Who are they? + - What triggered them into this sequence? + - What do they already know/believe? + - What's their current relationship with you? + +3. **Goals** + - Primary conversion goal + - Relationship-building goals + - Segmentation goals + - What defines success? + +--- + +## Core Principles + +### 1. One Email, One Job +- Each email has one primary purpose +- One main CTA per email +- Don't try to do everything + +### 2. Value Before Ask +- Lead with usefulness +- Build trust through content +- Earn the right to sell + +### 3. Relevance Over Volume +- Fewer, better emails win +- Segment for relevance +- Quality > frequency + +### 4. Clear Path Forward +- Every email moves them somewhere +- Links should do something useful +- Make next steps obvious + +--- + +## Email Sequence Strategy + +### Sequence Length +- Welcome: 3-7 emails +- Lead nurture: 5-10 emails +- Onboarding: 5-10 emails +- Re-engagement: 3-5 emails + +Depends on: +- Sales cycle length +- Product complexity +- Relationship stage + +### Timing/Delays +- Welcome email: Immediately +- Early sequence: 1-2 days apart +- Nurture: 2-4 days apart +- Long-term: Weekly or bi-weekly + +Consider: +- B2B: Avoid weekends +- B2C: Test weekends +- Time zones: Send at local time + +### Subject Line Strategy +- Clear > Clever +- Specific > Vague +- Benefit or curiosity-driven +- 40-60 characters ideal +- Test emoji (they're polarizing) + +**Patterns that work:** +- Question: "Still struggling with X?" +- How-to: "How to [achieve outcome] in [timeframe]" +- Number: "3 ways to [benefit]" +- Direct: "[First name], your [thing] is ready" +- Story tease: "The mistake I made with [topic]" + +### Preview Text +- Extends the subject line +- ~90-140 characters +- Don't repeat subject line +- Complete the thought or add intrigue + +--- + +## Sequence Types Overview + +### Welcome Sequence (Post-Signup) +**Length**: 5-7 emails over 12-14 days +**Goal**: Activate, build trust, convert + +Key emails: +1. Welcome + deliver promised value (immediate) +2. Quick win (day 1-2) +3. Story/Why (day 3-4) +4. Social proof (day 5-6) +5. Overcome objection (day 7-8) +6. Core feature highlight (day 9-11) +7. Conversion (day 12-14) + +### Lead Nurture Sequence (Pre-Sale) +**Length**: 6-8 emails over 2-3 weeks +**Goal**: Build trust, demonstrate expertise, convert + +Key emails: +1. Deliver lead magnet + intro (immediate) +2. Expand on topic (day 2-3) +3. Problem deep-dive (day 4-5) +4. Solution framework (day 6-8) +5. Case study (day 9-11) +6. Differentiation (day 12-14) +7. Objection handler (day 15-18) +8. Direct offer (day 19-21) + +### Re-Engagement Sequence +**Length**: 3-4 emails over 2 weeks +**Trigger**: 30-60 days of inactivity +**Goal**: Win back or clean list + +Key emails: +1. Check-in (genuine concern) +2. Value reminder (what's new) +3. Incentive (special offer) +4. Last chance (stay or unsubscribe) + +### Onboarding Sequence (Product Users) +**Length**: 5-7 emails over 14 days +**Goal**: Activate, drive to aha moment, upgrade +**Note**: Coordinate with in-app onboarding—email supports, doesn't duplicate + +Key emails: +1. Welcome + first step (immediate) +2. Getting started help (day 1) +3. Feature highlight (day 2-3) +4. Success story (day 4-5) +5. Check-in (day 7) +6. Advanced tip (day 10-12) +7. Upgrade/expand (day 14+) + +**For detailed templates**: See [references/sequence-templates.md](references/sequence-templates.md) + +--- + +## Email Types by Category + +### Onboarding Emails +- New users series +- New customers series +- Key onboarding step reminders +- New user invites + +### Retention Emails +- Upgrade to paid +- Upgrade to higher plan +- Ask for review +- Proactive support offers +- Product usage reports +- NPS survey +- Referral program + +### Billing Emails +- Switch to annual +- Failed payment recovery +- Cancellation survey +- Upcoming renewal reminders + +### Usage Emails +- Daily/weekly/monthly summaries +- Key event notifications +- Milestone celebrations + +### Win-Back Emails +- Expired trials +- Cancelled customers + +### Campaign Emails +- Monthly roundup / newsletter +- Seasonal promotions +- Product updates +- Industry news roundup +- Pricing updates + +**For detailed email type reference**: See [references/email-types.md](references/email-types.md) + +--- + +## Email Copy Guidelines + +### Structure +1. **Hook**: First line grabs attention +2. **Context**: Why this matters to them +3. **Value**: The useful content +4. **CTA**: What to do next +5. **Sign-off**: Human, warm close + +### Formatting +- Short paragraphs (1-3 sentences) +- White space between sections +- Bullet points for scanability +- Bold for emphasis (sparingly) +- Mobile-first (most read on phone) + +### Tone +- Conversational, not formal +- First-person (I/we) and second-person (you) +- Active voice +- Read it out loud—does it sound human? + +### Length +- 50-125 words for transactional +- 150-300 words for educational +- 300-500 words for story-driven + +### CTA Guidelines +- Buttons for primary actions +- Links for secondary actions +- One clear primary CTA per email +- Button text: Action + outcome + +**For detailed copy, personalization, and testing guidelines**: See [references/copy-guidelines.md](references/copy-guidelines.md) + +--- + +## Output Format + +### Sequence Overview +``` +Sequence Name: [Name] +Trigger: [What starts the sequence] +Goal: [Primary conversion goal] +Length: [Number of emails] +Timing: [Delay between emails] +Exit Conditions: [When they leave the sequence] +``` + +### For Each Email +``` +Email [#]: [Name/Purpose] +Send: [Timing] +Subject: [Subject line] +Preview: [Preview text] +Body: [Full copy] +CTA: [Button text] → [Link destination] +Segment/Conditions: [If applicable] +``` + +### Metrics Plan +What to measure and benchmarks + +--- + +## Task-Specific Questions + +1. What triggers entry to this sequence? +2. What's the primary goal/conversion action? +3. What do they already know about you? +4. What other emails are they receiving? +5. What's your current email performance? + +--- + +## Tool Integrations + +For implementation, see the [tools registry](../../tools/REGISTRY.md). Key email tools: + +| Tool | Best For | MCP | Guide | +|------|----------|:---:|-------| +| **Customer.io** | Behavior-based automation | - | [customer-io.md](../../tools/integrations/customer-io.md) | +| **Mailchimp** | SMB email marketing | āœ“ | [mailchimp.md](../../tools/integrations/mailchimp.md) | +| **Resend** | Developer-friendly transactional | āœ“ | [resend.md](../../tools/integrations/resend.md) | +| **SendGrid** | Transactional email at scale | - | [sendgrid.md](../../tools/integrations/sendgrid.md) | +| **Kit** | Creator/newsletter focused | - | [kit.md](../../tools/integrations/kit.md) | + +--- + +## Related Skills + +- **cold-email** — WHEN the sequence targets people who have NOT opted in (outbound prospecting). NOT for warm leads or subscribers who have expressed interest. +- **copywriting** — WHEN landing pages linked from emails need copy optimization that matches the email's message and audience. NOT for the email copy itself. +- **launch-strategy** — WHEN coordinating email sequences around a specific product launch, announcement, or release window. NOT for evergreen nurture or onboarding sequences. +- **analytics-tracking** — WHEN setting up email click tracking, UTM parameters, and attribution to connect email engagement to downstream conversions. NOT for writing or designing the sequence. +- **onboarding-cro** — WHEN email sequences are supporting a parallel in-app onboarding flow and need to be coordinated to avoid duplication. NOT as a replacement for in-app onboarding experience. + +--- + +## Communication + +Deliver email sequences as complete, ready-to-send drafts — include subject line, preview text, full body, and CTA for every email in the sequence. Always specify the trigger condition and send timing. When the sequence is long (5+ emails), lead with a sequence overview table before individual emails. Flag if any email could conflict with other sequences the audience receives. Load `marketing-context` for brand voice, ICP, and product context before writing. + +--- + +## Proactive Triggers + +- User mentions low trial-to-paid conversion → ask if there's a trial expiration email sequence before recommending in-app or pricing changes. +- User reports high open rates but low clicks → diagnose email body copy and CTA specificity before blaming subject lines. +- User wants to "do email marketing" → clarify sequence type (welcome, nurture, re-engagement, etc.) before writing anything. +- User has a product launch coming → recommend coordinating launch email sequence with in-app messaging and landing page copy for consistent messaging. +- User mentions list is going cold → suggest re-engagement sequence with progressive offers before recommending acquisition spend. + +--- + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| Sequence Architecture Doc | Trigger, goal, length, timing, exit conditions, and branching logic for the full sequence | +| Complete Email Drafts | Subject line, preview text, full body, and CTA for every email in the sequence | +| Metrics Benchmarks | Open rate, click rate, and conversion rate targets per email type and sequence goal | +| Segmentation Rules | Audience entry/exit conditions, behavioral branching, and suppression lists | +| Subject Line Variations | 3 subject line alternatives per email for A/B testing | diff --git a/marketing-skill/email-sequence/scripts/sequence_analyzer.py b/marketing-skill/email-sequence/scripts/sequence_analyzer.py new file mode 100755 index 0000000..7da6d6f --- /dev/null +++ b/marketing-skill/email-sequence/scripts/sequence_analyzer.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python3 +""" +sequence_analyzer.py — Email sequence quality analyzer +Usage: + python3 sequence_analyzer.py --file sequence.json + python3 sequence_analyzer.py --json + python3 sequence_analyzer.py # demo mode + +Input JSON format: + [ + {"subject": "...", "body": "...", "delay_days": 0}, + {"subject": "...", "body": "...", "delay_days": 2}, + ... + ] +""" + +import argparse +import json +import re +import sys + + +# --------------------------------------------------------------------------- +# Word/pattern lists +# --------------------------------------------------------------------------- + +SPAM_TRIGGER_WORDS = [ + "free", "guarantee", "guaranteed", "winner", "won", "prize", + "congratulations", "cash", "earn money", "make money", "extra income", + "100% free", "no cost", "risk free", "act now", "limited time", + "click here", "buy now", "order now", "get it now", + "as seen on", "dear friend", "you have been selected", + "this isn't spam", "not spam", "no credit card required", + "special promotion", "special offer", "amazing offer", + "!!!", "!!!", "$$$", "£££", + "increase your", "increase sales", "double your", + "lose weight", "weight loss", "diet", "viagra", "casino", +] + +CTA_PATTERNS = re.compile( + r"\b(click|tap|reply|download|sign up|register|buy|purchase|get started|" + r"learn more|read more|visit|go to|check out|schedule|book|claim|try|" + r"subscribe|join|start|access|watch|see|grab|discover)\b", + re.IGNORECASE, +) + +PERSONALIZATION_TOKENS = re.compile( + r"\{\{?\s*\w+\s*\}?\}|%\w+%|\[FIRST_NAME\]|\[NAME\]|\[COMPANY\]|\[FIRSTNAME\]", + re.IGNORECASE, +) + + +# --------------------------------------------------------------------------- +# Per-email analysis +# --------------------------------------------------------------------------- + +def analyze_email(email: dict, index: int) -> dict: + subject = email.get("subject", "") + body = email.get("body", "") + delay = email.get("delay_days", 0) + + # Subject analysis + subject_len = len(subject) + subject_word_count = len(subject.split()) + subject_ok = 30 <= subject_len <= 60 + subject_has_number = bool(re.search(r"\d", subject)) + subject_question = subject.strip().endswith("?") + subject_all_caps = subject == subject.upper() and len(subject) > 3 + + # Body analysis + body_words = re.findall(r"\b\w+\b", body) + body_word_count = len(body_words) + + # CTA detection + cta_matches = CTA_PATTERNS.findall(body) + has_cta = len(cta_matches) > 0 + + # Personalization tokens + tokens_in_subject = PERSONALIZATION_TOKENS.findall(subject) + tokens_in_body = PERSONALIZATION_TOKENS.findall(body) + total_tokens = len(tokens_in_subject) + len(tokens_in_body) + + # Spam triggers + combined = (subject + " " + body).lower() + spam_found = [w for w in SPAM_TRIGGER_WORDS if w.lower() in combined] + + # Spam score (0-100, higher = more spammy) + spam_score = min(100, len(spam_found) * 10) + + return { + "email_index": index + 1, + "delay_days": delay, + "subject": { + "text": subject, + "length": subject_len, + "word_count": subject_word_count, + "length_ok": subject_ok, + "has_number": subject_has_number, + "is_question": subject_question, + "all_caps_warning": subject_all_caps, + "personalized": len(tokens_in_subject) > 0, + }, + "body": { + "word_count": body_word_count, + "length_verdict": _body_length_verdict(body_word_count), + "has_cta": has_cta, + "cta_phrases": list(set(cta_matches))[:5], + "personalization_tokens": total_tokens, + }, + "spam": { + "trigger_words_found": spam_found[:8], + "trigger_count": len(spam_found), + "spam_risk_score": spam_score, + "risk_level": "High" if spam_score >= 40 else "Medium" if spam_score >= 20 else "Low", + }, + } + + +def _body_length_verdict(word_count: int) -> str: + if word_count < 50: + return "Too short (<50 words)" + if word_count <= 150: + return "Short/punchy — good for re-engagement" + if word_count <= 300: + return "Optimal (150-300 words)" + if word_count <= 500: + return "Long — ensure high value throughout" + return "Very long (500+ words) — consider trimming" + + +# --------------------------------------------------------------------------- +# Sequence-level analysis +# --------------------------------------------------------------------------- + +def analyze_pacing(emails: list) -> dict: + if len(emails) <= 1: + return {"note": "Single email — no pacing to analyze"} + + delays = [e.get("delay_days", 0) for e in emails] + gaps = [delays[i] - delays[i - 1] for i in range(1, len(delays))] + + issues = [] + for i, gap in enumerate(gaps): + if gap <= 0: + issues.append(f"Email {i+2}: same-day or before previous — check delay_days") + elif gap == 1: + issues.append(f"Email {i+2}: only 1-day gap — may feel aggressive") + elif gap > 14: + issues.append(f"Email {i+2}: {gap}-day gap — momentum may drop") + + # Assess overall cadence + avg_gap = sum(gaps) / len(gaps) if gaps else 0 + if avg_gap <= 2: + cadence = "Aggressive (avg <2 days)" + elif avg_gap <= 5: + cadence = "High-frequency (avg 2-5 days)" + elif avg_gap <= 10: + cadence = "Standard (avg 5-10 days)" + else: + cadence = "Low-frequency (avg 10+ days)" + + return { + "email_count": len(emails), + "total_duration_days": max(delays) - min(delays), + "avg_gap_days": round(avg_gap, 1), + "cadence_type": cadence, + "gaps": gaps, + "issues": issues, + } + + +# --------------------------------------------------------------------------- +# Scoring +# --------------------------------------------------------------------------- + +def compute_sequence_score(email_analyses: list, pacing: dict) -> dict: + if not email_analyses: + return {"overall": 0} + + # Subject score: avg subject length compliance + subject_ok_count = sum(1 for e in email_analyses if e["subject"]["length_ok"]) + subject_score = round(subject_ok_count / len(email_analyses) * 100) + + # CTA score: % of emails with CTA + cta_count = sum(1 for e in email_analyses if e["body"]["has_cta"]) + cta_score = round(cta_count / len(email_analyses) * 100) + + # Personalization score + personalized_count = sum(1 for e in email_analyses if e["body"]["personalization_tokens"] > 0) + personalization_score = round(personalized_count / len(email_analyses) * 100) + + # Spam score (inverted — low spam = high score) + avg_spam = sum(e["spam"]["spam_risk_score"] for e in email_analyses) / len(email_analyses) + spam_score = max(0, 100 - int(avg_spam)) + + # Pacing score + pacing_issues = len(pacing.get("issues", [])) + pacing_score = max(0, 100 - pacing_issues * 20) + + # Body length score + length_ok_count = sum( + 1 for e in email_analyses + if "Optimal" in e["body"]["length_verdict"] or "punchy" in e["body"]["length_verdict"] + ) + length_score = round(length_ok_count / len(email_analyses) * 100) + + weights = { + "subject_quality": 0.20, + "cta_presence": 0.20, + "spam_safety": 0.25, + "personalization": 0.15, + "pacing": 0.10, + "body_length": 0.10, + } + scores = { + "subject_quality": subject_score, + "cta_presence": cta_score, + "spam_safety": spam_score, + "personalization": personalization_score, + "pacing": pacing_score, + "body_length": length_score, + } + overall = round(sum(scores[k] * weights[k] for k in weights)) + grade = "A" if overall >= 85 else "B" if overall >= 70 else "C" if overall >= 55 else "D" if overall >= 40 else "F" + + return { + "overall": overall, + "grade": grade, + "breakdown": {k: {"score": v, "weight": f"{int(weights[k]*100)}%"} for k, v in scores.items()}, + } + + +# --------------------------------------------------------------------------- +# Demo data +# --------------------------------------------------------------------------- + +DEMO_SEQUENCE = [ + { + "subject": "{{first_name}}, your free marketing audit is ready", + "body": "Hi {{first_name}},\n\nWe analyzed 500 campaigns like yours and found three quick wins that could double your ROAS in 30 days.\n\nI've put together a custom audit for {{company}}. It's free and takes 10 minutes to review.\n\n→ Click here to see your results: [LINK]\n\nBest,\nSarah", + "delay_days": 0, + }, + { + "subject": "Did you see this, {{first_name}}?", + "body": "Quick follow-up.\n\nMost marketers we talk to are sitting on 2-3 easy optimizations that could add 20-40% more revenue from the same ad spend.\n\nHere's the #1 thing we see: landing pages that don't match the ad promise.\n\nWorth 5 minutes? → [Review your audit]\n\nSarah", + "delay_days": 3, + }, + { + "subject": "The $50,000 mistake (and how to avoid it)", + "body": "True story.\n\nOne of our clients was spending $8,500/month on Google Ads with a 1.8x ROAS. Technically above break-even, but barely.\n\nWe found that 60% of their budget was going to one keyword that had zero purchase intent.\n\nAfter fixing it: same spend, 4.2x ROAS.\n\nThat's the kind of thing our audit catches. Have you looked at yours yet?\n\n→ [Open your free audit]\n\nSarah\n\nP.S. This offer expires Friday.", + "delay_days": 5, + }, + { + "subject": "Last call — your audit expires tonight", + "body": "{{first_name}}, this is the last reminder.\n\nYour personalized audit expires at midnight tonight.\n\nIf growing your ROAS is a priority this quarter, take 10 minutes now.\n\n→ [Claim your audit before it expires]\n\nSarah", + "delay_days": 7, + }, + { + "subject": "New case study: {{company}}-style win", + "body": "Since you didn't grab the audit, I wanted to send you something valuable anyway.\n\nHere's a 3-minute case study showing how we helped a B2B SaaS company go from 1.9x to 5.4x ROAS in 45 days.\n\nNo audit required — just solid tactics you can steal.\n\n→ [Read the case study]\n\nHope it helps,\nSarah", + "delay_days": 14, + }, +] + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="Email sequence analyzer — scores sequence quality 0-100." + ) + parser.add_argument("--file", help="JSON file with email sequence array") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r", encoding="utf-8") as f: + emails = json.load(f) + else: + emails = DEMO_SEQUENCE + if not args.json: + print("No input provided — running in demo mode (5-email nurture sequence).\n") + + email_analyses = [analyze_email(e, i) for i, e in enumerate(emails)] + pacing = analyze_pacing(emails) + scoring = compute_sequence_score(email_analyses, pacing) + + if args.json: + output = { + "sequence_score": scoring, + "pacing": pacing, + "emails": email_analyses, + } + print(json.dumps(output, indent=2)) + return + + # Human-readable + overall = scoring["overall"] + grade = scoring["grade"] + + print("=" * 64) + print(f" EMAIL SEQUENCE ANALYSIS Score: {overall}/100 Grade: {grade}") + print("=" * 64) + + # Pacing summary + print(f"\n šŸ“… SEQUENCE PACING") + print(f" Emails: {pacing['email_count']}") + print(f" Duration: {pacing.get('total_duration_days', 0)} days") + print(f" Avg gap: {pacing.get('avg_gap_days', 0)} days") + print(f" Cadence: {pacing.get('cadence_type', 'N/A')}") + if pacing.get("issues"): + for issue in pacing["issues"]: + print(f" āš ļø {issue}") + + print(f"\n šŸ“§ PER-EMAIL BREAKDOWN") + print(f" {'#':<3} {'Subject':<40} {'Words':<6} {'CTA':<4} {'Tokens':<7} {'Spam'}") + print(" " + "─" * 60) + + for e in email_analyses: + subj = e["subject"]["text"][:38] + if not e["subject"]["length_ok"]: + subj += "āš ļø" + words = e["body"]["word_count"] + cta = "āœ…" if e["body"]["has_cta"] else "āŒ" + tokens = e["body"]["personalization_tokens"] + spam_lvl = e["spam"]["risk_level"] + spam_icon = "āœ…" if spam_lvl == "Low" else ("āš ļø " if spam_lvl == "Medium" else "āŒ") + spam_str = f"{spam_icon}{spam_lvl}" + print(f" {e['email_index']:<3} {subj:<40} {words:<6} {cta:<4} {tokens:<7} {spam_str}") + + if any(e["spam"]["trigger_words_found"] for e in email_analyses): + print(f"\n āš ļø SPAM TRIGGER WORDS DETECTED") + for e in email_analyses: + if e["spam"]["trigger_words_found"]: + triggers = ", ".join(e["spam"]["trigger_words_found"]) + print(f" Email {e['email_index']}: {triggers}") + + print(f"\n SCORE BREAKDOWN") + for k, v in scoring["breakdown"].items(): + label = k.replace("_", " ").title() + bar_len = round(v["score"] / 10) + bar = "ā–ˆ" * bar_len + "ā–‘" * (10 - bar_len) + print(f" {label:<22} [{bar}] {v['score']:>3}/100 (weight {v['weight']})") + + print() + print("=" * 64) + print(f" Overall: {overall}/100 Grade: {grade}") + print("=" * 64) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/form-cro/SKILL.md b/marketing-skill/form-cro/SKILL.md new file mode 100644 index 0000000..069cc08 --- /dev/null +++ b/marketing-skill/form-cro/SKILL.md @@ -0,0 +1,471 @@ +--- +name: form-cro +description: When the user wants to optimize any form that is NOT signup/registration — including lead capture forms, contact forms, demo request forms, application forms, survey forms, or checkout forms. Also use when the user mentions "form optimization," "lead form conversions," "form friction," "form fields," "form completion rate," or "contact form." For signup/registration forms, see signup-flow-cro. For popups containing forms, see popup-cro. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Form CRO + +You are an expert in form optimization. Your goal is to maximize form completion rates while capturing the data that matters. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, identify: + +1. **Form Type** + - Lead capture (gated content, newsletter) + - Contact form + - Demo/sales request + - Application form + - Survey/feedback + - Checkout form + - Quote request + +2. **Current State** + - How many fields? + - What's the current completion rate? + - Mobile vs. desktop split? + - Where do users abandon? + +3. **Business Context** + - What happens with form submissions? + - Which fields are actually used in follow-up? + - Are there compliance/legal requirements? + +--- + +## Core Principles + +### 1. Every Field Has a Cost +Each field reduces completion rate. Rule of thumb: +- 3 fields: Baseline +- 4-6 fields: 10-25% reduction +- 7+ fields: 25-50%+ reduction + +For each field, ask: +- Is this absolutely necessary before we can help them? +- Can we get this information another way? +- Can we ask this later? + +### 2. Value Must Exceed Effort +- Clear value proposition above form +- Make what they get obvious +- Reduce perceived effort (field count, labels) + +### 3. Reduce Cognitive Load +- One question per field +- Clear, conversational labels +- Logical grouping and order +- Smart defaults where possible + +--- + +## Field-by-Field Optimization + +### Email Field +- Single field, no confirmation +- Inline validation +- Typo detection (did you mean gmail.com?) +- Proper mobile keyboard + +### Name Fields +- Single "Name" vs. First/Last — test this +- Single field reduces friction +- Split needed only if personalization requires it + +### Phone Number +- Make optional if possible +- If required, explain why +- Auto-format as they type +- Country code handling + +### Company/Organization +- Auto-suggest for faster entry +- Enrichment after submission (Clearbit, etc.) +- Consider inferring from email domain + +### Job Title/Role +- Dropdown if categories matter +- Free text if wide variation +- Consider making optional + +### Message/Comments (Free Text) +- Make optional +- Reasonable character guidance +- Expand on focus + +### Dropdown Selects +- "Select one..." placeholder +- Searchable if many options +- Consider radio buttons if < 5 options +- "Other" option with text field + +### Checkboxes (Multi-select) +- Clear, parallel labels +- Reasonable number of options +- Consider "Select all that apply" instruction + +--- + +## Form Layout Optimization + +### Field Order +1. Start with easiest fields (name, email) +2. Build commitment before asking more +3. Sensitive fields last (phone, company size) +4. Logical grouping if many fields + +### Labels and Placeholders +- Labels: Always visible (not just placeholder) +- Placeholders: Examples, not labels +- Help text: Only when genuinely helpful + +**Good:** +``` +Email +[name@company.com] +``` + +**Bad:** +``` +[Enter your email address] ← Disappears on focus +``` + +### Visual Design +- Sufficient spacing between fields +- Clear visual hierarchy +- CTA button stands out +- Mobile-friendly tap targets (44px+) + +### Single Column vs. Multi-Column +- Single column: Higher completion, mobile-friendly +- Multi-column: Only for short related fields (First/Last name) +- When in doubt, single column + +--- + +## Multi-Step Forms + +### When to Use Multi-Step +- More than 5-6 fields +- Logically distinct sections +- Conditional paths based on answers +- Complex forms (applications, quotes) + +### Multi-Step Best Practices +- Progress indicator (step X of Y) +- Start with easy, end with sensitive +- One topic per step +- Allow back navigation +- Save progress (don't lose data on refresh) +- Clear indication of required vs. optional + +### Progressive Commitment Pattern +1. Low-friction start (just email) +2. More detail (name, company) +3. Qualifying questions +4. Contact preferences + +--- + +## Error Handling + +### Inline Validation +- Validate as they move to next field +- Don't validate too aggressively while typing +- Clear visual indicators (green check, red border) + +### Error Messages +- Specific to the problem +- Suggest how to fix +- Positioned near the field +- Don't clear their input + +**Good:** "Please enter a valid email address (e.g., name@company.com)" +**Bad:** "Invalid input" + +### On Submit +- Focus on first error field +- Summarize errors if multiple +- Preserve all entered data +- Don't clear form on error + +--- + +## Submit Button Optimization + +### Button Copy +Weak: "Submit" | "Send" +Strong: "[Action] + [What they get]" + +Examples: +- "Get My Free Quote" +- "Download the Guide" +- "Request Demo" +- "Send Message" +- "Start Free Trial" + +### Button Placement +- Immediately after last field +- Left-aligned with fields +- Sufficient size and contrast +- Mobile: Sticky or clearly visible + +### Post-Submit States +- Loading state (disable button, show spinner) +- Success confirmation (clear next steps) +- Error handling (clear message, focus on issue) + +--- + +## Trust and Friction Reduction + +### Near the Form +- Privacy statement: "We'll never share your info" +- Security badges if collecting sensitive data +- Testimonial or social proof +- Expected response time + +### Reducing Perceived Effort +- "Takes 30 seconds" +- Field count indicator +- Remove visual clutter +- Generous white space + +### Addressing Objections +- "No spam, unsubscribe anytime" +- "We won't share your number" +- "No credit card required" + +--- + +## Form Types: Specific Guidance + +### Lead Capture (Gated Content) +- Minimum viable fields (often just email) +- Clear value proposition for what they get +- Consider asking enrichment questions post-download +- Test email-only vs. email + name + +### Contact Form +- Essential: Email/Name + Message +- Phone optional +- Set response time expectations +- Offer alternatives (chat, phone) + +### Demo Request +- Name, Email, Company required +- Phone: Optional with "preferred contact" choice +- Use case/goal question helps personalize +- Calendar embed can increase show rate + +### Quote/Estimate Request +- Multi-step often works well +- Start with easy questions +- Technical details later +- Save progress for complex forms + +### Survey Forms +- Progress bar essential +- One question per screen for engagement +- Skip logic for relevance +- Consider incentive for completion + +--- + +## Mobile Optimization + +- Larger touch targets (44px minimum height) +- Appropriate keyboard types (email, tel, number) +- Autofill support +- Single column only +- Sticky submit button +- Minimal typing (dropdowns, buttons) + +--- + +## Measurement + +### Key Metrics +- **Form start rate**: Page views → Started form +- **Completion rate**: Started → Submitted +- **Field drop-off**: Which fields lose people +- **Error rate**: By field +- **Time to complete**: Total and by field +- **Mobile vs. desktop**: Completion by device + +### What to Track +- Form views +- First field focus +- Each field completion +- Errors by field +- Submit attempts +- Successful submissions + +--- + +## Output Format + +### Form Audit +For each issue: +- **Issue**: What's wrong +- **Impact**: Estimated effect on conversions +- **Fix**: Specific recommendation +- **Priority**: High/Medium/Low + +### Recommended Form Design +- **Required fields**: Justified list +- **Optional fields**: With rationale +- **Field order**: Recommended sequence +- **Copy**: Labels, placeholders, button +- **Error messages**: For each field +- **Layout**: Visual guidance + +### Test Hypotheses +Ideas to A/B test with expected outcomes + +--- + +## Experiment Ideas + +### Form Structure Experiments + +**Layout & Flow** +- Single-step form vs. multi-step with progress bar +- 1-column vs. 2-column field layout +- Form embedded on page vs. separate page +- Vertical vs. horizontal field alignment +- Form above fold vs. after content + +**Field Optimization** +- Reduce to minimum viable fields +- Add or remove phone number field +- Add or remove company/organization field +- Test required vs. optional field balance +- Use field enrichment to auto-fill known data +- Hide fields for returning/known visitors + +**Smart Forms** +- Add real-time validation for emails and phone numbers +- Progressive profiling (ask more over time) +- Conditional fields based on earlier answers +- Auto-suggest for company names + +--- + +### Copy & Design Experiments + +**Labels & Microcopy** +- Test field label clarity and length +- Placeholder text optimization +- Help text: show vs. hide vs. on-hover +- Error message tone (friendly vs. direct) + +**CTAs & Buttons** +- Button text variations ("Submit" vs. "Get My Quote" vs. specific action) +- Button color and size testing +- Button placement relative to fields + +**Trust Elements** +- Add privacy assurance near form +- Show trust badges next to submit +- Add testimonial near form +- Display expected response time + +--- + +### Form Type-Specific Experiments + +**Demo Request Forms** +- Test with/without phone number requirement +- Add "preferred contact method" choice +- Include "What's your biggest challenge?" question +- Test calendar embed vs. form submission + +**Lead Capture Forms** +- Email-only vs. email + name +- Test value proposition messaging above form +- Gated vs. ungated content strategies +- Post-submission enrichment questions + +**Contact Forms** +- Add department/topic routing dropdown +- Test with/without message field requirement +- Show alternative contact methods (chat, phone) +- Expected response time messaging + +--- + +### Mobile & UX Experiments + +- Larger touch targets for mobile +- Test appropriate keyboard types by field +- Sticky submit button on mobile +- Auto-focus first field on page load +- Test form container styling (card vs. minimal) + +--- + +## Task-Specific Questions + +1. What's your current form completion rate? +2. Do you have field-level analytics? +3. What happens with the data after submission? +4. Which fields are actually used in follow-up? +5. Are there compliance/legal requirements? +6. What's the mobile vs. desktop split? + +--- + +## Related Skills + +- **signup-flow-cro** — WHEN: the form being optimized is an account creation or trial registration form specifically. WHEN NOT: don't use signup-flow-cro for lead capture, contact, or demo request forms; form-cro is the right tool. +- **popup-cro** — WHEN: the form lives inside a modal, exit-intent popup, or slide-in widget rather than embedded on a page. WHEN NOT: don't use popup-cro for standalone page-embedded forms. +- **page-cro** — WHEN: the page containing the form is itself underperforming — poor value prop, weak headline, or mismatched traffic source. Fix the page context before or alongside the form. WHEN NOT: don't invoke page-cro if the form is the only conversion element on a dedicated landing page and the page itself is fine. +- **ab-test-setup** — WHEN: specific form hypotheses are ready to test (field count, button copy, multi-step vs. single-step). WHEN NOT: don't use ab-test-setup before the audit identifies the most impactful change to test. +- **analytics-tracking** — WHEN: field-level drop-off data doesn't exist yet and the team needs to instrument form analytics before any optimization can happen. WHEN NOT: skip if analytics are already in place. +- **marketing-context** — WHEN: check `.claude/product-marketing-context.md` for ICP and qualification criteria, which directly informs which fields are truly necessary. WHEN NOT: skip if user has explicitly listed the fields and their business rationale. + +--- + +## Communication + +All form CRO output follows this quality standard: +- Every field recommendation is justified — never just "remove fields" without explaining which and why +- Audit output uses the **Issue / Impact / Fix / Priority** structure consistently +- Multi-step vs. single-step recommendation always includes the qualifying criteria for the choice +- Mobile optimization is addressed separately from desktop — never conflate the two +- Submit button copy alternatives are always provided (minimum 3 options with reasoning) +- Error message rewrites are included when error handling is flagged as an issue + +--- + +## Proactive Triggers + +Automatically surface form-cro when: + +1. **"Our lead form isn't converting"** — Any complaint about form completion rates immediately triggers the field audit and core principles review. +2. **Demo request or contact page being built** — When frontend-design or copywriting skills are active and a form is part of the page, proactively offer form-cro review. +3. **"We're getting leads but bad quality"** — Poor lead quality often signals wrong fields or missing qualification questions; proactively recommend field audit. +4. **Mobile conversion gap detected** — If page-cro or analytics review shows a desktop vs. mobile completion gap on a form, surface form-cro mobile optimization checklist. +5. **Long form identified** — When user describes or shares a form with 7+ fields, immediately flag the field-cost framework and multi-step recommendation. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Form Audit | Issue/Impact/Fix/Priority table | Per-field and per-pattern analysis with actionable fixes | +| Recommended Field Set | Justified list | Required vs. optional fields with rationale for each | +| Field Order & Layout Spec | Annotated outline | Recommended sequence, grouping, column layout, and mobile considerations | +| Submit Button Copy Options | 3-option table | Action-oriented button copy variants with reasoning | +| A/B Test Hypotheses | Table | Hypothesis Ɨ variant Ɨ success metric Ɨ priority for top 3-5 test ideas | diff --git a/marketing-skill/form-cro/scripts/form_field_analyzer.py b/marketing-skill/form-cro/scripts/form_field_analyzer.py new file mode 100644 index 0000000..4ff1496 --- /dev/null +++ b/marketing-skill/form-cro/scripts/form_field_analyzer.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 +""" +Form Field Analyzer for CRO + +Analyzes HTML forms for conversion optimization opportunities. +Checks field count, types, labels, friction signals, and mobile readiness. + +Usage: + python3 form_field_analyzer.py # Demo mode + python3 form_field_analyzer.py form.html # Analyze HTML file + python3 form_field_analyzer.py form.html --json # JSON output +""" + +import json +import sys +import os +import re +from html.parser import HTMLParser + + +class FormAnalyzer(HTMLParser): + def __init__(self): + super().__init__() + self.forms = [] + self.current_form = None + self.in_label = False + self.current_label = "" + self.in_button = False + self.current_button = "" + + def handle_starttag(self, tag, attrs): + attrs_dict = dict(attrs) + + if tag == "form": + self.current_form = { + "action": attrs_dict.get("action", ""), + "method": attrs_dict.get("method", "GET").upper(), + "fields": [], + "buttons": [], + "has_autocomplete": "autocomplete" in attrs_dict + } + + elif tag == "input" and self.current_form is not None: + input_type = attrs_dict.get("type", "text").lower() + if input_type not in ("hidden", "submit"): + self.current_form["fields"].append({ + "type": input_type, + "name": attrs_dict.get("name", ""), + "placeholder": attrs_dict.get("placeholder", ""), + "required": "required" in attrs_dict, + "autocomplete": attrs_dict.get("autocomplete", ""), + "has_label": False + }) + elif input_type == "submit": + self.current_form["buttons"].append(attrs_dict.get("value", "Submit")) + + elif tag == "textarea" and self.current_form is not None: + self.current_form["fields"].append({ + "type": "textarea", + "name": attrs_dict.get("name", ""), + "placeholder": attrs_dict.get("placeholder", ""), + "required": "required" in attrs_dict, + "autocomplete": "", + "has_label": False + }) + + elif tag == "select" and self.current_form is not None: + self.current_form["fields"].append({ + "type": "select", + "name": attrs_dict.get("name", ""), + "placeholder": "", + "required": "required" in attrs_dict, + "autocomplete": "", + "has_label": False + }) + + elif tag == "label": + self.in_label = True + self.current_label = "" + for_attr = attrs_dict.get("for", "") + if for_attr and self.current_form: + for field in self.current_form["fields"]: + if field["name"] == for_attr: + field["has_label"] = True + + elif tag == "button": + self.in_button = True + self.current_button = "" + + def handle_data(self, data): + if self.in_label: + self.current_label += data.strip() + if self.in_button: + self.current_button += data.strip() + + def handle_endtag(self, tag): + if tag == "form" and self.current_form: + self.forms.append(self.current_form) + self.current_form = None + elif tag == "label": + self.in_label = False + elif tag == "button": + self.in_button = False + if self.current_button and self.current_form: + self.current_form["buttons"].append(self.current_button) + + +def analyze_form(form): + """Analyze a single form for CRO issues.""" + fields = form["fields"] + issues = [] + warnings = [] + positives = [] + + field_count = len(fields) + + # Field count analysis + if field_count > 7: + issues.append(f"Too many fields ({field_count}). Each field above 3 reduces conversion by ~5-10%. Consider progressive disclosure.") + elif field_count > 4: + warnings.append(f"{field_count} fields — acceptable but test reducing to 3-4 core fields.") + elif field_count <= 3: + positives.append(f"Low friction — only {field_count} fields.") + + # Phone number field + phone_fields = [f for f in fields if "phone" in f["name"].lower() or f["type"] == "tel"] + if phone_fields: + required_phones = [f for f in phone_fields if f["required"]] + if required_phones: + issues.append("Phone number is REQUIRED — this is the #1 form abandonment trigger. Make optional or remove.") + else: + warnings.append("Phone field present (optional) — still causes friction. Consider removing unless sales-critical.") + + # Labels + unlabeled = [f for f in fields if not f["has_label"] and not f["placeholder"]] + if unlabeled: + issues.append(f"{len(unlabeled)} fields have no label AND no placeholder. Users won't know what to enter.") + + placeholder_only = [f for f in fields if not f["has_label"] and f["placeholder"]] + if placeholder_only: + warnings.append(f"{len(placeholder_only)} fields use placeholder-only labels. Placeholders disappear on focus — use visible labels.") + + # Button text + weak_ctas = ["submit", "send", "go", "ok"] + for btn in form["buttons"]: + if btn.lower() in weak_ctas: + warnings.append(f'CTA button says "{btn}" — use action-specific text like "Get My Free Report" or "Start Free Trial".') + + if not form["buttons"]: + issues.append("No submit button found. Form may be broken or use JavaScript submission only.") + + # Autocomplete + fields_with_autocomplete = [f for f in fields if f["autocomplete"]] + if not fields_with_autocomplete and field_count > 0: + warnings.append("No autocomplete attributes. Adding autocomplete reduces mobile friction significantly.") + + # Required fields + required_count = sum(1 for f in fields if f["required"]) + if required_count == field_count and field_count > 2: + warnings.append("ALL fields are required. Consider making some optional to reduce perceived commitment.") + + # Score + score = 100 + score -= len(issues) * 15 + score -= len(warnings) * 5 + score += len(positives) * 5 + score = max(0, min(100, score)) + + return { + "field_count": field_count, + "required_count": required_count, + "has_phone": len(phone_fields) > 0, + "cta_text": form["buttons"], + "issues": issues, + "warnings": warnings, + "positives": positives, + "score": score, + "fields": [{"name": f["name"], "type": f["type"], "required": f["required"]} for f in fields] + } + + +def format_report(analyses): + """Format human-readable report.""" + lines = [] + lines.append("") + lines.append("=" * 60) + lines.append(" FORM CRO — FIELD ANALYSIS REPORT") + lines.append("=" * 60) + + for i, analysis in enumerate(analyses): + lines.append("") + lines.append(f" FORM {i + 1}") + lines.append(f" Fields: {analysis['field_count']} | Required: {analysis['required_count']} | CTA: {', '.join(analysis['cta_text']) or 'none'}") + lines.append("") + + score = analysis["score"] + bar = "ā–ˆ" * (score // 5) + "ā–‘" * (20 - score // 5) + lines.append(f" FORM SCORE: {score}/100") + lines.append(f" [{bar}]") + lines.append("") + + lines.append(" Fields:") + for f in analysis["fields"]: + req = " *" if f["required"] else "" + lines.append(f" [{f['type']}] {f['name']}{req}") + lines.append("") + + if analysis["positives"]: + lines.append(" 🟢 STRENGTHS:") + for p in analysis["positives"]: + lines.append(f" āœ“ {p}") + lines.append("") + + if analysis["issues"]: + lines.append(" šŸ”“ ISSUES:") + for issue in analysis["issues"]: + lines.append(f" • {issue}") + lines.append("") + + if analysis["warnings"]: + lines.append(" 🟔 WARNINGS:") + for warn in analysis["warnings"]: + lines.append(f" • {warn}") + lines.append("") + + return "\n".join(lines) + + +SAMPLE_HTML = """ +
+ + + + + + + + + + + + + + + + + + + + + + +
+""" + + +def main(): + use_json = "--json" in sys.argv + args = [a for a in sys.argv[1:] if a != "--json"] + + if args and os.path.isfile(args[0]): + with open(args[0]) as f: + html = f.read() + else: + if not args: + print("[Demo mode — analyzing sample lead capture form]") + html = SAMPLE_HTML + + parser = FormAnalyzer() + parser.feed(html) + + if not parser.forms: + print("No
elements found in the HTML.") + sys.exit(1) + + analyses = [analyze_form(form) for form in parser.forms] + + if use_json: + print(json.dumps(analyses, indent=2)) + else: + print(format_report(analyses)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/free-tool-strategy/SKILL.md b/marketing-skill/free-tool-strategy/SKILL.md new file mode 100644 index 0000000..0348cd9 --- /dev/null +++ b/marketing-skill/free-tool-strategy/SKILL.md @@ -0,0 +1,272 @@ +--- +name: free-tool-strategy +description: "When the user wants to build a free tool for marketing — lead generation, SEO value, or brand awareness. Use when they mention 'engineering as marketing,' 'free tool,' 'calculator,' 'generator,' 'checker,' 'grader,' 'marketing tool,' 'lead gen tool,' 'build something for traffic,' 'interactive tool,' or 'free resource.' Covers idea evaluation, tool design, and launch strategy. For pure SEO content strategy (no tool), use seo-audit or content-strategy instead." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Free Tool Strategy + +You are a growth engineer who has built and launched free tools that generated hundreds of thousands of visitors, thousands of leads, and hundreds of backlinks without a single paid ad. You know which ideas have legs and which waste engineering time. Your goal is to help decide what to build, how to design it for maximum value and lead capture, and how to launch it so people actually find it. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered. + +Gather this context (ask if not provided): + +### 1. Product & Audience +- What's your core product and who buys it? +- What problem does your ideal customer have that a free tool could solve adjacently? +- What does your audience search for that isn't your product? + +### 2. Resources +- How much engineering time can you dedicate? (Hours, days, weeks) +- Do you have design resources, or is this no-code/template? +- Who maintains the tool after launch? + +### 3. Goals +- Primary goal: SEO traffic, lead generation, backlinks, or brand awareness? +- What does a "win" look like? (X leads/month, Y backlinks, Z organic visitors) + +--- + +## How This Skill Works + +### Mode 1: Evaluate Tool Ideas +You have one or more ideas and you're not sure which to build — or whether to build any of them. + +**Workflow:** +1. Score each idea against the 6-factor evaluation framework +2. Identify the highest-potential idea based on your specific goals and resources +3. Validate with keyword data before committing engineering time + +### Mode 2: Design the Tool +You've decided what to build. Now design it to maximize value, lead capture, and shareability. + +**Workflow:** +1. Define the core value exchange (what the user inputs → what they get back) +2. Design the UX for minimum friction +3. Plan lead capture: where, what to ask, progressive profiling +4. Design shareable output (results page, generated report, embeddable badge) +5. Plan the SEO landing page structure + +### Mode 3: Launch and Measure +You've built it. Now distribute it and track whether it's working. + +**Workflow:** +1. Pre-launch: SEO landing page, schema markup, submit to directories +2. Launch channels: Product Hunt, Hacker News, industry newsletters, social +3. Outreach: who links to similar tools? → build a link acquisition list +4. Measurement: set up tracking for usage, leads, organic traffic, backlinks +5. Iterate: usage data tells you what to improve + +--- + +## Tool Types and When to Use Each + +| Tool Type | What It Does | Build Complexity | Best For | +|-----------|-------------|-----------------|---------| +| **Calculator** | Takes inputs, outputs a number or range | Low–Medium | LTV, ROI, pricing, salary, savings | +| **Generator** | Creates text, ideas, or structured content | Low (template) – High (AI) | Headlines, bios, copy, names, reports | +| **Checker** | Analyzes a URL, text, or file and scores/audits it | Medium–High | SEO audit, readability, compliance, spelling | +| **Grader** | Scores something against a rubric | Medium | Website grade, email grade, sales page score | +| **Converter** | Transforms input from one format to another | Low–Medium | Units, formats, currencies, time zones | +| **Template** | Pre-built fillable documents | Very Low | Contracts, briefs, decks, roadmaps | +| **Interactive Visualization** | Shows data or concepts visually | High | Market maps, comparison charts, trend data | + +See [references/tool-types-guide.md](references/tool-types-guide.md) for detailed examples, build guides, and complexity breakdowns per type. + +--- + +## The 6-Factor Evaluation Framework + +Score each idea 1–5 on each factor. Highest total = build first. + +| Factor | What to Check | 1 (weak) | 5 (strong) | +|--------|--------------|----------|-----------| +| **Search Volume** | Monthly searches for "free [tool]" | <100/mo | >5k/mo | +| **Competition** | Quality of existing free tools | Excellent tools exist | No good free alternatives | +| **Build Effort** | Engineering time required | Months | Days | +| **Lead Capture Potential** | Can you naturally gate or capture email? | Forced gate, kills UX | Natural fit (results emailed, report downloaded) | +| **SEO Value** | Can you build topical authority + backlinks? | Thin, one-page utility | Deep use case, link magnet | +| **Viral Potential** | Will users share results or embed the tool? | Nobody shares | Results are shareable by design | + +**Scoring guide:** +- 25–30: Build it, now +- 18–24: Strong candidate, validate keyword volume first +- 12–17: Maybe, if resources are low or it fits a strategic gap +- <12: Pass, or rethink the concept + +--- + +## Design Principles + +### Value Before Gate +Give the core value first. Gate the upgrade — the deeper report, the saved results, the email delivery. If the tool is only valuable after they give you their email, you've designed a lead form, not a tool. + +**Good:** Show the score immediately → offer to email the full report +**Bad:** "Enter your email to see your results" + +### Minimal Friction +- Max 3 inputs to get initial results +- No account required for the core value +- Progressive disclosure: simple first, detailed on request +- Mobile-optimized — 50%+ of tool traffic is mobile + +### Shareable Results +Design results so users want to share them: +- Unique results URL that others can visit +- "Tweet your score" / "Copy your results" buttons +- Embed code for badges or widgets +- Downloadable report (PDF or CSV) +- Social-ready image generation (score card, certificate) + +### Mobile-First +- Inputs work on touch screens +- Results render cleanly on mobile +- Share buttons trigger native share sheet +- No hover-dependent UI + +--- + +## Lead Capture — When, What, How + +### When to Gate + +**Gate with email when:** +- Results are complex enough to warrant a "report" framing +- Tool produces ongoing value (track over time, re-run monthly) +- Results are personalized and users would naturally want to save them + +**Don't gate when:** +- Core result is a single number or short answer +- Competition offers the same thing without a gate +- Your primary goal is SEO/backlinks (gates hurt time-on-page and links) + +### What to Ask + +Ask the minimum. Every field drops completion by ~10%. + +**First gate:** Email only +**Second gate (on re-use or report download):** Name + Company size + Role + +### Progressive Profiling +Don't ask everything at once. Build the profile over multiple sessions: +- Session 1: Email to save results +- Session 2: Role, use case (asked contextually, not in a form) +- Session 3: Company, team size (if they request team features) + +--- + +## SEO Strategy for Free Tools + +### Landing Page Structure + +``` +H1: [Free Tool Name] — [What It Does] [one phrase] +Subhead: [Who it's for] + [what problem it solves] +[The Tool — above the fold] +H2: How [Tool Name] works +H2: Why [audience] use [tool name] +H2: [Related Question 1] +H2: [Related Question 2] +H2: Frequently Asked Questions +``` + +Target keyword in: H1, URL slug, meta title, first 100 words, at least 2 subheadings. + +### Schema Markup +Add `SoftwareApplication` schema to tell Google what the page is: +```json +{ + "@type": "SoftwareApplication", + "name": "Tool Name", + "applicationCategory": "BusinessApplication", + "offers": {"@type": "Offer", "price": "0"}, + "description": "..." +} +``` + +### Link Magnet Potential +Tools attract links from: +- Resource pages ("best free tools for X") +- Blog posts ("the tools I use for X") +- Subreddits, Slack communities, Facebook groups +- Weekly newsletters in your niche + +Plan your outreach list before launch. Who writes about tools in your category? Find their existing "best tools" posts and reach out post-launch. + +--- + +## Measurement + +Track these from day one: + +| Metric | What It Tells You | Tool | +|--------|------------------|------| +| Tool usage (sessions, completions) | Is anyone using it? | GA4 / Plausible | +| Lead conversion rate | Is it generating leads? | CRM + GA4 events | +| Organic traffic | Is it ranking? | Google Search Console | +| Referring domains | Is it earning links? | Ahrefs / Google GSC | +| Email to paid conversion | Is it generating pipeline? | CRM attribution | +| Bounce rate / time on page | Is the tool actually used? | GA4 | + +**Targets at 90 days post-launch:** +- Organic traffic: 500+ sessions/month +- Lead conversion: 5–15% of completions +- Referring domains: 10+ organic backlinks + +Run `scripts/tool_roi_estimator.py` to model break-even timeline based on your traffic and conversion assumptions. + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Tool requires account before use** → Flag and redesign the gate. This kills SEO, kills virality, and tells users you're harvesting data, not providing value. +- **No shareable output** → If results exist only in the session and can't be shared or saved, you've built half a tool. Flag the missed virality opportunity. +- **No keyword validation** → If the tool concept hasn't been validated against search volume before build, flag — 3 hours of research beats 3 weeks of building a tool nobody searches for. +- **Competitors with the same free tool** → If an existing tool is well-established and free, the bar is "10x better or don't build it." Flag the competitive risk. +- **Single input → single output** → Ultra-simple tools lose SEO value quickly and attract no links. Flag if the tool needs more depth to be link-worthy. +- **No maintenance plan** → Free tools die when the API they call changes or the logic gets stale. Flag the need for a maintenance owner before launch. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Evaluate my tool ideas" | Scored comparison matrix (6 factors Ɨ ideas), ranked recommendation with rationale | +| "Design this tool" | UX spec: inputs, outputs, lead capture flow, share mechanics, landing page outline | +| "Write the landing page" | Full landing page copy: H1, subhead, how it works section, FAQ, meta title + description | +| "Plan the launch" | Pre-launch checklist, launch channel list with specific actions, outreach target list | +| "Set up measurement" | GA4 event tracking plan, GSC setup checklist, KPI targets at 30/60/90 days | +| "Is this tool worth building?" | ROI model (using tool_roi_estimator.py): break-even month, required traffic, lead value threshold | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — recommendation before reasoning +- **Numbers-grounded** — traffic targets, conversion rates, ROI projections tied to your inputs +- **Confidence tagging** — 🟢 validated / 🟔 estimated / šŸ”“ assumed +- **Build decisions are binary** — "build it" or "don't build it" with a clear reason, not "it depends" + +--- + +## Related Skills + +- **seo-audit**: Use for auditing existing pages and keyword strategy. NOT for building new tool-based content assets. +- **content-strategy**: Use for planning the overall content program (blogs, guides, whitepapers). NOT for tool-specific lead generation. +- **copywriting**: Use when writing the marketing copy for the tool landing page. NOT for the tool UX design or lead capture strategy. +- **launch-strategy**: Use when planning the full product or feature launch. NOT for tool-specific distribution (use free-tool-strategy for that). +- **analytics-tracking**: Use when implementing the measurement stack for the tool. NOT for deciding what to measure (use free-tool-strategy for that). +- **form-cro**: Use when optimizing the lead capture form in the tool. NOT for the tool design or launch strategy. diff --git a/marketing-skill/free-tool-strategy/references/launch-playbook.md b/marketing-skill/free-tool-strategy/references/launch-playbook.md new file mode 100644 index 0000000..ab093ca --- /dev/null +++ b/marketing-skill/free-tool-strategy/references/launch-playbook.md @@ -0,0 +1,182 @@ +# Launch Playbook — How to Launch a Free Tool for Maximum Impact + +A free tool with no distribution is just code sitting on a server. This playbook gives you the launch sequence that turns a new tool into traffic, leads, and backlinks. + +--- + +## The Launch Mindset + +Most companies "launch" by posting it on LinkedIn and waiting. That gets you 200 visits from your existing followers and then nothing. + +A real launch is a 4-week sustained distribution campaign. You're not announcing — you're seeding. Every channel you touch plants a seed that compounds over months (especially for SEO). + +--- + +## Pre-Launch Checklist (1–2 Weeks Before) + +### SEO Foundations +- [ ] Target keyword researched and confirmed (search volume + low-medium competition) +- [ ] URL slug locked: `/tools/[keyword-rich-name]` +- [ ] Meta title written: "[Free Tool Name] — [What It Does] | [Brand]" +- [ ] Meta description written: 155 chars, includes target keyword, tells user what they get +- [ ] H1 matches search intent, not just brand name +- [ ] `SoftwareApplication` schema markup added (see SKILL.md) +- [ ] Internal links from related content pointing to the tool page +- [ ] Tool page links to 2-3 related resources on your site + +### Tool Quality Gate +- [ ] Core value delivered in ≤3 user inputs +- [ ] Results render on mobile +- [ ] Results are shareable (unique URL, copy button, or social share) +- [ ] Lead capture is in place (but gated after value, not before) +- [ ] Email delivery working if you're sending results via email +- [ ] Error handling — what happens with bad inputs? +- [ ] Load time <3 seconds (tools with slow loads have brutal bounce rates) + +### Analytics Setup +- [ ] GA4 (or Plausible) tracking installed +- [ ] Key events tracked: tool_started, tool_completed, lead_captured, result_shared +- [ ] Google Search Console verified +- [ ] Heatmap tool installed (Hotjar or Microsoft Clarity) to watch real usage + +### Outreach List Ready +- [ ] List of 20-50 sites that link to similar free tools (from Ahrefs / Google "site:domain resources") +- [ ] List of newsletters in your category that feature tools +- [ ] List of subreddits and communities where your audience hangs out +- [ ] Influencers or thought leaders who regularly share tools in your space + +--- + +## Launch Week — The Sequence + +### Day 1: SEO and Directories +- Submit tool to Google Search Console (Request Indexing) +- Submit to Bing Webmaster Tools +- Submit to relevant online directories (AlternativeTo, Product Hunt upcoming, SaaSHub, Capterra if applicable) +- Post in your company's blog (a 600-900 word post explaining the tool, linking to it) + +### Day 2: Product Hunt +- Submit to Product Hunt at midnight PST (Thursday or Tuesday for best timing) +- Have your team and early fans upvote in the first 2 hours +- Respond to every comment personally — PH algorithm rewards engagement +- Ask your top customers to upvote (personalized message, not mass email) +- Product Hunt tip: the thumbnail image and tagline matter more than the description + +### Day 3: Community Seeding (No Pitch) +- Post in relevant subreddits — share as a resource, not a promotion + - Frame: "I built this free [tool type] for [audience] because I couldn't find one — feedback welcome" + - No "check out our new tool" — that's spam and gets removed +- Share in Slack communities in your industry +- Share in relevant Facebook groups +- LinkedIn post — personal post from founder, not company page (personal posts get 10Ɨ the reach) + +### Day 4: Email to Your List +- Dedicated email to your subscriber list introducing the tool +- Subject line: "Free [Tool Name] — [benefit in 5 words]" +- Keep it short: what it is, why you built it, one sentence result, link +- Ask them to share with one person who'd benefit + +### Day 5: Hacker News +- Post to HN with a "Show HN:" prefix: `Show HN: [Tool Name] — [what it does in one line]` +- HN community responds well to honest builder posts with a unique angle +- Must be technically interesting or niche — generic marketing tools don't land +- Be available to answer technical questions in the thread all day + +### Day 6-7: Social Amplification +- Twitter/X thread: "I built a free [tool] for [audience]. Here's how it works:" → walkthrough with screenshots +- Short-form video (LinkedIn/TikTok): screen recording of yourself using the tool +- Reach out to 5 people who you know will love it — personal message, not mass email + +--- + +## Post-Launch: Weeks 2-4 + +### Backlink Outreach +This is where the long-term SEO value comes from. + +**Identify targets:** +1. Search Google: `"best free tools for [your category]"` — email everyone on that list +2. Use Ahrefs: find pages linking to similar tools → those same pages may link to yours +3. Search: `"[competitor tool name]" site:[niche blog]` — those bloggers are interested in tools like yours + +**Outreach template:** +``` +Subject: Free [Tool Name] that might fit your "[Resource List Title]" post + +Hi [Name], + +I noticed your post on the best free tools for [category]. I recently built [Tool Name] +— it helps [audience] [specific outcome] without [common pain point]. + +[Direct link to tool] + +Would it fit your list? Happy to give you early access or a custom embed if that's useful. + +[Your name] +``` + +**Volume:** 50-100 personalized outreach emails in the first 30 days. Expect 5-15% positive response. One good resource page link is worth 50 generic directory submissions. + +### Content That Multiplies +- Write a guide that uses the tool as a central reference: "How to [goal] — with a free calculator to check your numbers" +- Create a results-based case study: "We analyzed 500 [things] with our [tool] — here's what we found" +- Partner with a newsletter: offer to write a guest post that features the tool as the main resource + +--- + +## Measurement — First 90 Days + +### Weekly Check-ins (GA4 + GSC) + +| Week | What to Look For | +|------|----------------| +| 1 | Direct traffic from launch channels. Tool completion rate (anything under 40% means fix UX) | +| 2-4 | Product Hunt/HN traffic tailing off. Backlinks starting to trickle in. | +| 5-8 | First organic impressions in GSC. Check what queries are sending traffic. | +| 9-12 | Organic traffic should be visible. Lead capture rate should be stable. | + +### The "Is It Working?" Test at 90 Days + +| Metric | Needs Work | Good | Great | +|--------|-----------|------|-------| +| Organic sessions/month | <200 | 500–2,000 | >5,000 | +| Tool completion rate | <30% | 40–60% | >70% | +| Lead conversion rate (completions → email) | <3% | 5–15% | >20% | +| Referring domains (backlinks) | <5 | 10–30 | >50 | + +--- + +## When a Launch Flops + +A tool can fail to gain traction for 4 reasons: + +1. **Wrong keyword** — nobody searches for this. Check GSC; if you have zero impressions after 60 days, the keyword target is wrong. Pivot the page copy to a related term with volume. + +2. **Wrong problem** — the tool exists, but it's not solving an acute enough problem. Talk to 5 people who used it and didn't return. What were they hoping for? + +3. **Gated too early** — traffic is high but completion is low. You're asking for email before delivering value. Remove or move the gate. + +4. **Distribution failure** — the tool is fine, but you only posted it once. Run the backlink outreach again with a fresh list. Submit to 10 new directories. Write the guide post. + +Most "failed" tools aren't actually failures — they just didn't get the 90-day distribution campaign they needed. + +--- + +## Tools That Keep Working (Maintenance) + +A free tool is a 3-year investment, not a 3-week campaign. + +**Monthly:** +- Check tool is still functioning (APIs, URLs, formulas) +- Review top search queries in GSC → update H2s and content to match +- Add one new feature based on user requests (check support inbox) + +**Quarterly:** +- Update any data the tool uses (benchmarks, averages, rates) +- Refresh the landing page copy — Google rewards freshness +- Identify 20 new backlink targets and run outreach + +**Annually:** +- Full UX review — does it still work on the latest mobile browsers? +- Competitive audit — are better free alternatives emerging? +- Decide: invest more, maintain as-is, or retire and redirect diff --git a/marketing-skill/free-tool-strategy/references/tool-types-guide.md b/marketing-skill/free-tool-strategy/references/tool-types-guide.md new file mode 100644 index 0000000..c196db5 --- /dev/null +++ b/marketing-skill/free-tool-strategy/references/tool-types-guide.md @@ -0,0 +1,253 @@ +# Tool Types Guide — Comprehensive Reference for Free Marketing Tools + +Each tool type explained with examples, build complexity, typical outcomes, and design guidance. + +--- + +## The 7 Tool Types + +### 1. Calculators + +**What they do:** Take numerical or categorical inputs → output a calculated result (a number, range, or score). + +**Examples:** +- SaaS Pricing Calculator ("What should you charge?") +- ROI Calculator ("How much would you save?") +- LTV Calculator ("What's your customer worth?") +- Churn Impact Calculator ("What does 1% more churn cost you?") +- Salary Calculator by role/location/experience + +**Build complexity:** Low–Medium +- Simple formula: 1-2 days of dev +- Multi-variable model: 1-2 weeks + +**Lead potential:** High — people want to save or email complex results. + +**SEO value:** Medium-High — calculators earn links from resource pages and ranking for "[topic] calculator" queries. + +**Viral potential:** Medium — people share results when they're surprising or validating. + +**Design tips:** +- Sliders are more satisfying than input fields for numerical ranges +- Show results dynamically (real-time as they adjust inputs) +- Include a "how this was calculated" section for credibility +- Email results: "Send this to myself" captures the lead naturally + +**What makes a calculator link-worthy:** +The underlying model must be credible. If you're calculating LTV, show your formula and cite your assumptions. A calculator with methodology is shareable content, not just a widget. + +--- + +### 2. Generators + +**What they do:** Take inputs (topic, style, parameters) → output structured text or content. + +**Examples:** +- Headline Generator (input: product + audience → 10 headline options) +- LinkedIn Bio Generator +- Job Description Generator +- Email Subject Line Generator +- Product Description Generator +- Business Name Generator + +**Build complexity:** Low (template-based) to High (LLM-powered) + +**Template-based (madlibs):** +- 1-3 days +- Take inputs, fill template slots, combine with variations +- Deterministic output + +**LLM-powered:** +- 1-2 weeks (API integration + prompt engineering) +- Generative output +- Requires API key costs to be modeled into business case + +**Lead potential:** Medium — output varies, so gating with email is natural if you offer "save and regenerate." + +**SEO value:** High for "[topic] generator free" — some of the highest-traffic tools are generators. + +**Viral potential:** High — people share clever or surprisingly good generated outputs. + +**Design tips:** +- Show an example output before the user enters anything (reduces bounce) +- Generate 3-5 variations, not just 1 +- "Copy to clipboard" button is a must +- "Generate again" encourages engagement (more pageviews, better SEO signal) + +--- + +### 3. Checkers + +**What they do:** Analyze a URL, email, text, file, or domain → return an audit or pass/fail assessment. + +**Examples:** +- SEO Checker ("Analyze your page's SEO") +- Email Spam Checker ("Will your email hit spam?") +- Website Speed Checker +- LinkedIn Profile Checker +- Ad Copy Compliance Checker +- Password Strength Checker +- Domain Authority Checker + +**Build complexity:** Medium–High +- Text analysis (readability, keyword density): 2-5 days +- URL crawling (page analysis): 1-2 weeks +- Email delivery testing: 1-2 weeks + email infrastructure + +**Lead potential:** High — checker results are specific to the user; saves/exports feel natural. + +**SEO value:** Very High — "[type] checker" or "check my [thing]" queries are often high-volume. + +**Viral potential:** High — "Your page scored 47/100 — here's what's broken" drives sharing. + +**Design tips:** +- Score the output (0-100) — people anchor on scores and compare +- Categorize results: Critical / Warnings / Passed +- Prioritize issues — don't just list everything, rank by impact +- Loading state matters — show progress (feels like analysis is happening) + +--- + +### 4. Graders + +**What they do:** Score something holistically against a rubric. More opinionated than a checker — you're grading against a defined standard. + +**Examples:** +- Website Grader (HubSpot's classic) +- Sales Page Grader +- Email Newsletter Grader +- LinkedIn Company Page Grader +- Onboarding Flow Grader +- Pricing Page Grader + +**Build complexity:** Medium +- Define the rubric first (the criteria matter more than the tech) +- Usually 1-2 weeks + +**Lead potential:** Very High — graders feel like getting a report card; people want the full results. + +**SEO value:** High for niche graders ("sales page grader" etc.). + +**Viral potential:** Medium-High — share your score as social proof or to invite critique. + +**Design tips:** +- The grade (A-F or 0-100) is the hook — show it prominently +- Break down the grade into components (e.g., "Design: A, Copy: C, CTA: D") +- Each component should explain why and how to improve it +- The improvement advice is where the lead capture is earned + +--- + +### 5. Converters + +**What they do:** Transform input from one format to another. Pure utility. + +**Examples:** +- Markdown to HTML Converter +- Timestamp Converter +- CSV to JSON Converter +- Video Frame Rate Converter +- UTC to Local Time Converter +- File Format Converter +- Currency Converter + +**Build complexity:** Very Low – Low +- Most conversions are 1-2 days +- Pure client-side (no server needed) + +**Lead potential:** Low — pure utility, low friction reason to capture email. + +**SEO value:** Medium — "convert X to Y" queries exist but are dominated by large tool sites. + +**Viral potential:** Low — people bookmark and return, don't share. + +**When to build:** Only if the conversion is specific to your audience (e.g., a SaaS for designers building a "Figma token to CSS converter"). Generic converters are dominated by free sites with years of SEO authority. + +--- + +### 6. Templates + +**What they do:** Pre-built, fillable documents that users download, copy, or use. + +**Examples:** +- Job Description Templates +- Product Roadmap Template +- SaaS Metrics Dashboard Template (Google Sheets) +- Email Sequence Template +- SEO Content Brief Template +- Brand Voice Guide Template +- Engineering RFP Template + +**Build complexity:** Very Low +- Template creation: hours to 1 day +- Hosting: Google Docs/Sheets share, Notion public page, or downloadable PDF + +**Lead potential:** Very High — download = natural lead capture (email to send the file). + +**SEO value:** High — "[role] template" queries are competitive but high-intent. + +**Viral potential:** Medium — people share templates that save them real time. + +**Design tips:** +- The template itself is the product — make it excellent +- Include instructions inside the template +- Offer a "filled example" so users understand what it should look like +- Update templates seasonally to keep them ranking + +--- + +### 7. Interactive Visualizations + +**What they do:** Show data, concepts, or comparisons in a visual, explorable way. + +**Examples:** +- SaaS Market Map (interactive, filterable) +- Marketing Funnel Visualizer +- Company Comparison Tool (filter by size, location, tech stack) +- Real-Time Industry Benchmark Dashboard +- Interactive Pricing Comparison + +**Build complexity:** High +- 2-6 weeks typically +- Requires data (your own research, public datasets, or API) +- May require ongoing data maintenance + +**Lead potential:** Medium — users engage deeply but email capture isn't always natural. + +**SEO value:** Very High if data-driven — journalists and bloggers link to unique datasets. + +**Viral potential:** Very High if the data is surprising or highly visual — these are your link magnets. + +**Design tips:** +- The data is the moat — if you have unique data, this is the highest-leverage tool type +- Interactive beats static for time-on-page +- Make it embeddable (embed code button) for backlink acquisition +- Update the data regularly — stale data kills backlinks when someone discovers it + +--- + +## Build vs. No-Code Decision Guide + +| Tool Type | No-Code Options | When to Go Custom Dev | +|-----------|---------------|----------------------| +| Calculator | Outgrow, Calconic, Typeform | When logic is complex, or brand/speed matters | +| Generator | Typeform + Zapier, GPT wrappers | When you need custom LLM behavior | +| Checker | Limited — usually needs dev | Always (URL crawling, text analysis) | +| Grader | Outgrow, Involve.me | When the rubric is fixed and simple | +| Converter | Findable no-code tools | Rarely — utility tools are trivially buildable | +| Template | Google Docs, Notion, Canva | When document quality matters | +| Visualization | Flourish, Observable | When data is complex or interactive | + +--- + +## What Makes a Tool "10x Better Than the Existing Free Option" + +If there's already a free tool for the job, you need a compelling reason to build yours. One of: + +1. **Niche specificity** — existing tool is generic, yours is specific to your audience's workflow +2. **Better UX** — existing tools are ugly, clunky, or require too many steps +3. **Integrated action** — after results, existing tools drop the user; yours offers next steps or a trial +4. **Unique data or model** — your checker uses proprietary data that others don't have +5. **Shareable output** — existing tools give results in a table; yours generates a shareable card or PDF + +Don't build "the same tool, but ours." That's a traffic fight you won't win. Build "the tool that does what the others don't." diff --git a/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py b/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py new file mode 100644 index 0000000..e5271fe --- /dev/null +++ b/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +""" +tool_roi_estimator.py — Estimates ROI of building a free marketing tool. + +Models the return from a free tool given build cost, maintenance, expected traffic, +conversion rate, and lead value. Outputs ROI timeline, break-even month, and +minimum traffic needed to justify the investment. + +Usage: + python3 tool_roi_estimator.py # runs embedded sample + python3 tool_roi_estimator.py params.json # uses your params + echo '{"build_cost": 5000, "lead_value": 200}' | python3 tool_roi_estimator.py + +JSON input format: + { + "build_cost": 5000, # One-time engineering cost ($) — dev time Ɨ rate + "monthly_maintenance": 150, # Ongoing server, API, ops cost per month ($) + "traffic_month_1": 500, # Expected organic sessions in month 1 + "traffic_growth_rate": 0.15, # Monthly organic traffic growth rate (0.15 = 15%) + "tool_completion_rate": 0.55, # % of visitors who complete the tool (0.55 = 55%) + "lead_capture_rate": 0.10, # % of completions who give email (0.10 = 10%) + "lead_to_trial_rate": 0.08, # % of leads who start a trial + "trial_to_paid_rate": 0.25, # % of trials who become paid customers + "ltv": 1200, # Customer LTV ($) + "months_to_model": 24, # How many months to project + "seo_ramp_months": 3, # Months before organic traffic kicks in (0 if PH/HN spike) + "backlink_value_monthly": 200, # Estimated value of earned backlinks (DA Ɨ niche rate) + "tool_name": "ROI Calculator" # For display only + } +""" + +import json +import math +import sys + + +# --------------------------------------------------------------------------- +# Core calculations +# --------------------------------------------------------------------------- + +def traffic_at_month(params, month): + """ + Traffic grows from near-zero during SEO ramp, then compounds. + Month 1 = launch spike (Product Hunt / HN etc.) if ramp=0, or baseline. + """ + ramp = params.get("seo_ramp_months", 3) + base = params["traffic_month_1"] + growth = params["traffic_growth_rate"] + + if month <= ramp: + # Linear ramp to base traffic during SEO warmup + return round(base * (month / ramp), 0) if ramp > 0 else base + else: + # Compound growth after ramp + months_since_ramp = month - ramp + return round(base * ((1 + growth) ** months_since_ramp), 0) + + +def leads_at_month(params, sessions): + completion_rate = params["tool_completion_rate"] + lead_capture_rate = params["lead_capture_rate"] + completions = sessions * completion_rate + leads = completions * lead_capture_rate + return round(leads, 1) + + +def customers_at_month(params, leads): + trial_rate = params["lead_to_trial_rate"] + paid_rate = params["trial_to_paid_rate"] + customers = leads * trial_rate * paid_rate + return round(customers, 2) + + +def revenue_at_month(params, customers): + return round(customers * params["ltv"], 2) + + +def cost_at_month(params, month): + """ + Month 1: build cost + maintenance. + Subsequent months: maintenance only. + """ + maintenance = params["monthly_maintenance"] + backlink_value = params.get("backlink_value_monthly", 0) + if month == 1: + return params["build_cost"] + maintenance + return maintenance # backlink value is additive, not a cost + + +def backlink_value_at_month(params, month): + """Backlinks grow slowly — assume linear ramp over 6 months.""" + max_val = params.get("backlink_value_monthly", 0) + ramp = 6 + if month >= ramp: + return max_val + return round(max_val * (month / ramp), 2) + + +def build_projection(params): + months = params["months_to_model"] + rows = [] + cumulative_cost = 0 + cumulative_revenue = 0 + cumulative_backlink_value = 0 + + for m in range(1, months + 1): + sessions = traffic_at_month(params, m) + leads = leads_at_month(params, sessions) + customers = customers_at_month(params, leads) + revenue = revenue_at_month(params, customers) + cost = cost_at_month(params, m) + bl_value = backlink_value_at_month(params, m) + + cumulative_cost += cost + cumulative_revenue += revenue + cumulative_backlink_value += bl_value + total_value = cumulative_revenue + cumulative_backlink_value + cumulative_net = total_value - cumulative_cost + + rows.append({ + "month": m, + "sessions": int(sessions), + "leads": leads, + "customers": customers, + "revenue": revenue, + "cost": round(cost, 2), + "backlink_value": bl_value, + "cumulative_cost": round(cumulative_cost, 2), + "cumulative_revenue": round(cumulative_revenue, 2), + "cumulative_backlink_value": round(cumulative_backlink_value, 2), + "cumulative_net": round(cumulative_net, 2), + }) + + return rows + + +def find_break_even_month(projection): + for row in projection: + if row["cumulative_net"] >= 0: + return row["month"] + return None + + +def calculate_minimum_traffic(params): + """ + What monthly traffic volume is needed to break even within 12 months? + Solve for traffic where 12-month cumulative net >= 0. + Uses binary search. + """ + target_months = 12 + total_cost_12mo = params["build_cost"] + params["monthly_maintenance"] * target_months + + # Revenue per session (steady state, month 12) + completion = params["tool_completion_rate"] + lead_cap = params["lead_capture_rate"] + trial = params["lead_to_trial_rate"] + paid = params["trial_to_paid_rate"] + ltv = params["ltv"] + bl_monthly = params.get("backlink_value_monthly", 0) + + revenue_per_session = completion * lead_cap * trial * paid * ltv + + # Total sessions needed over 12 months (ignoring ramp for simplification) + if revenue_per_session <= 0: + return None + + # With backlink value: total_value = sessions_total Ɨ revenue_per_session + 12 Ɨ bl_monthly + # sessions_total = total needed + total_bl_value = bl_monthly * 12 * 0.5 # ramp factor + needed_from_sessions = max(0, total_cost_12mo - total_bl_value) + min_monthly_sessions = needed_from_sessions / (target_months * 0.6 * revenue_per_session) + # 0.6 factor: first 3 months lower traffic during ramp + + return round(min_monthly_sessions, 0) + + +def calculate_roi_summary(projection, params): + if not projection: + return {} + last = projection[-1] + total_cost = last["cumulative_cost"] + total_revenue = last["cumulative_revenue"] + total_value = total_revenue + last["cumulative_backlink_value"] + net = last["cumulative_net"] + roi = (net / total_cost * 100) if total_cost > 0 else 0 + total_leads = sum(r["leads"] for r in projection) + total_customers = sum(r["customers"] for r in projection) + cost_per_lead = total_cost / total_leads if total_leads > 0 else 0 + + return { + "total_cost": round(total_cost, 2), + "total_revenue": round(total_revenue, 2), + "total_value_with_backlinks": round(total_value, 2), + "net_benefit": round(net, 2), + "roi_pct": round(roi, 1), + "total_leads": round(total_leads, 0), + "total_customers": round(total_customers, 1), + "cost_per_lead": round(cost_per_lead, 2), + } + + +# --------------------------------------------------------------------------- +# Formatting +# --------------------------------------------------------------------------- + +def fc(value): + return f"${value:,.2f}" + + +def fp(value): + return f"{value:.1f}%" + + +def fi(value): + return f"{int(value):,}" + + +def print_report(params, projection, summary, break_even, min_traffic): + tool_name = params.get("tool_name", "Free Tool") + months = params["months_to_model"] + + print("\n" + "=" * 65) + print(f"FREE TOOL ROI ESTIMATOR — {tool_name.upper()}") + print("=" * 65) + + print("\nšŸ“Š INPUT PARAMETERS") + print(f" Build cost (one-time): {fc(params['build_cost'])}") + print(f" Monthly maintenance: {fc(params['monthly_maintenance'])}") + print(f" Starting monthly traffic: {fi(params['traffic_month_1'])} sessions") + print(f" Monthly traffic growth: {fp(params['traffic_growth_rate'] * 100)}") + print(f" SEO ramp period: {params.get('seo_ramp_months', 3)} months") + print(f" Tool completion rate: {fp(params['tool_completion_rate'] * 100)}") + print(f" Lead capture rate: {fp(params['lead_capture_rate'] * 100)} (of completions)") + print(f" Lead → trial rate: {fp(params['lead_to_trial_rate'] * 100)}") + print(f" Trial → paid rate: {fp(params['trial_to_paid_rate'] * 100)}") + print(f" LTV: {fc(params['ltv'])}") + print(f" Backlink value (monthly): {fc(params.get('backlink_value_monthly', 0))}") + + print(f"\nšŸ“ˆ {months}-MONTH SUMMARY") + print(f" Total investment: {fc(summary['total_cost'])}") + print(f" Revenue from leads: {fc(summary['total_revenue'])}") + print(f" Backlink value: {fc(summary.get('total_value_with_backlinks', 0) - summary['total_revenue'])}") + print(f" Total value generated: {fc(summary.get('total_value_with_backlinks', summary['total_revenue']))}") + print(f" Net benefit: {fc(summary['net_benefit'])}") + print(f" ROI: {fp(summary['roi_pct'])}") + + print(f"\nšŸŽÆ LEAD & CUSTOMER METRICS") + print(f" Total leads generated: {fi(summary['total_leads'])}") + print(f" Total customers acquired: {round(summary['total_customers'], 1)}") + print(f" Cost per lead: {fc(summary['cost_per_lead'])}") + print(f" CAC via tool: {fc(summary['total_cost'] / max(summary['total_customers'], 0.01))}") + + print(f"\nā± BREAK-EVEN ANALYSIS") + if break_even: + print(f" Break-even month: Month {break_even}") + assessment = "🟢 Fast payback" if break_even <= 6 else "🟔 Moderate" if break_even <= 12 else "šŸ”“ Long payback" + print(f" Assessment: {assessment}") + else: + print(f" Break-even month: Not reached in {months} months āš ļø") + print(f" Action needed: Increase traffic, improve completion/capture rate, or reduce build cost") + + if min_traffic: + print(f" Min traffic for 12-mo break-even: {fi(min_traffic)} sessions/month") + current = params["traffic_month_1"] + if current >= min_traffic: + print(f" Your projected traffic ({fi(current)}/mo) exceeds minimum āœ…") + else: + gap = min_traffic - current + print(f" Traffic gap: need {fi(gap)} more sessions/month than projected āš ļø") + + print(f"\nšŸ“… MONTHLY PROJECTION") + print(f" {'Mo':>3} {'Sessions':>9} {'Leads':>6} {'Custs':>6} {'Revenue':>9} {'Cum Net':>10}") + print(f" {'-'*3} {'-'*9} {'-'*6} {'-'*6} {'-'*9} {'-'*10}") + for row in projection: + net = row["cumulative_net"] + net_str = fc(net) if net >= 0 else f"({fc(abs(net))})" + be_marker = " ← break-even" if row["month"] == break_even else "" + print(f" {row['month']:>3} {fi(row['sessions']):>9} {row['leads']:>6.1f} {row['customers']:>6.2f}" + f" {fc(row['revenue']):>9} {net_str:>10}{be_marker}") + + print("\n" + "=" * 65) + + # Recommendations + print("\nšŸ’” RECOMMENDATIONS") + roi = summary["roi_pct"] + if roi > 200: + print(" āœ… Strong ROI case — build it, invest in distribution") + elif roi > 50: + print(" 🟔 Positive ROI but slim — validate keyword volume before committing full build cost") + print(" Consider: MVP version (no-code) to test demand before full dev investment") + else: + print(" šŸ”“ ROI case is weak — investigate:") + print(" 1. Is the target keyword validated? (check search volume)") + print(" 2. Can you reduce build cost? (no-code MVP first)") + print(" 3. Is the lead-to-customer conversion realistic?") + print(" 4. Is the LTV accurate?") + + completion = params["tool_completion_rate"] + if completion < 0.40: + print(" āš ļø Low completion rate — reconsider UX or number of required inputs") + if params["lead_capture_rate"] < 0.05: + print(" āš ļø Low lead capture — check gate placement (should be after value is delivered)") + if break_even and break_even > 18: + print(" āš ļø Long break-even — prioritize launch distribution to accelerate traffic ramp") + + +# --------------------------------------------------------------------------- +# Default sample +# --------------------------------------------------------------------------- + +DEFAULT_PARAMS = { + "tool_name": "SaaS ROI Calculator", + "build_cost": 4000, + "monthly_maintenance": 100, + "traffic_month_1": 600, + "traffic_growth_rate": 0.12, + "seo_ramp_months": 3, + "tool_completion_rate": 0.55, + "lead_capture_rate": 0.12, + "lead_to_trial_rate": 0.08, + "trial_to_paid_rate": 0.25, + "ltv": 1400, + "months_to_model": 18, + "backlink_value_monthly": 150, +} + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + params = None + + if len(sys.argv) > 1: + try: + with open(sys.argv[1]) as f: + params = json.load(f) + except Exception as e: + print(f"Error reading file: {e}", file=sys.stderr) + sys.exit(1) + elif not sys.stdin.isatty(): + raw = sys.stdin.read().strip() + if raw: + try: + params = json.loads(raw) + except Exception as e: + print(f"Error reading stdin: {e}", file=sys.stderr) + sys.exit(1) + else: + print("No input provided — running with sample parameters.\n") + params = DEFAULT_PARAMS + else: + print("No input provided — running with sample parameters.\n") + params = DEFAULT_PARAMS + + # Fill defaults for any missing keys + for k, v in DEFAULT_PARAMS.items(): + params.setdefault(k, v) + + projection = build_projection(params) + summary = calculate_roi_summary(projection, params) + break_even = find_break_even_month(projection) + min_traffic = calculate_minimum_traffic(params) + + print_report(params, projection, summary, break_even, min_traffic) + + # JSON output + json_output = { + "inputs": params, + "results": { + "roi_pct": summary["roi_pct"], + "break_even_month": break_even, + "total_leads": summary["total_leads"], + "total_customers": summary["total_customers"], + "cost_per_lead": summary["cost_per_lead"], + "net_benefit": summary["net_benefit"], + "min_monthly_traffic_for_12mo_breakeven": min_traffic, + } + } + + print("\n--- JSON Output ---") + print(json.dumps(json_output, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/launch-strategy/SKILL.md b/marketing-skill/launch-strategy/SKILL.md new file mode 100644 index 0000000..bcf74bd --- /dev/null +++ b/marketing-skill/launch-strategy/SKILL.md @@ -0,0 +1,387 @@ +--- +name: launch-strategy +description: "When the user wants to plan a product launch, feature announcement, or release strategy. Also use when the user mentions 'launch,' 'Product Hunt,' 'feature release,' 'announcement,' 'go-to-market,' 'beta launch,' 'early access,' 'waitlist,' 'product update,' 'GTM plan,' 'launch checklist,' or 'launch momentum.' This skill covers phased launches, channel strategy, and ongoing launch momentum." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Launch Strategy + +You are an expert in SaaS product launches and feature announcements. Your goal is to help users plan launches that build momentum, capture attention, and convert interest into users. + +## Before Starting + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +--- + +## Core Philosophy + +The best companies don't just launch once—they launch again and again. Every new feature, improvement, and update is an opportunity to capture attention and engage your audience. + +A strong launch isn't about a single moment. It's about: +- Getting your product into users' hands early +- Learning from real feedback +- Making a splash at every stage +- Building momentum that compounds over time + +--- + +## The ORB Framework + +Structure your launch marketing across three channel types. Everything should ultimately lead back to owned channels. + +### Owned Channels +You own the channel (though not the audience). Direct access without algorithms or platform rules. + +**Examples:** +- Email list +- Blog +- Podcast +- Branded community (Slack, Discord) +- Website/product + +**Why they matter:** +- Get more effective over time +- No algorithm changes or pay-to-play +- Direct relationship with audience +- Compound value from content + +**Start with 1-2 based on audience:** +- Industry lacks quality content → Start a blog +- People want direct updates → Focus on email +- Engagement matters → Build a community + +**Example - Superhuman:** +Built demand through an invite-only waitlist and one-on-one onboarding sessions. Every new user got a 30-minute live demo. This created exclusivity, FOMO, and word-of-mouth—all through owned relationships. Years later, their original onboarding materials still drive engagement. + +### Rented Channels +Platforms that provide visibility but you don't control. Algorithms shift, rules change, pay-to-play increases. + +**Examples:** +- Social media (Twitter/X, LinkedIn, Instagram) +- App stores and marketplaces +- YouTube +- Reddit + +**How to use correctly:** +- Pick 1-2 platforms where your audience is active +- Use them to drive traffic to owned channels +- Don't rely on them as your only strategy + +**Example - Notion:** +Hacked virality through Twitter, YouTube, and Reddit where productivity enthusiasts were active. Encouraged community to share templates and workflows. But they funneled all visibility into owned assets—every viral post led to signups, then targeted email onboarding. + +**Platform-specific tactics:** +- Twitter/X: Threads that spark conversation → link to newsletter +- LinkedIn: High-value posts → lead to gated content or email signup +- Marketplaces (Shopify, Slack): Optimize listing → drive to site for more + +Rented channels give speed, not stability. Capture momentum by bringing users into your owned ecosystem. + +### Borrowed Channels +Tap into someone else's audience to shortcut the hardest part—getting noticed. + +**Examples:** +- Guest content (blog posts, podcast interviews, newsletter features) +- Collaborations (webinars, co-marketing, social takeovers) +- Speaking engagements (conferences, panels, virtual summits) +- Influencer partnerships + +**Be proactive, not passive:** +1. List industry leaders your audience follows +2. Pitch win-win collaborations +3. Use tools like SparkToro or Listen Notes to find audience overlap +4. Set up affiliate/referral incentives + +**Example - TRMNL:** +Sent a free e-ink display to YouTuber Snazzy Labs—not a paid sponsorship, just hoping he'd like it. He created an in-depth review that racked up 500K+ views and drove $500K+ in sales. They also set up an affiliate program for ongoing promotion. + +Borrowed channels give instant credibility, but only work if you convert borrowed attention into owned relationships. + +--- + +## Five-Phase Launch Approach + +Launching isn't a one-day event. It's a phased process that builds momentum. + +### Phase 1: Internal Launch +Gather initial feedback and iron out major issues before going public. + +**Actions:** +- Recruit early users one-on-one to test for free +- Collect feedback on usability gaps and missing features +- Ensure prototype is functional enough to demo (doesn't need to be production-ready) + +**Goal:** Validate core functionality with friendly users. + +### Phase 2: Alpha Launch +Put the product in front of external users in a controlled way. + +**Actions:** +- Create landing page with early access signup form +- Announce the product exists +- Invite users individually to start testing +- MVP should be working in production (even if still evolving) + +**Goal:** First external validation and initial waitlist building. + +### Phase 3: Beta Launch +Scale up early access while generating external buzz. + +**Actions:** +- Work through early access list (some free, some paid) +- Start marketing with teasers about problems you solve +- Recruit friends, investors, and influencers to test and share + +**Consider adding:** +- Coming soon landing page or waitlist +- "Beta" sticker in dashboard navigation +- Email invites to early access list +- Early access toggle in settings for experimental features + +**Goal:** Build buzz and refine product with broader feedback. + +### Phase 4: Early Access Launch +Shift from small-scale testing to controlled expansion. + +**Actions:** +- Leak product details: screenshots, feature GIFs, demos +- Gather quantitative usage data and qualitative feedback +- Run user research with engaged users (incentivize with credits) +- Optionally run product/market fit survey to refine messaging + +**Expansion options:** +- Option A: Throttle invites in batches (5-10% at a time) +- Option B: Invite all users at once under "early access" framing + +**Goal:** Validate at scale and prepare for full launch. + +### Phase 5: Full Launch +Open the floodgates. + +**Actions:** +- Open self-serve signups +- Start charging (if not already) +- Announce general availability across all channels + +**Launch touchpoints:** +- Customer emails +- In-app popups and product tours +- Website banner linking to launch assets +- "New" sticker in dashboard navigation +- Blog post announcement +- Social posts across platforms +- Product Hunt, BetaList, Hacker News, etc. + +**Goal:** Maximum visibility and conversion to paying users. + +--- + +## Product Hunt Launch Strategy + +Product Hunt can be powerful for reaching early adopters, but it's not magic—it requires preparation. + +### Pros +- Exposure to tech-savvy early adopter audience +- Credibility bump (especially if Product of the Day) +- Potential PR coverage and backlinks + +### Cons +- Very competitive to rank well +- Short-lived traffic spikes +- Requires significant pre-launch planning + +### How to Launch Successfully + +**Before launch day:** +1. Build relationships with influential supporters, content hubs, and communities +2. Optimize your listing: compelling tagline, polished visuals, short demo video +3. Study successful launches to identify what worked +4. Engage in relevant communities—provide value before pitching +5. Prepare your team for all-day engagement + +**On launch day:** +1. Treat it as an all-day event +2. Respond to every comment in real-time +3. Answer questions and spark discussions +4. Encourage your existing audience to engage +5. Direct traffic back to your site to capture signups + +**After launch day:** +1. Follow up with everyone who engaged +2. Convert Product Hunt traffic into owned relationships (email signups) +3. Continue momentum with post-launch content + +### Case Studies + +**SavvyCal** (Scheduling tool): +- Optimized landing page and onboarding before launch +- Built relationships with productivity/SaaS influencers in advance +- Responded to every comment on launch day +- Result: #2 Product of the Month + +**Reform** (Form builder): +- Studied successful launches and applied insights +- Crafted clear tagline, polished visuals, demo video +- Engaged in communities before launch (provided value first) +- Treated launch as all-day engagement event +- Directed traffic to capture signups +- Result: #1 Product of the Day + +--- + +## Post-Launch Product Marketing + +Your launch isn't over when the announcement goes live. Now comes adoption and retention work. + +### Immediate Post-Launch Actions + +**Educate new users:** +Set up automated onboarding email sequence introducing key features and use cases. + +**Reinforce the launch:** +Include announcement in your weekly/biweekly/monthly roundup email to catch people who missed it. + +**Differentiate against competitors:** +Publish comparison pages highlighting why you're the obvious choice. + +**Update web pages:** +Add dedicated sections about the new feature/product across your site. + +**Offer hands-on preview:** +Create no-code interactive demo (using tools like Navattic) so visitors can explore before signing up. + +### Keep Momentum Going +It's easier to build on existing momentum than start from scratch. Every touchpoint reinforces the launch. + +--- + +## Ongoing Launch Strategy + +Don't rely on a single launch event. Regular updates and feature rollouts sustain engagement. + +### How to Prioritize What to Announce + +Use this matrix to decide how much marketing each update deserves: + +**Major updates** (new features, product overhauls): +- Full campaign across multiple channels +- Blog post, email campaign, in-app messages, social media +- Maximize exposure + +**Medium updates** (new integrations, UI enhancements): +- Targeted announcement +- Email to relevant segments, in-app banner +- Don't need full fanfare + +**Minor updates** (bug fixes, small tweaks): +- Changelog and release notes +- Signal that product is improving +- Don't dominate marketing + +### Announcement Tactics + +**Space out releases:** +Instead of shipping everything at once, stagger announcements to maintain momentum. + +**Reuse high-performing tactics:** +If a previous announcement resonated, apply those insights to future updates. + +**Keep engaging:** +Continue using email, social, and in-app messaging to highlight improvements. + +**Signal active development:** +Even small changelog updates remind customers your product is evolving. This builds retention and word-of-mouth—customers feel confident you'll be around. + +--- + +## Launch Checklist + +### Pre-Launch +- [ ] Landing page with clear value proposition +- [ ] Email capture / waitlist signup +- [ ] Early access list built +- [ ] Owned channels established (email, blog, community) +- [ ] Rented channel presence (social profiles optimized) +- [ ] Borrowed channel opportunities identified (podcasts, influencers) +- [ ] Product Hunt listing prepared (if using) +- [ ] Launch assets created (screenshots, demo video, GIFs) +- [ ] Onboarding flow ready +- [ ] Analytics/tracking in place + +### Launch Day +- [ ] Announcement email to list +- [ ] Blog post published +- [ ] Social posts scheduled and posted +- [ ] Product Hunt listing live (if using) +- [ ] In-app announcement for existing users +- [ ] Website banner/notification active +- [ ] Team ready to engage and respond +- [ ] Monitor for issues and feedback + +### Post-Launch +- [ ] Onboarding email sequence active +- [ ] Follow-up with engaged prospects +- [ ] Roundup email includes announcement +- [ ] Comparison pages published +- [ ] Interactive demo created +- [ ] Gather and act on feedback +- [ ] Plan next launch moment + +--- + +## Task-Specific Questions + +1. What are you launching? (New product, major feature, minor update) +2. What's your current audience size and engagement? +3. What owned channels do you have? (Email list size, blog traffic, community) +4. What's your timeline for launch? +5. Have you launched before? What worked/didn't work? +6. Are you considering Product Hunt? What's your preparation status? + +--- + +## Proactive Triggers + +Proactively offer launch planning when: + +1. **Feature ship date mentioned** — When an engineering delivery date is discussed, immediately ask about the launch plan; shipping without a marketing plan is a missed opportunity. +2. **Waitlist or early access mentioned** — Offer to design the full phased launch funnel from alpha through full GA, not just the landing page. +3. **Product Hunt consideration** — Any mention of Product Hunt should trigger the full PH strategy section including pre-launch relationship building timeline. +4. **Post-launch silence** — If a user launched recently but hasn't followed up with momentum content, proactively suggest the post-launch marketing actions (comparison pages, roundup email, interactive demo). +5. **Pricing change planned** — Pricing updates are a launch opportunity; offer to build an announcement campaign treating it as a product update. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Launch Plan | Markdown doc | Phase-by-phase plan with owners, dates, channels, and success metrics | +| ORB Channel Map | Table | Owned/Rented/Borrowed channel strategy with tactics per channel | +| Launch Day Checklist | Checklist | Complete day-of execution checklist with time-boxed actions | +| Product Hunt Brief | Markdown doc | Listing copy, asset specs, pre-launch timeline, engagement playbook | +| Post-Launch Momentum Plan | Bulleted list | 30-day post-launch actions to sustain and compound the launch | + +--- + +## Communication + +Launch plans should be concrete, time-bound, and channel-specific — no vague "post on social media" recommendations. Every output should specify who does what and when. Reference `marketing-context` to ensure the launch narrative matches ICP language and positioning before drafting any copy. Quality bar: a launch plan is only complete when it covers all three ORB channel types and includes both launch-day and post-launch actions. + +--- + +## Related Skills + +- **email-sequence** — USE for building the launch announcement and post-launch onboarding email sequences; NOT as a substitute for the full channel strategy. +- **social-content** — USE for drafting the specific social posts and threads for launch day; NOT for channel selection strategy. +- **paid-ads** — USE when the launch plan includes a paid amplification component; NOT for organic launch-only strategies. +- **content-strategy** — USE when the launch requires a sustained content program (blog posts, case studies) in the weeks after; NOT for single-day launch execution. +- **pricing-strategy** — USE when the launch involves a pricing change or new tier introduction; NOT for feature-only launches. +- **marketing-context** — USE as foundation to align launch messaging with ICP and brand voice; always load first. diff --git a/marketing-skill/launch-strategy/scripts/launch_readiness_scorer.py b/marketing-skill/launch-strategy/scripts/launch_readiness_scorer.py new file mode 100644 index 0000000..46a68e0 --- /dev/null +++ b/marketing-skill/launch-strategy/scripts/launch_readiness_scorer.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 +""" +launch_readiness_scorer.py — Product Launch Readiness Scorer +100% stdlib, no pip installs required. + +Usage: + python3 launch_readiness_scorer.py # demo mode + python3 launch_readiness_scorer.py --checklist checklist.json + python3 launch_readiness_scorer.py --checklist checklist.json --json + python3 launch_readiness_scorer.py --export-template > my_checklist.json + +checklist.json format: + { + "product": [ + {"item": "Beta tested with 10+ users", "status": "done"}, + {"item": "Documentation ready", "status": "partial"}, + {"item": "Support team trained", "status": "not_started"} + ], + "marketing": [...], + "technical": [...] + } + +Valid status values: "done" | "partial" | "not_started" +""" + +import argparse +import json +import sys +from datetime import datetime, timezone + + +# --------------------------------------------------------------------------- +# Default checklist template +# --------------------------------------------------------------------------- + +DEFAULT_CHECKLIST = { + "product": [ + {"item": "Beta tested with real users (≄10)", "status": "done", "weight": 3}, + {"item": "Core user journey validated end-to-end", "status": "done", "weight": 3}, + {"item": "Known P0/P1 bugs resolved", "status": "partial", "weight": 3}, + {"item": "User-facing documentation complete", "status": "partial", "weight": 2}, + {"item": "In-app onboarding / empty states ready", "status": "done", "weight": 2}, + {"item": "Support team trained on common Q&A", "status": "not_started", "weight": 2}, + {"item": "Pricing finalised and live", "status": "done", "weight": 2}, + {"item": "Accessibility basics checked (WCAG AA)", "status": "not_started", "weight": 1}, + {"item": "Localisation / i18n ready (if applicable)", "status": "done", "weight": 1}, + {"item": "Feedback collection mechanism in place", "status": "partial", "weight": 1}, + ], + "marketing": [ + {"item": "Landing page live and conversion-optimised", "status": "done", "weight": 3}, + {"item": "Email announcement list ready (≄100)", "status": "done", "weight": 3}, + {"item": "Press / media kit prepared", "status": "partial", "weight": 2}, + {"item": "Social media assets created", "status": "done", "weight": 2}, + {"item": "Product Hunt / launch platform submission", "status": "not_started", "weight": 2}, + {"item": "SEO meta tags and OG images set", "status": "done", "weight": 2}, + {"item": "Influencer / community outreach planned", "status": "partial", "weight": 2}, + {"item": "Launch-day email sequence scheduled", "status": "not_started", "weight": 2}, + {"item": "Paid ads creative prepared (if applicable)", "status": "not_started", "weight": 1}, + {"item": "Referral / viral loop mechanism designed", "status": "not_started", "weight": 1}, + ], + "technical": [ + {"item": "Production monitoring & alerting active", "status": "done", "weight": 3}, + {"item": "Load / performance tested at 5Ɨ expected", "status": "partial", "weight": 3}, + {"item": "Rollback plan documented and rehearsed", "status": "not_started", "weight": 3}, + {"item": "Database backups verified and automated", "status": "done", "weight": 2}, + {"item": "CDN / caching configured", "status": "done", "weight": 2}, + {"item": "Error tracking (Sentry/similar) live", "status": "done", "weight": 2}, + {"item": "SSL / HTTPS confirmed on all endpoints", "status": "done", "weight": 2}, + {"item": "Analytics events firing correctly", "status": "partial", "weight": 2}, + {"item": "Rate limiting / DDoS protection in place", "status": "partial", "weight": 2}, + {"item": "Feature flags configured for safe rollout", "status": "not_started", "weight": 1}, + ], +} + +CATEGORY_META = { + "product": {"emoji": "šŸ›  ", "label": "Product Readiness"}, + "marketing": {"emoji": "šŸ“£ ", "label": "Marketing Readiness"}, + "technical": {"emoji": "āš™ļø ", "label": "Technical Readiness"}, +} + +STATUS_WEIGHTS = { + "done": 1.0, + "partial": 0.5, + "not_started": 0.0, +} + +BLOCKERS_THRESHOLD = 0.0 # not_started items with weight ≄3 are blockers + + +# --------------------------------------------------------------------------- +# Core scoring +# --------------------------------------------------------------------------- + +def score_category(items: list) -> dict: + """Score a single category 0-100 using weighted item scores.""" + if not items: + return {"score": 0, "items": [], "blockers": []} + + total_weight = 0 + earned_weight = 0 + blockers = [] + scored_items = [] + + for it in items: + raw_status = it.get("status", "not_started").strip().lower() + status = raw_status if raw_status in STATUS_WEIGHTS else "not_started" + weight = it.get("weight", 1) + sw = STATUS_WEIGHTS[status] + earned = sw * weight + + total_weight += weight + earned_weight += earned + + scored_items.append({ + "item": it["item"], + "status": status, + "weight": weight, + "points_earned": earned, + "points_max": weight, + }) + + if status == "not_started" and weight >= 3: + blockers.append(it["item"]) + + score = round((earned_weight / total_weight) * 100) if total_weight > 0 else 0 + return { + "score": score, + "score_label": _score_label(score), + "items": scored_items, + "blockers": blockers, + "items_done": sum(1 for i in scored_items if i["status"] == "done"), + "items_partial": sum(1 for i in scored_items if i["status"] == "partial"), + "items_pending": sum(1 for i in scored_items if i["status"] == "not_started"), + "total_items": len(scored_items), + } + + +def score_readiness(checklist: dict) -> dict: + """Score all categories and produce an overall launch readiness result.""" + categories = {} + all_scores = [] + all_blockers = [] + + for cat, items in checklist.items(): + result = score_category(items) + categories[cat] = result + all_scores.append(result["score"]) + all_blockers.extend(result["blockers"]) + + overall = round(sum(all_scores) / len(all_scores)) if all_scores else 0 + + return { + "overall": { + "score": overall, + "score_label": _score_label(overall), + "launch_decision": _launch_decision(overall, all_blockers), + "blockers": all_blockers, + "generated_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), + }, + "categories": { + cat: {**CATEGORY_META.get(cat, {"emoji": "šŸ“‹", "label": cat.title()}), + **res} + for cat, res in categories.items() + }, + "action_plan": _action_plan(categories), + } + + +def _launch_decision(score: int, blockers: list) -> str: + if blockers: + return f"ā›” NOT READY — {len(blockers)} blocker(s) must be resolved before launch." + if score >= 80: + return "āœ… LAUNCH READY — all categories are in good shape." + if score >= 60: + return "🟔 CONDITIONAL — address partial items but launch is defensible." + if score >= 40: + return "🟠 CAUTION — significant gaps; soft launch / waitlist recommended." + return "šŸ”“ NOT READY — major preparation required across multiple areas." + + +def _action_plan(categories: dict) -> list: + """Build a prioritised action list: blockers first, then by score ascending.""" + actions = [] + for cat, res in categories.items(): + label = CATEGORY_META.get(cat, {}).get("label", cat.title()) + for bl in res.get("blockers", []): + actions.append({ + "priority": "🚨 BLOCKER", + "category": label, + "action": bl, + }) + for cat, res in sorted(categories.items(), key=lambda x: x[1]["score"]): + label = CATEGORY_META.get(cat, {}).get("label", cat.title()) + for it in res.get("items", []): + if it["status"] == "partial": + actions.append({ + "priority": "āš ļø PARTIAL", + "category": label, + "action": f"Complete: {it['item']}", + }) + return actions[:15] # top 15 actions + + +def _score_label(s: int) -> str: + if s >= 90: return "Excellent" + if s >= 75: return "Good" + if s >= 60: return "Fair" + if s >= 40: return "Poor" + return "Critical" + + +# --------------------------------------------------------------------------- +# Pretty-print +# --------------------------------------------------------------------------- + +def pretty_print(result: dict) -> None: + ov = result["overall"] + + print("\n" + "=" * 65) + print(" šŸš€ LAUNCH READINESS SCORER") + print("=" * 65) + + print(f"\n Overall Score : {ov['score']}/100 ({ov['score_label']})") + print(f" Launch Decision : {ov['launch_decision']}") + if ov["blockers"]: + print(f"\n 🚨 BLOCKERS ({len(ov['blockers'])}):") + for b in ov["blockers"]: + print(f" • {b}") + + print(f"\n{'─'*65}") + print(f" {'CATEGORY':<30} {'SCORE':>6} {'DONE':>5} {'PARTIAL':>7} {'PENDING':>7}") + print(f"{'─'*65}") + + for cat, res in result["categories"].items(): + bar = "ā–ˆ" * (res["score"] // 10) + "ā–‘" * (10 - res["score"] // 10) + print(f" {res['emoji']} {res['label']:<27} {res['score']:>5}/100 " + f"{res['items_done']:>5} {res['items_partial']:>7} {res['items_pending']:>7} {bar}") + + print(f"\n{'─'*65}") + print(f" šŸ—‚ CATEGORY DETAILS\n") + + for cat, res in result["categories"].items(): + print(f" {res['emoji']} {res['label']} — {res['score']}/100 ({res['score_label']})") + for it in res["items"]: + icon = {"done": "āœ…", "partial": "šŸ”¶", "not_started": "⬜"}.get(it["status"], "⬜") + print(f" {icon} [{it['status']:<11}] (w={it['weight']}) {it['item']}") + print() + + ap = result["action_plan"] + if ap: + print(f" šŸ“‹ ACTION PLAN (top {len(ap)} items)\n") + for i, a in enumerate(ap, 1): + print(f" {i:>2}. {a['priority']} [{a['category']}] {a['action']}") + + print(f"\n Generated: {ov['generated_at']}") + print() + + +# --------------------------------------------------------------------------- +# CLI +# --------------------------------------------------------------------------- + +def parse_args(): + parser = argparse.ArgumentParser( + description="Score product launch readiness across categories (stdlib only).", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--checklist", type=str, default=None, + help="Path to JSON checklist file") + parser.add_argument("--json", action="store_true", + help="Output results as JSON") + parser.add_argument("--export-template", action="store_true", + help="Print the default checklist template as JSON and exit") + return parser.parse_args() + + +def main(): + args = parse_args() + + if args.export_template: + print(json.dumps(DEFAULT_CHECKLIST, indent=2)) + return + + if args.checklist: + with open(args.checklist) as f: + checklist = json.load(f) + else: + print("šŸ”¬ DEMO MODE — using embedded sample checklist\n") + checklist = DEFAULT_CHECKLIST + + result = score_readiness(checklist) + + if args.json: + print(json.dumps(result, indent=2)) + else: + pretty_print(result) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/marketing-context/SKILL.md b/marketing-skill/marketing-context/SKILL.md new file mode 100644 index 0000000..4a10fa6 --- /dev/null +++ b/marketing-skill/marketing-context/SKILL.md @@ -0,0 +1,169 @@ +--- +name: marketing-context +description: "Create and maintain the marketing context document that all marketing skills read before starting. Use when the user mentions 'marketing context,' 'brand voice,' 'set up context,' 'target audience,' 'ICP,' 'style guide,' 'who is my customer,' 'positioning,' or wants to avoid repeating foundational information across marketing tasks. Run this at the start of any new project before using other marketing skills." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Marketing Context + +You are an expert product marketer. Your goal is to capture the foundational positioning, messaging, and brand context that every other marketing skill needs — so users never repeat themselves. + +The document is stored at `.agents/marketing-context.md` (or `marketing-context.md` in the project root). + +## How This Skill Works + +### Mode 1: Auto-Draft from Codebase +Study the repo — README, landing pages, marketing copy, about pages, package.json, existing docs — and draft a V1. The user reviews, corrects, and fills gaps. This is faster than starting from scratch. + +### Mode 2: Guided Interview +Walk through each section conversationally, one at a time. Don't dump all questions at once. + +### Mode 3: Update Existing +Read the current context, summarize what's captured, and ask which sections need updating. + +Most users prefer Mode 1. After presenting the draft, ask: *"What needs correcting? What's missing?"* + +--- + +## Sections to Capture + +### 1. Product Overview +- One-line description +- What it does (2-3 sentences) +- Product category (the "shelf" — how customers search for you) +- Product type (SaaS, marketplace, e-commerce, service) +- Business model and pricing + +### 2. Target Audience +- Target company type (industry, size, stage) +- Target decision-makers (roles, departments) +- Primary use case (the main problem you solve) +- Jobs to be done (2-3 things customers "hire" you for) +- Specific use cases or scenarios + +### 3. Personas +For each stakeholder involved in buying: +- Role (User, Champion, Decision Maker, Financial Buyer, Technical Influencer) +- What they care about, their challenge, the value you promise them + +### 4. Problems & Pain Points +- Core challenge customers face before finding you +- Why current solutions fall short +- What it costs them (time, money, opportunities) +- Emotional tension (stress, fear, doubt) + +### 5. Competitive Landscape +- **Direct competitors**: Same solution, same problem +- **Secondary competitors**: Different solution, same problem +- **Indirect competitors**: Conflicting approach entirely +- How each falls short for customers + +### 6. Differentiation +- Key differentiators (capabilities alternatives lack) +- How you solve it differently +- Why that's better (benefits, not features) +- Why customers choose you over alternatives + +### 7. Objections & Anti-Personas +- Top 3 objections heard in sales + how to address each +- Who is NOT a good fit (anti-persona) + +### 8. Switching Dynamics (JTBD Four Forces) +- **Push**: Frustrations driving them away from current solution +- **Pull**: What attracts them to you +- **Habit**: What keeps them stuck with current approach +- **Anxiety**: What worries them about switching + +### 9. Customer Language (Verbatim) +- How customers describe the problem in their own words +- How they describe your solution in their own words +- Words and phrases TO use +- Words and phrases to AVOID +- Glossary of product-specific terms + +### 10. Brand Voice +- Tone (professional, casual, playful, authoritative) +- Communication style (direct, conversational, technical) +- Brand personality (3-5 adjectives) +- Voice DO's and DON'T's + +### 11. Style Guide +- Grammar and mechanics rules +- Capitalization conventions +- Formatting standards +- Preferred terminology + +### 12. Proof Points +- Key metrics or results to cite +- Notable customers / logos +- Testimonial snippets (verbatim) +- Main value themes with supporting evidence + +### 13. Content & SEO Context +- Target keywords (organized by topic cluster) +- Internal links map (key pages, anchor text) +- Writing examples (3-5 exemplary pieces) +- Content tone and length preferences + +### 14. Goals +- Primary business goal +- Key conversion action (what you want people to do) +- Current metrics (if known) + +--- + +## Output Template + +See `templates/marketing-context-template.md` for the full template. + +--- + +## Tips + +- **Be specific**: Ask "What's the #1 frustration that brings them to you?" not "What problem do they solve?" +- **Capture exact words**: Customer language beats polished descriptions +- **Ask for examples**: "Can you give me an example?" unlocks better answers +- **Validate as you go**: Summarize each section and confirm before moving on +- **Skip what doesn't apply**: Not every product needs all sections + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Missing customer language section** → "Without verbatim customer phrases, copy will sound generic. Can you share 3-5 quotes from customers describing their problem?" +- **No competitive landscape defined** → "Every marketing skill performs better with competitor context. Who are the top 3 alternatives your customers consider?" +- **Brand voice undefined** → "Without voice guidelines, every skill will sound different. Let's define 3-5 adjectives that capture your brand." +- **Context older than 6 months** → "Your marketing context was last updated [date]. Positioning may have shifted — review recommended." +- **No proof points** → "Marketing without proof points is opinion. What metrics, logos, or testimonials can we reference?" + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Set up marketing context" | Guided interview → complete `marketing-context.md` | +| "Auto-draft from codebase" | Codebase scan → V1 draft for review | +| "Update positioning" | Targeted update of differentiation + competitive sections | +| "Add customer quotes" | Customer language section populated with verbatim phrases | +| "Review context freshness" | Staleness audit with recommended updates | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **marketing-ops**: Routes marketing questions to the right skill — reads this context first. +- **copywriting**: For landing page and web copy. Reads brand voice + customer language from this context. +- **content-strategy**: For planning what content to create. Reads target keywords + personas from this context. +- **marketing-strategy-pmm**: For positioning and GTM strategy. Reads competitive landscape from this context. +- **cs-onboard** (C-Suite): For company-level context. This skill is marketing-specific — complements, not replaces, company-context.md. diff --git a/marketing-skill/marketing-context/scripts/context_validator.py b/marketing-skill/marketing-context/scripts/context_validator.py new file mode 100644 index 0000000..1394f3c --- /dev/null +++ b/marketing-skill/marketing-context/scripts/context_validator.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +"""Validate marketing context completeness — scores 0-100.""" + +import json +import re +import sys +from pathlib import Path + +SECTIONS = { + "Product Overview": {"required": True, "weight": 10, "markers": ["one-liner", "what it does", "product category", "business model"]}, + "Target Audience": {"required": True, "weight": 12, "markers": ["target compan", "decision-maker", "use case", "jobs to be done"]}, + "Personas": {"required": False, "weight": 5, "markers": ["persona", "champion", "decision maker"]}, + "Problems & Pain Points": {"required": True, "weight": 10, "markers": ["core problem", "fall short", "cost", "tension"]}, + "Competitive Landscape": {"required": True, "weight": 10, "markers": ["direct", "competitor", "secondary"]}, + "Differentiation": {"required": True, "weight": 10, "markers": ["differentiator", "differently", "why customers choose"]}, + "Objections": {"required": False, "weight": 5, "markers": ["objection", "response", "anti-persona"]}, + "Switching Dynamics": {"required": False, "weight": 5, "markers": ["push", "pull", "habit", "anxiety"]}, + "Customer Language": {"required": True, "weight": 10, "markers": ["verbatim", "words to use", "words to avoid"]}, + "Brand Voice": {"required": True, "weight": 8, "markers": ["tone", "style", "personality"]}, + "Style Guide": {"required": False, "weight": 3, "markers": ["grammar", "capitalization", "formatting"]}, + "Proof Points": {"required": True, "weight": 7, "markers": ["metric", "customer", "testimonial"]}, + "Content & SEO": {"required": False, "weight": 3, "markers": ["keyword", "internal link"]}, + "Goals": {"required": True, "weight": 2, "markers": ["business goal", "conversion"]} +} + + +def validate_context(content: str) -> dict: + """Validate marketing context file and return score.""" + content_lower = content.lower() + results = {"sections": {}, "score": 0, "max_score": 100, "missing_required": [], "missing_optional": [], "warnings": []} + total_weight = sum(s["weight"] for s in SECTIONS.values()) + earned = 0 + + for name, config in SECTIONS.items(): + section_present = name.lower().replace("& ", "").replace(" ", " ") in content_lower or any( + m in content_lower for m in config["markers"][:2] + ) + + markers_found = sum(1 for m in config["markers"] if m in content_lower) + markers_total = len(config["markers"]) + + has_placeholder = bool(re.search(r'\[.*?\]', content[content_lower.find(name.lower()):content_lower.find(name.lower()) + 500] if name.lower() in content_lower else "")) + + if section_present and markers_found > 0: + completeness = markers_found / markers_total + if has_placeholder and completeness < 0.5: + completeness *= 0.5 # Penalize unfilled templates + section_score = round(config["weight"] * completeness) + earned += section_score + status = "complete" if completeness >= 0.75 else "partial" + else: + section_score = 0 + status = "missing" + if config["required"]: + results["missing_required"].append(name) + else: + results["missing_optional"].append(name) + + results["sections"][name] = { + "status": status, + "markers_found": markers_found, + "markers_total": markers_total, + "score": section_score, + "max_score": config["weight"], + "required": config["required"] + } + + results["score"] = round((earned / total_weight) * 100) + + # Warnings + if "verbatim" not in content_lower and '"' not in content: + results["warnings"].append("No verbatim customer quotes found — copy will sound generic") + if not re.search(r'\d+%|\$\d+|\d+ customer', content_lower): + results["warnings"].append("No metrics or proof points with numbers found") + if "last updated" in content_lower: + date_match = re.search(r'last updated:?\s*(\d{4}-\d{2}-\d{2})', content_lower) + if date_match: + from datetime import datetime + try: + updated = datetime.strptime(date_match.group(1), "%Y-%m-%d") + age_days = (datetime.now() - updated).days + if age_days > 180: + results["warnings"].append(f"Context is {age_days} days old — review recommended (>180 days)") + except ValueError: + pass + + return results + + +def print_report(results: dict): + """Print human-readable validation report.""" + print(f"\n{'='*50}") + print(f"MARKETING CONTEXT VALIDATION") + print(f"{'='*50}") + print(f"\nOverall Score: {results['score']}/100") + print(f"{'🟢 Strong' if results['score'] >= 80 else '🟔 Needs Work' if results['score'] >= 50 else 'šŸ”“ Incomplete'}") + + print(f"\n{'─'*50}") + print(f"{'Section':<25} {'Status':<10} {'Score':<10}") + print(f"{'─'*50}") + for name, data in results["sections"].items(): + icon = {"complete": "āœ…", "partial": "āš ļø", "missing": "āŒ"}[data["status"]] + req = " *" if data["required"] else "" + print(f"{icon} {name:<23} {data['status']:<10} {data['score']}/{data['max_score']}{req}") + + if results["missing_required"]: + print(f"\nšŸ”“ Missing Required Sections:") + for s in results["missing_required"]: + print(f" → {s}") + + if results["missing_optional"]: + print(f"\n🟔 Missing Optional Sections:") + for s in results["missing_optional"]: + print(f" → {s}") + + if results["warnings"]: + print(f"\nāš ļø Warnings:") + for w in results["warnings"]: + print(f" → {w}") + + print(f"\n* = required section") + print(f"{'='*50}") + + +def main(): + if len(sys.argv) > 1: + filepath = Path(sys.argv[1]) + if not filepath.exists(): + print(f"Error: File not found: {filepath}", file=sys.stderr) + sys.exit(1) + content = filepath.read_text() + else: + # Demo with sample data + content = """# Marketing Context +*Last updated: 2026-01-15* + +## Product Overview +**One-liner:** AI-powered mobility analysis for elderly care +**What it does:** Smartphone-based fall risk assessment using computer vision +**Product category:** HealthTech / Digital Health +**Business model:** SaaS, per-facility licensing + +## Target Audience +**Target companies:** Care facilities, nursing homes, 50+ beds +**Decision-makers:** Facility directors, quality managers +**Primary use case:** Automated fall risk assessment replacing manual observation +**Jobs to be done:** +- Reduce fall incidents by identifying high-risk residents +- Meet regulatory documentation requirements efficiently +- Give care staff actionable mobility insights + +## Problems & Pain Points +**Core problem:** Manual fall risk assessment is subjective, time-consuming, and inconsistent +**Why alternatives fall short:** +- Manual observation takes 30+ minutes per resident +- Paper-based assessments are completed once per quarter at best +**What it costs them:** Falls cost €8,000-12,000 per incident, plus liability +**Emotional tension:** Staff fear missing warning signs, blame after incidents + +## Competitive Landscape +**Direct:** Traditional gait labs — $50K+ hardware, need trained staff +**Secondary:** Wearable sensors — low compliance, residents remove them +**Indirect:** Manual observation — subjective, inconsistent + +## Differentiation +**Key differentiators:** +- Uses standard smartphone (no special hardware) +- AI-powered analysis (objective, repeatable) +**Why customers choose us:** Fast, affordable, no hardware investment + +## Customer Language +**How they describe the problem:** +- "We never know who's going to fall next" +- "The documentation takes forever" +**Words to use:** mobility analysis, fall prevention, care quality +**Words to avoid:** surveillance, monitoring, tracking + +## Brand Voice +**Tone:** Professional, empathetic, evidence-based +**Personality:** Trustworthy, innovative, caring + +## Proof Points +**Metrics:** +- 80+ care facilities served +- 30% reduction in fall incidents (pilot data) +**Customers:** Major care facility chains in Germany + +## Goals +**Business goal:** Expand to 200+ facilities, enter Spain and Netherlands +**Conversion action:** Book a demo +""" + print("[Using embedded sample data — pass a file path for real validation]") + + results = validate_context(content) + print_report(results) + + if "--json" in sys.argv: + print(f"\n{json.dumps(results, indent=2)}") + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/marketing-context/templates/marketing-context-template.md b/marketing-skill/marketing-context/templates/marketing-context-template.md new file mode 100644 index 0000000..a325181 --- /dev/null +++ b/marketing-skill/marketing-context/templates/marketing-context-template.md @@ -0,0 +1,133 @@ +# Marketing Context + +*Last updated: [date]* + +## Product Overview +**One-liner:** [What you do in one sentence] +**What it does:** [2-3 sentences] +**Product category:** [The "shelf" — how customers search for you] +**Product type:** [SaaS, marketplace, e-commerce, service] +**Business model:** [Pricing model and range] + +## Target Audience +**Target companies:** [Industry, size, stage] +**Decision-makers:** [Roles, departments] +**Primary use case:** [The main problem you solve] +**Jobs to be done:** +- [Job 1] +- [Job 2] +- [Job 3] +**Use cases:** +- [Scenario 1] +- [Scenario 2] + +## Personas + +| Persona | Role | Cares about | Challenge | Value we promise | +|---------|------|-------------|-----------|------------------| +| [Name] | User | | | | +| [Name] | Champion | | | | +| [Name] | Decision Maker | | | | +| [Name] | Financial Buyer | | | | + +## Problems & Pain Points +**Core problem:** [What customers face before finding you] +**Why alternatives fall short:** +- [Gap 1] +- [Gap 2] +**What it costs them:** [Time, money, opportunities] +**Emotional tension:** [Stress, fear, doubt] + +## Competitive Landscape + +| Competitor | Type | How they fall short | +|-----------|------|---------------------| +| [Name] | Direct | [Gap] | +| [Name] | Secondary | [Gap] | +| [Name] | Indirect | [Gap] | + +## Differentiation +**Key differentiators:** +- [Differentiator 1] +- [Differentiator 2] +**How we do it differently:** [Approach] +**Why that's better:** [Benefits] +**Why customers choose us:** [Decision drivers] + +## Objections + +| Objection | Response | +|-----------|----------| +| "[Objection 1]" | [How to address] | +| "[Objection 2]" | [How to address] | +| "[Objection 3]" | [How to address] | + +**Anti-persona (NOT a good fit):** [Who should NOT buy this] + +## Switching Dynamics +**Push (away from current):** [Frustrations] +**Pull (toward us):** [Attractions] +**Habit (keeping them stuck):** [Inertia] +**Anxiety (about switching):** [Worries] + +## Customer Language +**How they describe the problem:** +- "[verbatim quote]" +- "[verbatim quote]" +**How they describe us:** +- "[verbatim quote]" +- "[verbatim quote]" +**Words to use:** [list] +**Words to avoid:** [list] + +| Term | Meaning | +|------|---------| +| [Product term] | [Definition] | + +## Brand Voice +**Tone:** [professional, casual, playful, authoritative] +**Style:** [direct, conversational, technical] +**Personality:** [3-5 adjectives] +**Voice DO's:** [list] +**Voice DON'T's:** [list] + +## Style Guide +**Grammar:** [Key rules] +**Capitalization:** [Conventions] +**Formatting:** [Standards] +**Preferred terms:** [List] + +## Proof Points +**Metrics:** +- [Metric 1] +- [Metric 2] +**Customers:** [Notable logos] +**Testimonials:** +> "[quote]" — [Name, Title, Company] +> "[quote]" — [Name, Title, Company] + +| Value Theme | Supporting Proof | +|-------------|-----------------| +| [Theme 1] | [Evidence] | +| [Theme 2] | [Evidence] | + +## Content & SEO Context +**Target keywords:** + +| Cluster | Primary Keyword | Secondary Keywords | Intent | +|---------|----------------|-------------------|--------| +| [Topic 1] | [keyword] | [kw1, kw2] | [informational/commercial] | + +**Internal links map:** + +| Page | URL | Use for | Anchor text | +|------|-----|---------|-------------| +| [Page name] | [URL] | [Topic] | [Suggested anchor] | + +**Writing examples:** +- [URL or file — what makes it good] + +## Goals +**Business goal:** [Primary objective] +**Conversion action:** [What you want people to do] +**Current metrics:** [If known] diff --git a/marketing-skill/marketing-demand-acquisition/SKILL.md b/marketing-skill/marketing-demand-acquisition/SKILL.md index a96b77a..d78468e 100644 --- a/marketing-skill/marketing-demand-acquisition/SKILL.md +++ b/marketing-skill/marketing-demand-acquisition/SKILL.md @@ -308,3 +308,32 @@ Required: | First demo scheduled | 3 business days | **Validation:** Test lead through workflow, verify notifications and routing. + +## Proactive Triggers + +- **Over-relying on one channel** → Single-channel dependency is a business risk. Diversify. +- **No lead scoring** → Not all leads are equal. Route to revenue-operations for scoring. +- **CAC exceeding LTV** → Demand gen is unprofitable. Optimize or cut channels. +- **No nurture for non-ready leads** → 80% of leads aren't ready to buy. Nurture converts them later. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Demand gen plan" | Multi-channel acquisition strategy with budget allocation | +| "Pipeline analysis" | Funnel conversion rates with bottleneck identification | +| "Channel strategy" | Channel selection matrix based on audience and budget | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **paid-ads**: For executing paid acquisition campaigns. +- **content-strategy**: For content-driven demand generation. +- **email-sequence**: For nurture sequences in the demand funnel. +- **campaign-analytics**: For measuring demand gen effectiveness. diff --git a/marketing-skill/marketing-ideas/SKILL.md b/marketing-skill/marketing-ideas/SKILL.md new file mode 100644 index 0000000..e9c2c5b --- /dev/null +++ b/marketing-skill/marketing-ideas/SKILL.md @@ -0,0 +1,211 @@ +--- +name: marketing-ideas +description: "When the user needs marketing ideas, inspiration, or strategies for their SaaS or software product. Also use when the user asks for 'marketing ideas,' 'growth ideas,' 'how to market,' 'marketing strategies,' 'marketing tactics,' 'ways to promote,' or 'ideas to grow.' This skill provides 139 proven marketing approaches organized by category." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Marketing Ideas for SaaS + +You are a marketing strategist with a library of 139 proven marketing ideas. Your goal is to help users find the right marketing strategies for their specific situation, stage, and resources. + +## How to Use This Skill + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +When asked for marketing ideas: +1. Ask about their product, audience, and current stage if not clear +2. Suggest 3-5 most relevant ideas based on their context +3. Provide details on implementation for chosen ideas +4. Consider their resources (time, budget, team size) + +--- + +## Ideas by Category (Quick Reference) + +| Category | Ideas | Examples | +|----------|-------|----------| +| Content & SEO | 1-10 | Programmatic SEO, Glossary marketing, Content repurposing | +| Competitor | 11-13 | Comparison pages, Marketing jiu-jitsu | +| Free Tools | 14-22 | Calculators, Generators, Chrome extensions | +| Paid Ads | 23-34 | LinkedIn, Google, Retargeting, Podcast ads | +| Social & Community | 35-44 | LinkedIn audience, Reddit marketing, Short-form video | +| Email | 45-53 | Founder emails, Onboarding sequences, Win-back | +| Partnerships | 54-64 | Affiliate programs, Integration marketing, Newsletter swaps | +| Events | 65-72 | Webinars, Conference speaking, Virtual summits | +| PR & Media | 73-76 | Press coverage, Documentaries | +| Launches | 77-86 | Product Hunt, Lifetime deals, Giveaways | +| Product-Led | 87-96 | Viral loops, Powered-by marketing, Free migrations | +| Content Formats | 97-109 | Podcasts, Courses, Annual reports, Year wraps | +| Unconventional | 110-122 | Awards, Challenges, Guerrilla marketing | +| Platforms | 123-130 | App marketplaces, Review sites, YouTube | +| International | 131-132 | Expansion, Price localization | +| Developer | 133-136 | DevRel, Certifications | +| Audience-Specific | 137-139 | Referrals, Podcast tours, Customer language | + +**For the complete list with descriptions**: See [references/ideas-by-category.md](references/ideas-by-category.md) + +--- + +## Implementation Tips + +### By Stage + +**Pre-launch:** +- Waitlist referrals (#79) +- Early access pricing (#81) +- Product Hunt prep (#78) + +**Early stage:** +- Content & SEO (#1-10) +- Community (#35) +- Founder-led sales (#47) + +**Growth stage:** +- Paid acquisition (#23-34) +- Partnerships (#54-64) +- Events (#65-72) + +**Scale:** +- Brand campaigns +- International (#131-132) +- Media acquisitions (#73) + +### By Budget + +**Free:** +- Content & SEO +- Community building +- Social media +- Comment marketing + +**Low budget:** +- Targeted ads +- Sponsorships +- Free tools + +**Medium budget:** +- Events +- Partnerships +- PR + +**High budget:** +- Acquisitions +- Conferences +- Brand campaigns + +### By Timeline + +**Quick wins:** +- Ads, email, social posts + +**Medium-term:** +- Content, SEO, community + +**Long-term:** +- Brand, thought leadership, platform effects + +--- + +## Top Ideas by Use Case + +### Need Leads Fast +- Google Ads (#31) - High-intent search +- LinkedIn Ads (#28) - B2B targeting +- Engineering as Marketing (#15) - Free tool lead gen + +### Building Authority +- Conference Speaking (#70) +- Book Marketing (#104) +- Podcasts (#107) + +### Low Budget Growth +- Easy Keyword Ranking (#1) +- Reddit Marketing (#38) +- Comment Marketing (#44) + +### Product-Led Growth +- Viral Loops (#93) +- Powered By Marketing (#87) +- In-App Upsells (#91) + +### Enterprise Sales +- Investor Marketing (#133) +- Expert Networks (#57) +- Conference Sponsorship (#72) + +--- + +## Output Format + +When recommending ideas, provide for each: + +- **Idea name**: One-line description +- **Why it fits**: Connection to their situation +- **How to start**: First 2-3 implementation steps +- **Expected outcome**: What success looks like +- **Resources needed**: Time, budget, skills required + +--- + +## Task-Specific Questions + +1. What's your current stage and main growth goal? +2. What's your marketing budget and team size? +3. What have you already tried that worked or didn't? +4. What competitor tactics do you admire? + +--- + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- **User is at pre-revenue stage but asks about paid ads** → Flag spend timing risk; redirect to zero-budget tactics (content, community, founder-led sales) until PMF is validated. +- **User mentions "we need more leads" without specifying timeline or budget** → Clarify before recommending; a 30-day need requires different tactics than a 6-month need. +- **User is copying a competitor's entire marketing playbook** → Flag that follower strategies rarely win; suggest 1-2 differentiated angles that exploit the competitor's blind spots. +- **User has no email list or owned audience** → Flag platform dependency risk before recommending social or ad-heavy strategies; push for list-building as a foundation. +- **User is spread across 5+ channels with a team of 1-2** → Flag dilution immediately; recommend focusing on 1-2 channels and mastering them before expanding. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| Marketing ideas for my product | 3-5 curated ideas matched to stage, budget, and goal — each with rationale, first steps, and expected outcome | +| A full marketing channel list | Complete 139-idea reference organized by category, with implementation notes for relevant ones | +| A prioritized growth plan | Ranked list of 5-10 tactics with effort/impact matrix and 90-day sequencing | +| Ideas for a specific goal (e.g., leads, authority) | Focused shortlist from the relevant use-case category with implementation details | +| Competitor tactic breakdown | Analysis of what a named competitor is doing + gap/opportunity map for differentiation | + +--- + +## Communication + +All output follows the structured communication standard: + +- **Bottom line first** — recommend the top 3 ideas immediately, then explain +- **What + Why + How** — every idea gets: what it is, why it fits their situation, how to start +- **Effort/Impact framing** — always indicate relative effort and expected timeline to results +- **Confidence tagging** — 🟢 proven for this stage / 🟔 worth testing / šŸ”“ high-variance bet + +Never dump all 139 ideas. Curate ruthlessly for context. If stage or budget is unclear, ask before recommending. + +--- + +## Related Skills + +- **marketing-context**: USE as foundation before brainstorming — loads product, audience, and competitive context. NOT a substitute for this skill's idea library. +- **content-strategy**: USE when the chosen channel is content/SEO and a full topic plan is needed. NOT for channel selection itself. +- **copywriting**: USE when the chosen tactic requires page or ad copy. NOT for deciding which tactics to pursue. +- **social-content**: USE when the chosen idea involves social media execution. NOT for channel strategy decisions. +- **copy-editing**: USE to polish any marketing copy produced from these ideas. NOT for idea generation. +- **content-production**: USE when scaling content-based ideas to high volume. NOT for the initial brainstorm. +- **seo-audit**: USE when content/SEO ideas need technical validation. NOT for ideation. +- **free-tool-strategy**: USE when Engineering as Marketing (#15) is the chosen tactic and a tool needs to be planned and built. NOT for general idea browsing. diff --git a/marketing-skill/marketing-ideas/references/ideas-by-category.md b/marketing-skill/marketing-ideas/references/ideas-by-category.md new file mode 100644 index 0000000..8bd236a --- /dev/null +++ b/marketing-skill/marketing-ideas/references/ideas-by-category.md @@ -0,0 +1,347 @@ +# The 139 Marketing Ideas + +Complete list of proven marketing approaches organized by category. + +## Content & SEO (1-10) + +1. **Easy Keyword Ranking** - Target low-competition keywords where you can rank quickly. Find terms competitors overlook—niche variations, long-tail queries, emerging topics. + +2. **SEO Audit** - Conduct comprehensive technical SEO audits of your own site and share findings publicly. Document fixes and improvements to build authority. + +3. **Glossary Marketing** - Create comprehensive glossaries defining industry terms. Each term becomes an SEO-optimized page targeting "what is X" searches. + +4. **Programmatic SEO** - Build template-driven pages at scale targeting keyword patterns. Location pages, comparison pages, integration pages—any pattern with search volume. + +5. **Content Repurposing** - Transform one piece of content into multiple formats. Blog post becomes Twitter thread, YouTube video, podcast episode, infographic. + +6. **Proprietary Data Content** - Leverage unique data from your product to create original research and reports. Data competitors can't replicate creates linkable assets. + +7. **Internal Linking** - Strategic internal linking distributes authority and improves crawlability. Build topical clusters connecting related content. + +8. **Content Refreshing** - Regularly update existing content with fresh data, examples, and insights. Refreshed content often outperforms new content. + +9. **Knowledge Base SEO** - Optimize help documentation for search. Support articles targeting problem-solution queries capture users actively seeking solutions. + +10. **Parasite SEO** - Publish content on high-authority platforms (Medium, LinkedIn, Substack) that rank faster than your own domain. + +--- + +## Competitor & Comparison (11-13) + +11. **Competitor Comparison Pages** - Create detailed comparison pages positioning your product against competitors. "[Your Product] vs [Competitor]" pages capture high-intent searchers. + +12. **Marketing Jiu-Jitsu** - Turn competitor weaknesses into your strengths. When competitors raise prices, launch affordability campaigns. + +13. **Competitive Ad Research** - Study competitor advertising through tools like SpyFu or Facebook Ad Library. Learn what messaging resonates. + +--- + +## Free Tools & Engineering (14-22) + +14. **Side Projects as Marketing** - Build small, useful tools related to your main product. Side projects attract users who may later convert. + +15. **Engineering as Marketing** - Build free tools that solve real problems. Calculators, analyzers, generators—useful utilities that naturally lead to your paid product. + +16. **Importers as Marketing** - Build import tools for competitor data. "Import from [Competitor]" reduces switching friction. + +17. **Quiz Marketing** - Create interactive quizzes that engage users while qualifying leads. Personality quizzes, assessments, and diagnostic tools generate shares. + +18. **Calculator Marketing** - Build calculators solving real problems—ROI calculators, pricing estimators, savings tools. Calculators attract links and rank well. + +19. **Chrome Extensions** - Create browser extensions providing standalone value. Chrome Web Store becomes another distribution channel. + +20. **Microsites** - Build focused microsites for specific campaigns, products, or audiences. Dedicated domains can rank faster. + +21. **Scanners** - Build free scanning tools that audit or analyze something. Website scanners, security checkers, performance analyzers. + +22. **Public APIs** - Open APIs enable developers to build on your platform, creating an ecosystem. + +--- + +## Paid Advertising (23-34) + +23. **Podcast Advertising** - Sponsor relevant podcasts to reach engaged audiences. Host-read ads perform especially well. + +24. **Pre-targeting Ads** - Show awareness ads before launching direct response campaigns. Warm audiences convert better. + +25. **Facebook Ads** - Meta's detailed targeting reaches specific audiences. Test creative variations and leverage retargeting. + +26. **Instagram Ads** - Visual-first advertising for products with strong imagery. Stories and Reels ads capture attention. + +27. **Twitter Ads** - Reach engaged professionals discussing industry topics. Promoted tweets and follower campaigns. + +28. **LinkedIn Ads** - Target by job title, company size, and industry. Premium CPMs justified by B2B purchase intent. + +29. **Reddit Ads** - Reach passionate communities with authentic messaging. Transparency wins on Reddit. + +30. **Quora Ads** - Target users actively asking questions your product answers. Intent-rich environment. + +31. **Google Ads** - Capture high-intent search queries. Brand terms, competitor terms, and category terms. + +32. **YouTube Ads** - Video ads with detailed targeting. Pre-roll and discovery ads reach users consuming related content. + +33. **Cross-Platform Retargeting** - Follow users across platforms with consistent messaging. + +34. **Click-to-Messenger Ads** - Ads that open direct conversations rather than landing pages. + +--- + +## Social Media & Community (35-44) + +35. **Community Marketing** - Build and nurture communities around your product. Slack groups, Discord servers, Facebook groups. + +36. **Quora Marketing** - Answer relevant questions with genuine expertise. Include product mentions where naturally appropriate. + +37. **Reddit Keyword Research** - Mine Reddit for real language your audience uses. Discover pain points and desires. + +38. **Reddit Marketing** - Participate authentically in relevant subreddits. Provide value first. + +39. **LinkedIn Audience** - Build personal brands on LinkedIn for B2B reach. Thought leadership builds authority. + +40. **Instagram Audience** - Visual storytelling for products with strong aesthetics. Behind-the-scenes and user stories. + +41. **X Audience** - Build presence on X/Twitter through consistent value. Threads and insights grow followings. + +42. **Short Form Video** - TikTok, Reels, and Shorts reach new audiences with snackable content. + +43. **Engagement Pods** - Coordinate with peers to boost each other's content engagement. + +44. **Comment Marketing** - Thoughtful comments on relevant content build visibility. + +--- + +## Email Marketing (45-53) + +45. **Mistake Email Marketing** - Send "oops" emails when something genuinely goes wrong. Authenticity generates engagement. + +46. **Reactivation Emails** - Win back churned or inactive users with targeted campaigns. + +47. **Founder Welcome Email** - Personal welcome emails from founders create connection. + +48. **Dynamic Email Capture** - Smart email capture that adapts to user behavior. Exit intent, scroll depth triggers. + +49. **Monthly Newsletters** - Consistent newsletters keep your brand top-of-mind. + +50. **Inbox Placement** - Technical email optimization for deliverability. Authentication and list hygiene. + +51. **Onboarding Emails** - Guide new users to activation with targeted sequences. + +52. **Win-back Emails** - Re-engage churned users with compelling reasons to return. + +53. **Trial Reactivation** - Expired trials aren't lost causes. Targeted campaigns can recover them. + +--- + +## Partnerships & Programs (54-64) + +54. **Affiliate Discovery Through Backlinks** - Find potential affiliates by analyzing who links to competitors. + +55. **Influencer Whitelisting** - Run ads through influencer accounts for authentic reach. + +56. **Reseller Programs** - Enable agencies to resell your product. White-label options create distribution partners. + +57. **Expert Networks** - Build networks of certified experts who implement your product. + +58. **Newsletter Swaps** - Exchange promotional mentions with complementary newsletters. + +59. **Article Quotes** - Contribute expert quotes to journalists. HARO connects experts with writers. + +60. **Pixel Sharing** - Partner with complementary companies to share remarketing audiences. + +61. **Shared Slack Channels** - Create shared channels with partners and customers. + +62. **Affiliate Program** - Structured commission programs for referrers. + +63. **Integration Marketing** - Joint marketing with integration partners. + +64. **Community Sponsorship** - Sponsor relevant communities, newsletters, or publications. + +--- + +## Events & Speaking (65-72) + +65. **Live Webinars** - Educational webinars demonstrate expertise while generating leads. + +66. **Virtual Summits** - Multi-speaker online events attract audiences through varied perspectives. + +67. **Roadshows** - Take your product on the road to meet customers directly. + +68. **Local Meetups** - Host or attend local meetups in key markets. + +69. **Meetup Sponsorship** - Sponsor relevant meetups to reach engaged local audiences. + +70. **Conference Speaking** - Speak at industry conferences to reach engaged audiences. + +71. **Conferences** - Host your own conference to become the center of your industry. + +72. **Conference Sponsorship** - Sponsor relevant conferences for brand visibility. + +--- + +## PR & Media (73-76) + +73. **Media Acquisitions as Marketing** - Acquire newsletters, podcasts, or publications in your space. + +74. **Press Coverage** - Pitch newsworthy stories to relevant publications. + +75. **Fundraising PR** - Leverage funding announcements for press coverage. + +76. **Documentaries** - Create documentary content exploring your industry or customers. + +--- + +## Launches & Promotions (77-86) + +77. **Black Friday Promotions** - Annual deals create urgency and acquisition spikes. + +78. **Product Hunt Launch** - Structured Product Hunt launches reach early adopters. + +79. **Early-Access Referrals** - Reward referrals with earlier access during launches. + +80. **New Year Promotions** - New Year brings fresh budgets and goal-setting energy. + +81. **Early Access Pricing** - Launch with discounted early access tiers. + +82. **Product Hunt Alternatives** - Launch on BetaList, Launching Next, AlternativeTo. + +83. **Twitter Giveaways** - Engagement-boosting giveaways that require follows or retweets. + +84. **Giveaways** - Strategic giveaways attract attention and capture leads. + +85. **Vacation Giveaways** - Grand prize giveaways generate massive engagement. + +86. **Lifetime Deals** - One-time payment deals generate cash and users. + +--- + +## Product-Led Growth (87-96) + +87. **Powered By Marketing** - "Powered by [Your Product]" badges create free impressions. + +88. **Free Migrations** - Offer free migration services from competitors. + +89. **Contract Buyouts** - Pay to exit competitor contracts. + +90. **One-Click Registration** - Minimize signup friction with OAuth options. + +91. **In-App Upsells** - Strategic upgrade prompts within the product experience. + +92. **Newsletter Referrals** - Built-in referral programs for newsletters. + +93. **Viral Loops** - Product mechanics that naturally encourage sharing. + +94. **Offboarding Flows** - Optimize cancellation flows to retain or learn. + +95. **Concierge Setup** - White-glove onboarding for high-value accounts. + +96. **Onboarding Optimization** - Continuous improvement of new user experience. + +--- + +## Content Formats (97-109) + +97. **Playlists as Marketing** - Create Spotify playlists for your audience. + +98. **Template Marketing** - Offer free templates users can immediately use. + +99. **Graphic Novel Marketing** - Transform complex stories into visual narratives. + +100. **Promo Videos** - High-quality promotional videos showcase your product. + +101. **Industry Interviews** - Interview customers, experts, and thought leaders. + +102. **Social Screenshots** - Design shareable screenshot templates for social proof. + +103. **Online Courses** - Educational courses establish authority while generating leads. + +104. **Book Marketing** - Author a book establishing expertise in your domain. + +105. **Annual Reports** - Publish annual reports showcasing industry data and trends. + +106. **End of Year Wraps** - Personalized year-end summaries users want to share. + +107. **Podcasts** - Launch a podcast reaching audiences during commutes. + +108. **Changelogs** - Public changelogs showcase product momentum. + +109. **Public Demos** - Live product demonstrations showing real usage. + +--- + +## Unconventional & Creative (110-122) + +110. **Awards as Marketing** - Create industry awards positioning your brand as tastemaker. + +111. **Challenges as Marketing** - Launch viral challenges that spread organically. + +112. **Reality TV Marketing** - Create reality-show style content following real customers. + +113. **Controversy as Marketing** - Strategic positioning against industry norms. + +114. **Moneyball Marketing** - Data-driven marketing finding undervalued channels. + +115. **Curation as Marketing** - Curate valuable resources for your audience. + +116. **Grants as Marketing** - Offer grants to customers or community members. + +117. **Product Competitions** - Sponsor competitions using your product. + +118. **Cameo Marketing** - Use Cameo celebrities for personalized messages. + +119. **OOH Advertising** - Out-of-home advertising—billboards, transit ads. + +120. **Marketing Stunts** - Bold, attention-grabbing marketing moments. + +121. **Guerrilla Marketing** - Unconventional, low-cost marketing in unexpected places. + +122. **Humor Marketing** - Use humor to stand out and create memorability. + +--- + +## Platforms & Marketplaces (123-130) + +123. **Open Source as Marketing** - Open-source components or tools build developer goodwill. + +124. **App Store Optimization** - Optimize app store listings for discoverability. + +125. **App Marketplaces** - List in Salesforce AppExchange, Shopify App Store, etc. + +126. **YouTube Reviews** - Get YouTubers to review your product. + +127. **YouTube Channel** - Build a YouTube presence with tutorials and thought leadership. + +128. **Source Platforms** - Submit to G2, Capterra, GetApp, and similar directories. + +129. **Review Sites** - Actively manage presence on review platforms. + +130. **Live Audio** - Host Twitter Spaces, Clubhouse, or LinkedIn Audio discussions. + +--- + +## International & Localization (131-132) + +131. **International Expansion** - Expand to new geographic markets with localization. + +132. **Price Localization** - Adjust pricing for local purchasing power. + +--- + +## Developer & Technical (133-136) + +133. **Investor Marketing** - Market to investors for portfolio introductions. + +134. **Certifications** - Create certification programs validating expertise. + +135. **Support as Marketing** - Exceptional support creates stories customers share. + +136. **Developer Relations** - Build relationships with developer communities. + +--- + +## Audience-Specific (137-139) + +137. **Two-Sided Referrals** - Reward both referrer and referred. + +138. **Podcast Tours** - Guest on multiple podcasts reaching your target audience. + +139. **Customer Language** - Use the exact words your customers use in marketing. diff --git a/marketing-skill/marketing-ops/SKILL.md b/marketing-skill/marketing-ops/SKILL.md new file mode 100644 index 0000000..8da639d --- /dev/null +++ b/marketing-skill/marketing-ops/SKILL.md @@ -0,0 +1,190 @@ +--- +name: marketing-ops +description: "Central router for the marketing skill ecosystem. Use when unsure which marketing skill to use, when orchestrating a multi-skill campaign, or when coordinating across content, SEO, CRO, channels, and analytics. Also use when the user mentions 'marketing help,' 'campaign plan,' 'what should I do next,' 'marketing priorities,' or 'coordinate marketing.'" +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Marketing Ops + +You are a senior marketing operations leader. Your goal is to route marketing questions to the right specialist skill, orchestrate multi-skill campaigns, and ensure quality across all marketing output. + +## Before Starting + +**Check for marketing context first:** +If `marketing-context.md` exists, read it. If it doesn't, recommend running the **marketing-context** skill first — everything works better with context. + +## How This Skill Works + +### Mode 1: Route a Question +User has a marketing question → you identify the right skill and route them. + +### Mode 2: Campaign Orchestration +User wants to plan or execute a campaign → you coordinate across multiple skills in sequence. + +### Mode 3: Marketing Audit +User wants to assess their marketing → you run a cross-functional audit touching SEO, content, CRO, and channels. + +--- + +## Routing Matrix + +### Content Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "Write a blog post," "content ideas," "what should I write" | **content-strategy** | Not copywriting (that's for page copy) | +| "Write copy for my homepage," "landing page copy," "headline" | **copywriting** | Not content-strategy (that's for planning) | +| "Edit this copy," "proofread," "polish this" | **copy-editing** | Not copywriting (that's for writing new) | +| "Social media post," "LinkedIn post," "tweet" | **social-content** | Not social-media-manager (that's for strategy) | +| "Marketing ideas," "brainstorm," "what else can I try" | **marketing-ideas** | | +| "Write an article," "research and write," "SEO article" | **content-production** | Not content-creator (production has the full pipeline) | +| "Sounds too robotic," "make it human," "AI watermarks" | **content-humanizer** | | + +### SEO Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "SEO audit," "technical SEO," "on-page SEO" | **seo-audit** | Not ai-seo (that's for AI search engines) | +| "AI search," "ChatGPT visibility," "Perplexity," "AEO" | **ai-seo** | Not seo-audit (that's traditional SEO) | +| "Schema markup," "structured data," "JSON-LD," "rich snippets" | **schema-markup** | | +| "Site structure," "URL structure," "navigation," "sitemap" | **site-architecture** | | +| "Programmatic SEO," "pages at scale," "template pages" | **programmatic-seo** | | + +### CRO Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "Optimize this page," "conversion rate," "CRO audit" | **page-cro** | Not form-cro (that's for forms specifically) | +| "Form optimization," "lead form," "contact form" | **form-cro** | Not signup-flow-cro (that's for registration) | +| "Signup flow," "registration," "account creation" | **signup-flow-cro** | Not onboarding-cro (that's post-signup) | +| "Onboarding," "activation," "first-run experience" | **onboarding-cro** | Not signup-flow-cro (that's pre-signup) | +| "Popup," "modal," "overlay," "exit intent" | **popup-cro** | | +| "Paywall," "upgrade screen," "upsell modal" | **paywall-upgrade-cro** | | + +### Channels Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "Email sequence," "drip campaign," "welcome sequence" | **email-sequence** | Not cold-email (that's for outbound) | +| "Cold email," "outreach," "prospecting email" | **cold-email** | Not email-sequence (that's for lifecycle) | +| "Paid ads," "Google Ads," "Meta ads," "ad campaign" | **paid-ads** | Not ad-creative (that's for copy generation) | +| "Ad copy," "ad headlines," "ad variations," "RSA" | **ad-creative** | Not paid-ads (that's for strategy) | +| "Social media strategy," "social calendar," "community" | **social-media-manager** | Not social-content (that's for individual posts) | + +### Growth Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "A/B test," "experiment," "split test" | **ab-test-setup** | | +| "Referral program," "affiliate," "word of mouth" | **referral-program** | | +| "Free tool," "calculator," "marketing tool" | **free-tool-strategy** | | +| "Churn," "cancel flow," "dunning," "retention" | **churn-prevention** | | + +### Intelligence Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "Campaign analytics," "channel performance," "attribution" | **campaign-analytics** | Not analytics-tracking (that's for setup) | +| "Set up tracking," "GA4," "GTM," "event tracking" | **analytics-tracking** | Not campaign-analytics (that's for analysis) | +| "Competitor page," "vs page," "alternative page" | **competitor-alternatives** | | +| "Psychology," "persuasion," "behavioral science" | **marketing-psychology** | | + +### Sales & GTM Pod +| Trigger | Route to | NOT this | +|---------|----------|----------| +| "Product launch," "feature announcement," "Product Hunt" | **launch-strategy** | | +| "Pricing," "how much to charge," "pricing tiers" | **pricing-strategy** | | + +### Cross-Domain (route outside marketing-skill/) +| Trigger | Route to | Domain | +|---------|----------|--------| +| "Revenue operations," "pipeline," "lead scoring" | **revenue-operations** | business-growth/ | +| "Sales deck," "pitch deck," "objection handling" | **sales-engineer** | business-growth/ | +| "Customer health," "expansion," "NPS" | **customer-success-manager** | business-growth/ | +| "Landing page code," "React component" | **landing-page-generator** | product-team/ | +| "Competitive teardown," "feature matrix" | **competitive-teardown** | product-team/ | +| "Email template code," "transactional email" | **email-template-builder** | engineering-team/ | +| "Brand strategy," "growth model," "marketing budget" | **cmo-advisor** | c-level-advisor/ | + +--- + +## Campaign Orchestration + +For multi-skill campaigns, follow this sequence: + +### New Product/Feature Launch +``` +1. marketing-context (ensure foundation exists) +2. launch-strategy (plan the launch) +3. content-strategy (plan content around launch) +4. copywriting (write landing page) +5. email-sequence (write launch emails) +6. social-content (write social posts) +7. paid-ads + ad-creative (paid promotion) +8. analytics-tracking (set up tracking) +9. campaign-analytics (measure results) +``` + +### Content Campaign +``` +1. content-strategy (plan topics + calendar) +2. seo-audit (identify SEO opportunities) +3. content-production (research → write → optimize) +4. content-humanizer (polish for natural voice) +5. schema-markup (add structured data) +6. social-content (promote on social) +7. email-sequence (distribute via email) +``` + +### Conversion Optimization Sprint +``` +1. page-cro (audit current pages) +2. copywriting (rewrite underperforming copy) +3. form-cro or signup-flow-cro (optimize forms) +4. ab-test-setup (design tests) +5. analytics-tracking (ensure tracking is right) +6. campaign-analytics (measure impact) +``` + +--- + +## Quality Gate + +Before any marketing output reaches the user: +- [ ] Marketing context was checked (not generic advice) +- [ ] Output follows communication standard (bottom line first) +- [ ] Actions have owners and deadlines +- [ ] Related skills referenced for next steps +- [ ] Cross-domain skills flagged when relevant + +--- + +## Proactive Triggers + +- **No marketing context exists** → "Run marketing-context first — every skill works 3x better with context." +- **Multiple skills needed** → Route to campaign orchestration mode, not just one skill. +- **Cross-domain question disguised as marketing** → Route to correct domain (e.g., "help with pricing" → pricing-strategy, not CRO). +- **Analytics not set up** → "Before optimizing, make sure tracking is in place — route to analytics-tracking first." +- **Content without SEO** → "This content should be SEO-optimized. Run seo-audit or content-production, not just copywriting." + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "What marketing skill should I use?" | Routing recommendation with skill name + why + what to expect | +| "Plan a campaign" | Campaign orchestration plan with skill sequence + timeline | +| "Marketing audit" | Cross-functional audit touching all pods with prioritized recommendations | +| "What's missing in my marketing?" | Gap analysis against full skill ecosystem | + +## Communication + +All output passes quality verification: +- Self-verify: routing recommendation checked against full matrix +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **chief-of-staff** (C-Suite): The C-level router. Marketing-ops is the domain-specific equivalent. +- **marketing-context**: Foundation — run this first if it doesn't exist. +- **cmo-advisor** (C-Suite): Strategic marketing decisions. Marketing-ops handles execution routing. +- **campaign-analytics**: For measuring outcomes of orchestrated campaigns. diff --git a/marketing-skill/marketing-ops/scripts/campaign_tracker.py b/marketing-skill/marketing-ops/scripts/campaign_tracker.py new file mode 100644 index 0000000..66dc0dd --- /dev/null +++ b/marketing-skill/marketing-ops/scripts/campaign_tracker.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +"""Track campaign status across marketing skills — tasks, owners, deadlines.""" + +import json +import sys +from datetime import datetime, timedelta +from pathlib import Path + +SAMPLE_CAMPAIGN = { + "name": "Q1 Product Launch", + "created": "2026-03-01", + "status": "in_progress", + "skills_used": [], + "tasks": [ + {"skill": "marketing-context", "task": "Update context for new feature", "owner": "Marketing", "deadline": "2026-03-03", "status": "complete"}, + {"skill": "launch-strategy", "task": "Plan launch phases", "owner": "PMM", "deadline": "2026-03-05", "status": "complete"}, + {"skill": "content-strategy", "task": "Plan content calendar", "owner": "Content", "deadline": "2026-03-07", "status": "in_progress"}, + {"skill": "copywriting", "task": "Write landing page copy", "owner": "Copywriter", "deadline": "2026-03-10", "status": "not_started"}, + {"skill": "email-sequence", "task": "Write launch email sequence", "owner": "Email", "deadline": "2026-03-10", "status": "not_started"}, + {"skill": "social-content", "task": "Create social media posts", "owner": "Social", "deadline": "2026-03-12", "status": "not_started"}, + {"skill": "paid-ads", "task": "Set up ad campaigns", "owner": "Paid", "deadline": "2026-03-12", "status": "not_started"}, + {"skill": "ad-creative", "task": "Generate ad variations", "owner": "Creative", "deadline": "2026-03-11", "status": "not_started"}, + {"skill": "analytics-tracking", "task": "Set up conversion tracking", "owner": "Analytics", "deadline": "2026-03-08", "status": "in_progress"}, + {"skill": "seo-audit", "task": "Optimize landing page SEO", "owner": "SEO", "deadline": "2026-03-09", "status": "not_started"}, + ] +} + + +def analyze_campaign(campaign: dict) -> dict: + """Analyze campaign status and generate report.""" + tasks = campaign["tasks"] + today = datetime.now().strftime("%Y-%m-%d") + + complete = [t for t in tasks if t["status"] == "complete"] + in_progress = [t for t in tasks if t["status"] == "in_progress"] + not_started = [t for t in tasks if t["status"] == "not_started"] + overdue = [t for t in tasks if t["deadline"] < today and t["status"] != "complete"] + due_soon = [t for t in tasks if today <= t["deadline"] <= (datetime.now() + timedelta(days=3)).strftime("%Y-%m-%d") and t["status"] != "complete"] + + total = len(tasks) + progress = round((len(complete) / total) * 100) if total > 0 else 0 + + # Skills coverage + skills_used = list(set(t["skill"] for t in tasks)) + pods_covered = set() + pod_map = { + "content": ["content-strategy", "copywriting", "copy-editing", "social-content", "marketing-ideas", "content-production", "content-humanizer", "content-creator"], + "seo": ["seo-audit", "programmatic-seo", "ai-seo", "schema-markup", "site-architecture"], + "cro": ["page-cro", "form-cro", "signup-flow-cro", "onboarding-cro", "popup-cro", "paywall-upgrade-cro"], + "channels": ["email-sequence", "cold-email", "paid-ads", "ad-creative", "social-media-manager"], + "growth": ["ab-test-setup", "referral-program", "free-tool-strategy", "churn-prevention"], + "intelligence": ["campaign-analytics", "analytics-tracking", "competitor-alternatives", "marketing-psychology"], + "gtm": ["launch-strategy", "pricing-strategy"] + } + for pod, skills in pod_map.items(): + if any(s in skills_used for s in skills): + pods_covered.add(pod) + + # Blockers + blockers = [] + for t in tasks: + if t["status"] == "not_started": + # Check if any dependency is incomplete + deps = [d for d in tasks if d["deadline"] < t["deadline"] and d["status"] != "complete"] + if deps: + blocker_names = [d["task"] for d in deps if d["status"] != "complete"] + if blocker_names: + blockers.append({"task": t["task"], "blocked_by": blocker_names[0]}) + + return { + "campaign": campaign["name"], + "progress": progress, + "total_tasks": total, + "complete": len(complete), + "in_progress": len(in_progress), + "not_started": len(not_started), + "overdue": [{"task": t["task"], "deadline": t["deadline"], "owner": t["owner"]} for t in overdue], + "due_soon": [{"task": t["task"], "deadline": t["deadline"], "owner": t["owner"]} for t in due_soon], + "pods_covered": sorted(pods_covered), + "pods_missing": sorted(set(pod_map.keys()) - pods_covered), + "skills_used": sorted(skills_used), + "blockers": blockers + } + + +def print_report(analysis: dict): + """Print human-readable campaign status.""" + print(f"\n{'='*55}") + print(f"CAMPAIGN: {analysis['campaign']}") + print(f"{'='*55}") + + bar_len = 30 + filled = round(bar_len * analysis["progress"] / 100) + bar = "ā–ˆ" * filled + "ā–‘" * (bar_len - filled) + print(f"\nProgress: [{bar}] {analysis['progress']}%") + print(f"Tasks: {analysis['complete']} done / {analysis['in_progress']} active / {analysis['not_started']} pending") + + if analysis["overdue"]: + print(f"\nšŸ”“ OVERDUE ({len(analysis['overdue'])}):") + for t in analysis["overdue"]: + print(f" → {t['task']} (due {t['deadline']}, owner: {t['owner']})") + + if analysis["due_soon"]: + print(f"\n🟔 DUE SOON ({len(analysis['due_soon'])}):") + for t in analysis["due_soon"]: + print(f" → {t['task']} (due {t['deadline']}, owner: {t['owner']})") + + if analysis["blockers"]: + print(f"\nāš ļø BLOCKERS:") + for b in analysis["blockers"]: + print(f" → {b['task']} blocked by: {b['blocked_by']}") + + print(f"\nšŸ“¦ Pods covered: {', '.join(analysis['pods_covered'])}") + if analysis["pods_missing"]: + print(f" Missing: {', '.join(analysis['pods_missing'])}") + + print(f"\nšŸ”§ Skills used: {', '.join(analysis['skills_used'])}") + print(f"{'='*55}") + + +def main(): + if len(sys.argv) > 1: + filepath = Path(sys.argv[1]) + if filepath.exists(): + campaign = json.loads(filepath.read_text()) + else: + print(f"Error: {filepath} not found", file=sys.stderr) + sys.exit(1) + else: + campaign = SAMPLE_CAMPAIGN + print("[Using sample campaign data — pass a JSON file for real tracking]") + + analysis = analyze_campaign(campaign) + print_report(analysis) + + if "--json" in sys.argv: + print(f"\n{json.dumps(analysis, indent=2)}") + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/marketing-psychology/SKILL.md b/marketing-skill/marketing-psychology/SKILL.md new file mode 100644 index 0000000..9bc0190 --- /dev/null +++ b/marketing-skill/marketing-psychology/SKILL.md @@ -0,0 +1,123 @@ +--- +name: marketing-psychology +description: "When the user wants to apply psychological principles, mental models, or behavioral science to marketing. Also use when the user mentions 'psychology,' 'mental models,' 'cognitive bias,' 'persuasion,' 'behavioral science,' 'why people buy,' 'decision-making,' or 'consumer behavior.' This skill provides 70+ mental models organized for marketing application." +license: MIT +metadata: + version: 1.1.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Marketing Psychology + +You are an expert in applied behavioral science for marketing. Your job is to identify which psychological principles apply to a specific marketing challenge and show how to use them — not just name-drop biases. + +## Before Starting + +**Check for marketing context first:** +If `marketing-context.md` exists, read it for audience personas and product positioning. Psychology works better when you know the audience. + +## How This Skill Works + +### Mode 1: Diagnose — Why Isn't This Converting? +Analyze a page, flow, or campaign through a behavioral science lens. Identify which cognitive biases or principles are being violated or underutilized. + +### Mode 2: Apply — Use Psychology to Improve +Given a specific marketing asset, recommend 3-5 psychological principles to apply with concrete implementation examples. + +### Mode 3: Reference — Look Up a Principle +Explain a specific mental model, bias, or principle with marketing applications and examples. + +--- + +## The 70+ Mental Models + +The full catalog lives in [references/mental-models-catalog.md](references/mental-models-catalog.md). Load it when you need to look up specific models or browse the full list. + +### Categories at a Glance + +| Category | Count | Key Models | Marketing Application | +|----------|-------|------------|----------------------| +| **Foundational Thinking** | 14 | First Principles, Jobs to Be Done, Inversion, Pareto, Second-Order Thinking | Strategic decisions, positioning | +| **Buyer Psychology** | 17 | Endowment Effect, Zero-Price Effect, Paradox of Choice, Social Proof | Conversion optimization, pricing | +| **Persuasion & Influence** | 13 | Reciprocity, Scarcity, Loss Aversion, Anchoring, Decoy Effect | Copy, CTAs, offers | +| **Pricing Psychology** | 5 | Charm Pricing, Rule of 100, Good-Better-Best | Pricing pages, discount framing | +| **Design & Delivery** | 10 | AIDA, Hick's Law, Nudge Theory, Fogg Model | UX, onboarding, form design | +| **Growth & Scaling** | 8 | Network Effects, Flywheel, Switching Costs, Compounding | Growth strategy, retention | + +### Most-Used Models (start here) + +**For conversion optimization:** +- **Loss Aversion** — People feel losses 2x more than gains. Frame benefits as what they'll miss. +- **Anchoring** — First number seen sets expectations. Show higher price first, then your price. +- **Social Proof** — People follow others. Show customer count, testimonials, logos. +- **Scarcity** — Limited availability increases desire. But only if real — fake urgency backfires. +- **Paradox of Choice** — Too many options = no decision. Limit to 3 tiers. + +**For pricing:** +- **Charm Pricing** — $49 feels meaningfully cheaper than $50 (left-digit effect). +- **Decoy Effect** — Add a dominated option to make your target tier look like the obvious choice. +- **Rule of 100** — Under $100: show % discount. Over $100: show $ discount. + +**For copy and messaging:** +- **Reciprocity** — Give value first (free tool, guide, audit). People feel compelled to reciprocate. +- **Endowment Effect** — Let people "own" something before paying (free trial, saved progress). +- **Framing** — Same fact, different frame. "95% uptime" vs "down 18 days/year." Choose wisely. + +--- + +## Quick Reference + +| Situation | Models to Apply | +|-----------|----------------| +| Landing page not converting | Loss Aversion, Social Proof, Anchoring, Hick's Law | +| Pricing page optimization | Charm Pricing, Decoy Effect, Good-Better-Best, Anchoring | +| Email sequence engagement | Reciprocity, Zeigarnik Effect, Goal-Gradient, Commitment | +| Reducing churn | Endowment Effect, Sunk Cost, Switching Costs, Status-Quo Bias | +| Onboarding activation | IKEA Effect, Goal-Gradient, Fogg Model, Default Effect | +| Ad creative improvement | Mere Exposure, Pratfall Effect, Contrast Effect, Framing | +| Referral program design | Reciprocity, Social Proof, Network Effects, Unity Principle | + +## Task-Specific Questions + +When applying psychology to a specific challenge, ask: + +1. **What's the desired behavior?** (Click, buy, share, return?) +2. **What's the current friction?** (Too many choices, unclear value, no urgency?) +3. **What's the emotional state?** (Excited, skeptical, confused, impatient?) +4. **What's the context?** (First visit, returning user, comparing options?) +5. **What's the risk tolerance?** (High-stakes B2B? Low-stakes consumer impulse?) + +## Proactive Triggers + +- **Landing page has no social proof** → Missing one of the most powerful conversion levers. Add testimonials, customer count, or logos. +- **Pricing page shows all features equally** → No anchoring or decoy. Restructure tiers with a recommended option. +- **CTA uses weak language** → "Submit" or "Get started" vs "Start my free trial" (endowment framing). +- **Too many form fields** → Hick's Law: more choices = more friction. Reduce or use progressive disclosure. +- **No urgency element** → If legitimate scarcity exists, surface it. Countdown timers, limited spots, seasonal offers. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Why isn't this converting?" | Behavioral diagnosis: which principles are violated + specific fixes | +| "Apply psychology to this page" | 3-5 applicable principles with concrete implementation | +| "Explain [principle]" | Definition + marketing applications + before/after examples | +| "Pricing psychology audit" | Pricing page analysis with principle-by-principle recommendations | +| "Psychology playbook for [goal]" | Curated set of 5-7 models specific to the goal | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **page-cro**: For full page optimization. Psychology provides the behavioral layer. +- **copywriting**: For writing copy. Psychology informs the persuasion techniques. +- **pricing-strategy**: For pricing decisions. Psychology provides the buyer behavior lens. +- **marketing-context**: Foundation — understanding audience makes psychology more precise. +- **ab-test-setup**: For testing which psychological approach works. Data beats theory. diff --git a/marketing-skill/marketing-psychology/references/mental-models-catalog.md b/marketing-skill/marketing-psychology/references/mental-models-catalog.md new file mode 100644 index 0000000..856ef6a --- /dev/null +++ b/marketing-skill/marketing-psychology/references/mental-models-catalog.md @@ -0,0 +1,397 @@ +# Mental Models Catalog for Marketing +## Foundational Thinking Models + +These models sharpen your strategy and help you solve the right problems. + +### First Principles +Break problems down to basic truths and build solutions from there. Instead of copying competitors, ask "why" repeatedly to find root causes. Use the 5 Whys technique to tunnel down to what really matters. + +**Marketing application**: Don't assume you need content marketing because competitors do. Ask why you need it, what problem it solves, and whether there's a better solution. + +### Jobs to Be Done +People don't buy products—they "hire" them to get a job done. Focus on the outcome customers want, not features. + +**Marketing application**: A drill buyer doesn't want a drill—they want a hole. Frame your product around the job it accomplishes, not its specifications. + +### Circle of Competence +Know what you're good at and stay within it. Venture outside only with proper learning or expert help. + +**Marketing application**: Don't chase every channel. Double down where you have genuine expertise and competitive advantage. + +### Inversion +Instead of asking "How do I succeed?", ask "What would guarantee failure?" Then avoid those things. + +**Marketing application**: List everything that would make your campaign fail—confusing messaging, wrong audience, slow landing page—then systematically prevent each. + +### Occam's Razor +The simplest explanation is usually correct. Avoid overcomplicating strategies or attributing results to complex causes when simple ones suffice. + +**Marketing application**: If conversions dropped, check the obvious first (broken form, page speed) before assuming complex attribution issues. + +### Pareto Principle (80/20 Rule) +Roughly 80% of results come from 20% of efforts. Identify and focus on the vital few. + +**Marketing application**: Find the 20% of channels, customers, or content driving 80% of results. Cut or reduce the rest. + +### Local vs. Global Optima +A local optimum is the best solution nearby, but a global optimum is the best overall. Don't get stuck optimizing the wrong thing. + +**Marketing application**: Optimizing email subject lines (local) won't help if email isn't the right channel (global). Zoom out before zooming in. + +### Theory of Constraints +Every system has one bottleneck limiting throughput. Find and fix that constraint before optimizing elsewhere. + +**Marketing application**: If your funnel converts well but traffic is low, more conversion optimization won't help. Fix the traffic bottleneck first. + +### Opportunity Cost +Every choice has a cost—what you give up by not choosing alternatives. Consider what you're saying no to. + +**Marketing application**: Time spent on a low-ROI channel is time not spent on high-ROI activities. Always compare against alternatives. + +### Law of Diminishing Returns +After a point, additional investment yields progressively smaller gains. + +**Marketing application**: The 10th blog post won't have the same impact as the first. Know when to diversify rather than double down. + +### Second-Order Thinking +Consider not just immediate effects, but the effects of those effects. + +**Marketing application**: A flash sale boosts revenue (first order) but may train customers to wait for discounts (second order). + +### Map ≠ Territory +Models and data represent reality but aren't reality itself. Don't confuse your analytics dashboard with actual customer experience. + +**Marketing application**: Your customer persona is a useful model, but real customers are more complex. Stay in touch with actual users. + +### Probabilistic Thinking +Think in probabilities, not certainties. Estimate likelihoods and plan for multiple outcomes. + +**Marketing application**: Don't bet everything on one campaign. Spread risk and plan for scenarios where your primary strategy underperforms. + +### Barbell Strategy +Combine extreme safety with small high-risk/high-reward bets. Avoid the mediocre middle. + +**Marketing application**: Put 80% of budget into proven channels, 20% into experimental bets. Avoid moderate-risk, moderate-reward middle. + +--- + +## Understanding Buyers & Human Psychology + +These models explain how customers think, decide, and behave. + +### Fundamental Attribution Error +People attribute others' behavior to character, not circumstances. "They didn't buy because they're not serious" vs. "The checkout was confusing." + +**Marketing application**: When customers don't convert, examine your process before blaming them. The problem is usually situational, not personal. + +### Mere Exposure Effect +People prefer things they've seen before. Familiarity breeds liking. + +**Marketing application**: Consistent brand presence builds preference over time. Repetition across channels creates comfort and trust. + +### Availability Heuristic +People judge likelihood by how easily examples come to mind. Recent or vivid events seem more common. + +**Marketing application**: Case studies and testimonials make success feel more achievable. Make positive outcomes easy to imagine. + +### Confirmation Bias +People seek information confirming existing beliefs and ignore contradictory evidence. + +**Marketing application**: Understand what your audience already believes and align messaging accordingly. Fighting beliefs head-on rarely works. + +### The Lindy Effect +The longer something has survived, the longer it's likely to continue. Old ideas often outlast new ones. + +**Marketing application**: Proven marketing principles (clear value props, social proof) outlast trendy tactics. Don't abandon fundamentals for fads. + +### Mimetic Desire +People want things because others want them. Desire is socially contagious. + +**Marketing application**: Show that desirable people want your product. Waitlists, exclusivity, and social proof trigger mimetic desire. + +### Sunk Cost Fallacy +People continue investing in something because of past investment, even when it's no longer rational. + +**Marketing application**: Know when to kill underperforming campaigns. Past spend shouldn't justify future spend if results aren't there. + +### Endowment Effect +People value things more once they own them. + +**Marketing application**: Free trials, samples, and freemium models let customers "own" the product, making them reluctant to give it up. + +### IKEA Effect +People value things more when they've put effort into creating them. + +**Marketing application**: Let customers customize, configure, or build something. Their investment increases perceived value and commitment. + +### Zero-Price Effect +Free isn't just a low price—it's psychologically different. "Free" triggers irrational preference. + +**Marketing application**: Free tiers, free trials, and free shipping have disproportionate appeal. The jump from $1 to $0 is bigger than $2 to $1. + +### Hyperbolic Discounting / Present Bias +People strongly prefer immediate rewards over future ones, even when waiting is more rational. + +**Marketing application**: Emphasize immediate benefits ("Start saving time today") over future ones ("You'll see ROI in 6 months"). + +### Status-Quo Bias +People prefer the current state of affairs. Change requires effort and feels risky. + +**Marketing application**: Reduce friction to switch. Make the transition feel safe and easy. "Import your data in one click." + +### Default Effect +People tend to accept pre-selected options. Defaults are powerful. + +**Marketing application**: Pre-select the plan you want customers to choose. Opt-out beats opt-in for subscriptions (ethically applied). + +### Paradox of Choice +Too many options overwhelm and paralyze. Fewer choices often lead to more decisions. + +**Marketing application**: Limit options. Three pricing tiers beat seven. Recommend a single "best for most" option. + +### Goal-Gradient Effect +People accelerate effort as they approach a goal. Progress visualization motivates action. + +**Marketing application**: Show progress bars, completion percentages, and "almost there" messaging to drive completion. + +### Peak-End Rule +People judge experiences by the peak (best or worst moment) and the end, not the average. + +**Marketing application**: Design memorable peaks (surprise upgrades, delightful moments) and strong endings (thank you pages, follow-up emails). + +### Zeigarnik Effect +Unfinished tasks occupy the mind more than completed ones. Open loops create tension. + +**Marketing application**: "You're 80% done" creates pull to finish. Incomplete profiles, abandoned carts, and cliffhangers leverage this. + +### Pratfall Effect +Competent people become more likable when they show a small flaw. Perfection is less relatable. + +**Marketing application**: Admitting a weakness ("We're not the cheapest, but...") can increase trust and differentiation. + +### Curse of Knowledge +Once you know something, you can't imagine not knowing it. Experts struggle to explain simply. + +**Marketing application**: Your product seems obvious to you but confusing to newcomers. Test copy with people unfamiliar with your space. + +### Mental Accounting +People treat money differently based on its source or intended use, even though money is fungible. + +**Marketing application**: Frame costs in favorable mental accounts. "$3/day" feels different than "$90/month" even though it's the same. + +### Regret Aversion +People avoid actions that might cause regret, even if the expected outcome is positive. + +**Marketing application**: Address regret directly. Money-back guarantees, free trials, and "no commitment" messaging reduce regret fear. + +### Bandwagon Effect / Social Proof +People follow what others are doing. Popularity signals quality and safety. + +**Marketing application**: Show customer counts, testimonials, logos, reviews, and "trending" indicators. Numbers create confidence. + +--- + +## Influencing Behavior & Persuasion + +These models help you ethically influence customer decisions. + +### Reciprocity Principle +People feel obligated to return favors. Give first, and people want to give back. + +**Marketing application**: Free content, free tools, and generous free tiers create reciprocal obligation. Give value before asking for anything. + +### Commitment & Consistency +Once people commit to something, they want to stay consistent with that commitment. + +**Marketing application**: Get small commitments first (email signup, free trial). People who've taken one step are more likely to take the next. + +### Authority Bias +People defer to experts and authority figures. Credentials and expertise create trust. + +**Marketing application**: Feature expert endorsements, certifications, "featured in" logos, and thought leadership content. + +### Liking / Similarity Bias +People say yes to those they like and those similar to themselves. + +**Marketing application**: Use relatable spokespeople, founder stories, and community language. "Built by marketers for marketers" signals similarity. + +### Unity Principle +Shared identity drives influence. "One of us" is powerful. + +**Marketing application**: Position your brand as part of the customer's tribe. Use insider language and shared values. + +### Scarcity / Urgency Heuristic +Limited availability increases perceived value. Scarcity signals desirability. + +**Marketing application**: Limited-time offers, low-stock warnings, and exclusive access create urgency. Only use when genuine. + +### Foot-in-the-Door Technique +Start with a small request, then escalate. Compliance with small requests leads to compliance with larger ones. + +**Marketing application**: Free trial → paid plan → annual plan → enterprise. Each step builds on the last. + +### Door-in-the-Face Technique +Start with an unreasonably large request, then retreat to what you actually want. The contrast makes the second request seem reasonable. + +**Marketing application**: Show enterprise pricing first, then reveal the affordable starter plan. The contrast makes it feel like a deal. + +### Loss Aversion / Prospect Theory +Losses feel roughly twice as painful as equivalent gains feel good. People will work harder to avoid losing than to gain. + +**Marketing application**: Frame in terms of what they'll lose by not acting. "Don't miss out" beats "You could gain." + +### Anchoring Effect +The first number people see heavily influences subsequent judgments. + +**Marketing application**: Show the higher price first (original price, competitor price, enterprise tier) to anchor expectations. + +### Decoy Effect +Adding a third, inferior option makes one of the original two look better. + +**Marketing application**: A "decoy" pricing tier that's clearly worse value makes your preferred tier look like the obvious choice. + +### Framing Effect +How something is presented changes how it's perceived. Same facts, different frames. + +**Marketing application**: "90% success rate" vs. "10% failure rate" are identical but feel different. Frame positively. + +### Contrast Effect +Things seem different depending on what they're compared to. + +**Marketing application**: Show the "before" state clearly. The contrast with your "after" makes improvements vivid. + +--- + +## Pricing Psychology + +These models specifically address how people perceive and respond to prices. + +### Charm Pricing / Left-Digit Effect +Prices ending in 9 seem significantly lower than the next round number. $99 feels much cheaper than $100. + +**Marketing application**: Use .99 or .95 endings for value-focused products. The left digit dominates perception. + +### Rounded-Price (Fluency) Effect +Round numbers feel premium and are easier to process. $100 signals quality; $99 signals value. + +**Marketing application**: Use round prices for premium products ($500/month), charm prices for value products ($497/month). + +### Rule of 100 +For prices under $100, percentage discounts seem larger ("20% off"). For prices over $100, absolute discounts seem larger ("$50 off"). + +**Marketing application**: $80 product: "20% off" beats "$16 off." $500 product: "$100 off" beats "20% off." + +### Price Relativity / Good-Better-Best +People judge prices relative to options presented. A middle tier seems reasonable between cheap and expensive. + +**Marketing application**: Three tiers where the middle is your target. The expensive tier makes it look reasonable; the cheap tier provides an anchor. + +### Mental Accounting (Pricing) +Framing the same price differently changes perception. + +**Marketing application**: "$1/day" feels cheaper than "$30/month." "Less than your morning coffee" reframes the expense. + +--- + +## Design & Delivery Models + +These models help you design effective marketing systems. + +### Hick's Law +Decision time increases with the number and complexity of choices. More options = slower decisions = more abandonment. + +**Marketing application**: Simplify choices. One clear CTA beats three. Fewer form fields beat more. + +### AIDA Funnel +Attention → Interest → Desire → Action. The classic customer journey model. + +**Marketing application**: Structure pages and campaigns to move through each stage. Capture attention before building desire. + +### Rule of 7 +Prospects need roughly 7 touchpoints before converting. One ad rarely converts; sustained presence does. + +**Marketing application**: Build multi-touch campaigns across channels. Retargeting, email sequences, and consistent presence compound. + +### Nudge Theory / Choice Architecture +Small changes in how choices are presented significantly influence decisions. + +**Marketing application**: Default selections, strategic ordering, and friction reduction guide behavior without restricting choice. + +### BJ Fogg Behavior Model +Behavior = Motivation Ɨ Ability Ɨ Prompt. All three must be present for action. + +**Marketing application**: High motivation but hard to do = won't happen. Easy to do but no prompt = won't happen. Design for all three. + +### EAST Framework +Make desired behaviors: Easy, Attractive, Social, Timely. + +**Marketing application**: Reduce friction (easy), make it appealing (attractive), show others doing it (social), ask at the right moment (timely). + +### COM-B Model +Behavior requires: Capability, Opportunity, Motivation. + +**Marketing application**: Can they do it (capability)? Is the path clear (opportunity)? Do they want to (motivation)? Address all three. + +### Activation Energy +The initial energy required to start something. High activation energy prevents action even if the task is easy overall. + +**Marketing application**: Reduce starting friction. Pre-fill forms, offer templates, show quick wins. Make the first step trivially easy. + +### North Star Metric +One metric that best captures the value you deliver to customers. Focus creates alignment. + +**Marketing application**: Identify your North Star (active users, completed projects, revenue per customer) and align all efforts toward it. + +### The Cobra Effect +When incentives backfire and produce the opposite of intended results. + +**Marketing application**: Test incentive structures. A referral bonus might attract low-quality referrals gaming the system. + +--- + +## Growth & Scaling Models + +These models explain how marketing compounds and scales. + +### Feedback Loops +Output becomes input, creating cycles. Positive loops accelerate growth; negative loops create decline. + +**Marketing application**: Build virtuous cycles: more users → more content → better SEO → more users. Identify and strengthen positive loops. + +### Compounding +Small, consistent gains accumulate into large results over time. Early gains matter most. + +**Marketing application**: Consistent content, SEO, and brand building compound. Start early; benefits accumulate exponentially. + +### Network Effects +A product becomes more valuable as more people use it. + +**Marketing application**: Design features that improve with more users: shared workspaces, integrations, marketplaces, communities. + +### Flywheel Effect +Sustained effort creates momentum that eventually maintains itself. Hard to start, easy to maintain. + +**Marketing application**: Content → traffic → leads → customers → case studies → more content. Each element powers the next. + +### Switching Costs +The price (time, money, effort, data) of changing to a competitor. High switching costs create retention. + +**Marketing application**: Increase switching costs ethically: integrations, data accumulation, workflow customization, team adoption. + +### Exploration vs. Exploitation +Balance trying new things (exploration) with optimizing what works (exploitation). + +**Marketing application**: Don't abandon working channels for shiny new ones, but allocate some budget to experiments. + +### Critical Mass / Tipping Point +The threshold after which growth becomes self-sustaining. + +**Marketing application**: Focus resources on reaching critical mass in one segment before expanding. Depth before breadth. + +### Survivorship Bias +Focusing on successes while ignoring failures that aren't visible. + +**Marketing application**: Study failed campaigns, not just successful ones. The viral hit you're copying had 99 failures you didn't see. + +--- + diff --git a/marketing-skill/marketing-strategy-pmm/SKILL.md b/marketing-skill/marketing-strategy-pmm/SKILL.md index 6bcc4bb..7678bc5 100644 --- a/marketing-skill/marketing-strategy-pmm/SKILL.md +++ b/marketing-skill/marketing-strategy-pmm/SKILL.md @@ -376,3 +376,32 @@ Enter new markets systematically: | 2 | Create assets, publish content | | 3 | Support launches, optimize campaigns | | 4 | Monthly report, plan next month | + +## Proactive Triggers + +- **No documented positioning** → Without clear positioning, all marketing is guesswork. +- **Messaging differs across channels** → Inconsistent story confuses buyers. +- **No ICP defined** → Selling to everyone means selling to no one. +- **Competitor repositioning** → Market shift detected. Review your positioning. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Position my product" | Positioning framework (April Dunford method) with output | +| "GTM strategy" | Go-to-market plan with channels, messaging, and timeline | +| "Competitive positioning" | Positioning map with competitive gaps and opportunities | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **marketing-context**: For capturing foundational positioning. PMM builds on this. +- **launch-strategy**: For executing product launches planned by PMM. +- **competitive-intel** (C-Suite): For strategic competitive intelligence. +- **cmo-advisor** (C-Suite): For marketing budget and growth model decisions. diff --git a/marketing-skill/onboarding-cro/SKILL.md b/marketing-skill/onboarding-cro/SKILL.md new file mode 100644 index 0000000..13f9e38 --- /dev/null +++ b/marketing-skill/onboarding-cro/SKILL.md @@ -0,0 +1,253 @@ +--- +name: onboarding-cro +description: When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions "onboarding flow," "activation rate," "user activation," "first-run experience," "empty states," "onboarding checklist," "aha moment," or "new user experience." For signup/registration optimization, see signup-flow-cro. For ongoing email sequences, see email-sequence. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Onboarding CRO + +You are an expert in user onboarding and activation. Your goal is to help users reach their "aha moment" as quickly as possible and establish habits that lead to long-term retention. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, understand: + +1. **Product Context** - What type of product? B2B or B2C? Core value proposition? +2. **Activation Definition** - What's the "aha moment"? What action indicates a user "gets it"? +3. **Current State** - What happens after signup? Where do users drop off? + +--- + +## Core Principles + +### 1. Time-to-Value Is Everything +Remove every step between signup and experiencing core value. + +### 2. One Goal Per Session +Focus first session on one successful outcome. Save advanced features for later. + +### 3. Do, Don't Show +Interactive > Tutorial. Doing the thing > Learning about the thing. + +### 4. Progress Creates Motivation +Show advancement. Celebrate completions. Make the path visible. + +--- + +## Defining Activation + +### Find Your Aha Moment + +The action that correlates most strongly with retention: +- What do retained users do that churned users don't? +- What's the earliest indicator of future engagement? + +**Examples by product type:** +- Project management: Create first project + add team member +- Analytics: Install tracking + see first report +- Design tool: Create first design + export/share +- Marketplace: Complete first transaction + +### Activation Metrics +- % of signups who reach activation +- Time to activation +- Steps to activation +- Activation by cohort/source + +--- + +## Onboarding Flow Design + +### Immediate Post-Signup (First 30 Seconds) + +| Approach | Best For | Risk | +|----------|----------|------| +| Product-first | Simple products, B2C, mobile | Blank slate overwhelm | +| Guided setup | Products needing personalization | Adds friction before value | +| Value-first | Products with demo data | May not feel "real" | + +**Whatever you choose:** +- Clear single next action +- No dead ends +- Progress indication if multi-step + +### Onboarding Checklist Pattern + +**When to use:** +- Multiple setup steps required +- Product has several features to discover +- Self-serve B2B products + +**Best practices:** +- 3-7 items (not overwhelming) +- Order by value (most impactful first) +- Start with quick wins +- Progress bar/completion % +- Celebration on completion +- Dismiss option (don't trap users) + +### Empty States + +Empty states are onboarding opportunities, not dead ends. + +**Good empty state:** +- Explains what this area is for +- Shows what it looks like with data +- Clear primary action to add first item +- Optional: Pre-populate with example data + +### Tooltips and Guided Tours + +**When to use:** Complex UI, features that aren't self-evident, power features users might miss + +**Best practices:** +- Max 3-5 steps per tour +- Dismissable at any time +- Don't repeat for returning users + +--- + +## Multi-Channel Onboarding + +### Email + In-App Coordination + +**Trigger-based emails:** +- Welcome email (immediate) +- Incomplete onboarding (24h, 72h) +- Activation achieved (celebration + next step) +- Feature discovery (days 3, 7, 14) + +**Email should:** +- Reinforce in-app actions, not duplicate them +- Drive back to product with specific CTA +- Be personalized based on actions taken + +--- + +## Handling Stalled Users + +### Detection +Define "stalled" criteria (X days inactive, incomplete setup) + +### Re-engagement Tactics + +1. **Email sequence** - Reminder of value, address blockers, offer help +2. **In-app recovery** - Welcome back, pick up where left off +3. **Human touch** - For high-value accounts, personal outreach + +--- + +## Measurement + +### Key Metrics + +| Metric | Description | +|--------|-------------| +| Activation rate | % reaching activation event | +| Time to activation | How long to first value | +| Onboarding completion | % completing setup | +| Day 1/7/30 retention | Return rate by timeframe | + +### Funnel Analysis + +Track drop-off at each step: +``` +Signup → Step 1 → Step 2 → Activation → Retention +100% 80% 60% 40% 25% +``` + +Identify biggest drops and focus there. + +--- + +## Output Format + +### Onboarding Audit +For each issue: Finding → Impact → Recommendation → Priority + +### Onboarding Flow Design +- Activation goal +- Step-by-step flow +- Checklist items (if applicable) +- Empty state copy +- Email sequence triggers +- Metrics plan + +--- + +## Common Patterns by Product Type + +| Product Type | Key Steps | +|--------------|-----------| +| B2B SaaS | Setup wizard → First value action → Team invite → Deep setup | +| Marketplace | Complete profile → Browse → First transaction → Repeat loop | +| Mobile App | Permissions → Quick win → Push setup → Habit loop | +| Content Platform | Follow/customize → Consume → Create → Engage | + +--- + +## Experiment Ideas + +When recommending experiments, consider tests for: +- Flow simplification (step count, ordering) +- Progress and motivation mechanics +- Personalization by role or goal +- Support and help availability + +**For comprehensive experiment ideas**: See [references/experiments.md](references/experiments.md) + +--- + +## Task-Specific Questions + +1. What action most correlates with retention? +2. What happens immediately after signup? +3. Where do users currently drop off? +4. What's your activation rate target? +5. Do you have cohort analysis on successful vs. churned users? + +--- + +## Related Skills + +- **signup-flow-cro** — WHEN optimizing the registration and pre-onboarding flow before users ever land in-app. NOT when users have already signed up and activation is the goal. +- **popup-cro** — WHEN using in-product modals, tooltips, or overlays as part of the onboarding experience. NOT for standalone lead capture or exit-intent popups on the marketing site. +- **paywall-upgrade-cro** — WHEN onboarding naturally leads into an upgrade prompt after the aha moment is reached. NOT during early onboarding before value is delivered. +- **ab-test-setup** — WHEN running controlled experiments on onboarding flows, checklists, or step ordering. NOT for initial brainstorming or design. +- **marketing-context** — Foundation skill. ALWAYS load when product/ICP context is needed for personalized onboarding recommendations. NOT optional — load before this skill if available. + +--- + +## Communication + +Deliver recommendations following the output quality standard: lead with the highest-leverage finding, provide a clear activation definition, then prioritize experiments by expected impact. Avoid vague advice — every recommendation should name a specific onboarding step, metric, or trigger. When writing onboarding copy or flows, ensure tone matches the product's brand voice (load `marketing-context` if available). + +--- + +## Proactive Triggers + +- User mentions low Day-1 or Day-7 retention → immediately ask about their activation event and current post-signup flow. +- User shares a signup funnel with a big drop between "signup" and "first key action" → diagnose onboarding, not acquisition. +- User says "users sign up but don't come back" → frame this as an activation/onboarding problem, not a marketing problem. +- User asks about improving trial-to-paid conversion → check whether activation is defined and being reached before assuming pricing is the blocker. +- User mentions "onboarding emails aren't working" → ask what in-app onboarding exists first; email should support, not replace, in-app experience. + +--- + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| Activation Definition Doc | Clearly defined aha moment, correlated action, and success metric | +| Onboarding Flow Diagram | Step-by-step post-signup flow with drop-off points and decision branches | +| Checklist Copy | 3–7 onboarding checklist items ordered by value, with completion messaging | +| Email Trigger Map | Trigger conditions, timing, and goals for each onboarding email in the sequence | +| Experiment Backlog | Prioritized A/B test ideas for onboarding steps, sorted by expected impact | diff --git a/marketing-skill/onboarding-cro/scripts/activation_funnel_analyzer.py b/marketing-skill/onboarding-cro/scripts/activation_funnel_analyzer.py new file mode 100644 index 0000000..faa58df --- /dev/null +++ b/marketing-skill/onboarding-cro/scripts/activation_funnel_analyzer.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +""" +Activation Funnel Analyzer for Onboarding CRO + +Analyzes user onboarding funnel data to identify drop-off points +and estimate the impact of improving each step. + +Usage: + python3 activation_funnel_analyzer.py # Demo mode + python3 activation_funnel_analyzer.py funnel.json # From data + python3 activation_funnel_analyzer.py funnel.json --json # JSON output + +Input format (JSON): +{ + "steps": [ + {"name": "Signup completed", "users": 1000}, + {"name": "Email verified", "users": 850}, + {"name": "Profile setup", "users": 620}, + {"name": "First action", "users": 310}, + {"name": "Aha moment", "users": 180}, + {"name": "Activated (Day 7)", "users": 120} + ] +} +""" + +import json +import sys +import os + + +def analyze_funnel(data): + """Analyze onboarding funnel for drop-offs and improvement potential.""" + steps = data["steps"] + + if len(steps) < 2: + return {"error": "Need at least 2 funnel steps"} + + total_start = steps[0]["users"] + analysis = [] + worst_step = None + worst_drop = 0 + + for i in range(len(steps)): + step = steps[i] + users = step["users"] + rate_from_start = (users / total_start * 100) if total_start > 0 else 0 + + if i == 0: + step_analysis = { + "step": step["name"], + "users": users, + "rate_from_start": round(rate_from_start, 1), + "drop_rate": 0, + "dropped_users": 0, + "is_worst": False + } + else: + prev_users = steps[i - 1]["users"] + dropped = prev_users - users + drop_rate = (dropped / prev_users * 100) if prev_users > 0 else 0 + + step_analysis = { + "step": step["name"], + "users": users, + "rate_from_start": round(rate_from_start, 1), + "drop_rate": round(drop_rate, 1), + "dropped_users": dropped, + "is_worst": False + } + + if drop_rate > worst_drop: + worst_drop = drop_rate + worst_step = i + + analysis.append(step_analysis) + + if worst_step is not None: + analysis[worst_step]["is_worst"] = True + + # Calculate improvement potential + final_users = steps[-1]["users"] + overall_conversion = (final_users / total_start * 100) if total_start > 0 else 0 + + improvements = [] + if worst_step is not None: + worst = analysis[worst_step] + # What if we halved the drop-off at the worst step? + current_drop_rate = worst["drop_rate"] / 100 + improved_drop_rate = current_drop_rate / 2 + prev_users = steps[worst_step - 1]["users"] + gained_users = int(prev_users * (current_drop_rate - improved_drop_rate)) + + # Propagate improvement through remaining steps + cascade_rate = 1.0 + for j in range(worst_step + 1, len(steps)): + if steps[j - 1]["users"] > 0: + cascade_rate *= steps[j]["users"] / steps[j - 1]["users"] + + additional_activated = int(gained_users * cascade_rate) + + improvements.append({ + "action": f"Halve drop-off at '{worst['step']}'", + "current_drop": f"{worst['drop_rate']}%", + "target_drop": f"{worst['drop_rate'] / 2:.1f}%", + "users_saved": gained_users, + "additional_activated": additional_activated, + "impact_on_overall": f"+{(additional_activated / total_start * 100):.1f}pp" + }) + + # Score + score = min(100, max(0, int(overall_conversion * 5))) # 20% activation = 100 + if overall_conversion < 5: + score = max(0, int(overall_conversion * 10)) + + return { + "steps": analysis, + "summary": { + "total_start": total_start, + "total_activated": final_users, + "overall_conversion": round(overall_conversion, 1), + "worst_step": analysis[worst_step]["step"] if worst_step else None, + "worst_drop_rate": round(worst_drop, 1), + "score": score + }, + "improvements": improvements + } + + +def format_report(result): + """Format human-readable report.""" + lines = [] + lines.append("") + lines.append("=" * 65) + lines.append(" ONBOARDING FUNNEL — ACTIVATION ANALYSIS") + lines.append("=" * 65) + lines.append("") + + summary = result["summary"] + score = summary["score"] + bar = "ā–ˆ" * (score // 5) + "ā–‘" * (20 - score // 5) + + lines.append(f" ACTIVATION SCORE: {score}/100") + lines.append(f" [{bar}]") + lines.append(f" Overall: {summary['total_start']} → {summary['total_activated']} ({summary['overall_conversion']}%)") + lines.append("") + + # Funnel visualization + lines.append(" FUNNEL:") + max_users = result["steps"][0]["users"] + for step in result["steps"]: + bar_width = int(step["users"] / max_users * 40) if max_users > 0 else 0 + bar_char = "ā–ˆ" * bar_width + marker = " ← WORST DROP" if step["is_worst"] else "" + drop_info = f" (-{step['drop_rate']}%)" if step["drop_rate"] > 0 else "" + lines.append(f" {bar_char} {step['users']:>5} | {step['step']}{drop_info}{marker}") + + lines.append("") + + # Step-by-step breakdown + lines.append(" STEP BREAKDOWN:") + lines.append(f" {'Step':<25} {'Users':>7} {'From Start':>12} {'Drop':>8} {'Lost':>7}") + lines.append(" " + "-" * 62) + for step in result["steps"]: + drop = f"-{step['drop_rate']}%" if step["drop_rate"] > 0 else "—" + lost = f"-{step['dropped_users']}" if step["dropped_users"] > 0 else "—" + lines.append(f" {step['step']:<25} {step['users']:>7} {step['rate_from_start']:>10.1f}% {drop:>8} {lost:>7}") + lines.append("") + + # Improvement potential + if result["improvements"]: + lines.append(" šŸ’” IMPROVEMENT POTENTIAL:") + for imp in result["improvements"]: + lines.append(f" Action: {imp['action']}") + lines.append(f" Drop: {imp['current_drop']} → {imp['target_drop']}") + lines.append(f" Users saved at step: +{imp['users_saved']}") + lines.append(f" Additional activated: +{imp['additional_activated']}") + lines.append(f" Impact on overall rate: {imp['impact_on_overall']}") + lines.append("") + + return "\n".join(lines) + + +SAMPLE_DATA = { + "steps": [ + {"name": "Signup completed", "users": 1000}, + {"name": "Email verified", "users": 840}, + {"name": "Profile setup", "users": 580}, + {"name": "First project created", "users": 290}, + {"name": "Invited teammate", "users": 145}, + {"name": "Aha moment (Day 3)", "users": 95}, + {"name": "Activated (Day 7)", "users": 72} + ] +} + + +def main(): + use_json = "--json" in sys.argv + args = [a for a in sys.argv[1:] if a != "--json"] + + if args and os.path.isfile(args[0]): + with open(args[0]) as f: + data = json.load(f) + else: + if not args: + print("[Demo mode — analyzing sample SaaS onboarding funnel]") + data = SAMPLE_DATA + + result = analyze_funnel(data) + + if use_json: + print(json.dumps(result, indent=2)) + else: + print(format_report(result)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/page-cro/SKILL.md b/marketing-skill/page-cro/SKILL.md new file mode 100644 index 0000000..95cca64 --- /dev/null +++ b/marketing-skill/page-cro/SKILL.md @@ -0,0 +1,224 @@ +--- +name: page-cro +description: When the user wants to optimize, improve, or increase conversions on any marketing page — including homepage, landing pages, pricing pages, feature pages, or blog posts. Also use when the user says "CRO," "conversion rate optimization," "this page isn't converting," "improve conversions," or "why isn't this page working." For signup/registration flows, see signup-flow-cro. For post-signup activation, see onboarding-cro. For forms outside of signup, see form-cro. For popups/modals, see popup-cro. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Page Conversion Rate Optimization (CRO) + +You are a conversion rate optimization expert. Your goal is to analyze marketing pages and provide actionable recommendations to improve conversion rates. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, identify: + +1. **Page Type**: Homepage, landing page, pricing, feature, blog, about, other +2. **Primary Conversion Goal**: Sign up, request demo, purchase, subscribe, download, contact sales +3. **Traffic Context**: Where are visitors coming from? (organic, paid, email, social) + +--- + +## CRO Analysis Framework + +Analyze the page across these dimensions, in order of impact: + +### 1. Value Proposition Clarity (Highest Impact) + +**Check for:** +- Can a visitor understand what this is and why they should care within 5 seconds? +- Is the primary benefit clear, specific, and differentiated? +- Is it written in the customer's language (not company jargon)? + +**Common issues:** +- Feature-focused instead of benefit-focused +- Too vague or too clever (sacrificing clarity) +- Trying to say everything instead of the most important thing + +### 2. Headline Effectiveness + +**Evaluate:** +- Does it communicate the core value proposition? +- Is it specific enough to be meaningful? +- Does it match the traffic source's messaging? + +**Strong headline patterns:** +- Outcome-focused: "Get [desired outcome] without [pain point]" +- Specificity: Include numbers, timeframes, or concrete details +- Social proof: "Join 10,000+ teams who..." + +### 3. CTA Placement, Copy, and Hierarchy + +**Primary CTA assessment:** +- Is there one clear primary action? +- Is it visible without scrolling? +- Does the button copy communicate value, not just action? + - Weak: "Submit," "Sign Up," "Learn More" + - Strong: "Start Free Trial," "Get My Report," "See Pricing" + +**CTA hierarchy:** +- Is there a logical primary vs. secondary CTA structure? +- Are CTAs repeated at key decision points? + +### 4. Visual Hierarchy and Scannability + +**Check:** +- Can someone scanning get the main message? +- Are the most important elements visually prominent? +- Is there enough white space? +- Do images support or distract from the message? + +### 5. Trust Signals and Social Proof + +**Types to look for:** +- Customer logos (especially recognizable ones) +- Testimonials (specific, attributed, with photos) +- Case study snippets with real numbers +- Review scores and counts +- Security badges (where relevant) + +**Placement:** Near CTAs and after benefit claims + +### 6. Objection Handling + +**Common objections to address:** +- Price/value concerns +- "Will this work for my situation?" +- Implementation difficulty +- "What if it doesn't work?" + +**Address through:** FAQ sections, guarantees, comparison content, process transparency + +### 7. Friction Points + +**Look for:** +- Too many form fields +- Unclear next steps +- Confusing navigation +- Required information that shouldn't be required +- Mobile experience issues +- Long load times + +--- + +## Output Format + +Structure your recommendations as: + +### Quick Wins (Implement Now) +Easy changes with likely immediate impact. + +### High-Impact Changes (Prioritize) +Bigger changes that require more effort but will significantly improve conversions. + +### Test Ideas +Hypotheses worth A/B testing rather than assuming. + +### Copy Alternatives +For key elements (headlines, CTAs), provide 2-3 alternatives with rationale. + +--- + +## Page-Specific Frameworks + +### Homepage CRO +- Clear positioning for cold visitors +- Quick path to most common conversion +- Handle both "ready to buy" and "still researching" + +### Landing Page CRO +- Message match with traffic source +- Single CTA (remove navigation if possible) +- Complete argument on one page + +### Pricing Page CRO +- Clear plan comparison +- Recommended plan indication +- Address "which plan is right for me?" anxiety + +### Feature Page CRO +- Connect feature to benefit +- Use cases and examples +- Clear path to try/buy + +### Blog Post CRO +- Contextual CTAs matching content topic +- Inline CTAs at natural stopping points + +--- + +## Experiment Ideas + +When recommending experiments, consider tests for: +- Hero section (headline, visual, CTA) +- Trust signals and social proof placement +- Pricing presentation +- Form optimization +- Navigation and UX + +**For comprehensive experiment ideas by page type**: See [references/experiments.md](references/experiments.md) + +--- + +## Task-Specific Questions + +1. What's your current conversion rate and goal? +2. Where is traffic coming from? +3. What does your signup/purchase flow look like after this page? +4. Do you have user research, heatmaps, or session recordings? +5. What have you already tried? + +--- + +## Related Skills + +- **signup-flow-cro** — WHEN: the page itself converts well but users drop off during the signup or registration process that follows it. WHEN NOT: don't switch to signup-flow-cro if the page itself is the bottleneck; fix the page first. +- **form-cro** — WHEN: the page contains a lead capture or contact form that is a conversion point in its own right (not a signup flow). WHEN NOT: don't use for embedded signup/account-creation forms; those belong in signup-flow-cro. +- **popup-cro** — WHEN: a popup or exit-intent modal is being considered as a conversion layer on top of the page. WHEN NOT: don't reach for popups before fixing core page conversion issues. +- **copywriting** — WHEN: the page requires a full copy overhaul, not just CTA tweaks; the messaging architecture needs rebuilding from the value prop down. WHEN NOT: don't invoke copywriting for minor headline or button copy iterations. +- **ab-test-setup** — WHEN: recommendations are ready and the team needs a structured experiment plan to validate changes without guessing. WHEN NOT: don't use ab-test-setup before having a clear hypothesis from the CRO analysis. +- **onboarding-cro** — WHEN: post-conversion activation is the real problem and the page is already converting adequately. WHEN NOT: don't jump to onboarding-cro before confirming the page conversion rate is acceptable. +- **marketing-context** — WHEN: always read `.claude/product-marketing-context.md` first to understand ICP, messaging, and traffic sources before evaluating the page. WHEN NOT: skip if the user has shared all relevant context directly. + +--- + +## Communication + +All page CRO output follows this quality standard: +- Recommendations are always organized as **Quick Wins → High-Impact → Test Ideas** — never a flat list +- Every recommendation includes a brief rationale tied to the CRO analysis framework dimension it addresses +- Copy alternatives are provided in sets of 2-3 with the reasoning for each variant +- Page-specific framework (homepage, landing page, pricing, etc.) is applied explicitly — don't give generic advice +- Never recommend A/B testing as a substitute for obvious fixes; call out what to fix vs. what to test +- Avoid prescribing layout without acknowledging traffic source and audience context + +--- + +## Proactive Triggers + +Automatically surface page-cro recommendations when: + +1. **"This page isn't converting"** — Any mention of low conversion, poor page performance, or high bounce rate immediately activates the CRO analysis framework. +2. **New landing page being built** — When copywriting or frontend-design skills are active and a marketing page is being created, proactively offer a CRO review before launch. +3. **Paid traffic mentioned** — User describes running ads to a page; immediately flag message-match and single-CTA best practices. +4. **Pricing page discussion** — Any pricing strategy or packaging conversation; proactively recommend pricing page CRO review alongside positioning work. +5. **A/B test results reviewed** — When ab-test-setup skill surfaces test results, offer a page-cro analysis to generate the next round of hypotheses. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| CRO Audit Summary | Markdown sections | Analysis across all 7 framework dimensions with issue severity ratings | +| Quick Wins List | Bullet list | ≤5 changes implementable immediately with expected impact | +| High-Impact Recommendations | Structured list | Each with rationale, effort estimate, and success metric | +| Copy Alternatives | Side-by-side table | 2-3 variants per key element (headline, CTA, subhead) with reasoning | +| A/B Test Hypotheses | Table | Hypothesis Ɨ variant description Ɨ success metric Ɨ priority | diff --git a/marketing-skill/page-cro/scripts/conversion_audit.py b/marketing-skill/page-cro/scripts/conversion_audit.py new file mode 100755 index 0000000..75f40a9 --- /dev/null +++ b/marketing-skill/page-cro/scripts/conversion_audit.py @@ -0,0 +1,427 @@ +#!/usr/bin/env python3 +""" +conversion_audit.py — CRO audit for HTML pages +Usage: + python3 conversion_audit.py --file page.html + python3 conversion_audit.py --url https://example.com + python3 conversion_audit.py --json + python3 conversion_audit.py # demo mode +""" + +import argparse +import json +import re +import sys +import urllib.request +from html.parser import HTMLParser + + +# --------------------------------------------------------------------------- +# HTML Parser +# --------------------------------------------------------------------------- + +class CROParser(HTMLParser): + def __init__(self): + super().__init__() + self._depth = 0 + self._above_fold_depth = 3 # approximate first screenful + self._above_fold_elements = 0 + self._total_elements = 0 + + self.buttons = [] # {"text": str, "position": int} + self.links_as_cta = [] # a tags with CTA-like classes/text + self.form_fields = 0 + self.forms = 0 + + # Social proof + self.testimonial_markers = 0 + self.logo_images = 0 + self.social_numbers = [] # "X customers", "X reviews", etc. + + # Trust signals + self.ssl_mentions = 0 + self.guarantee_mentions = 0 + self.privacy_mentions = 0 + + # Viewport meta + self.viewport_meta = False + + # Tracking state + self._in_body = False + self._above_fold_done = False + self._body_element_count = 0 + self._in_script = False + self._in_style = False + self._current_tag = None + self._current_text = [] + self._element_position = 0 # rough position counter + + # Full text (for regex scans) + self.full_text = [] + + def handle_starttag(self, tag, attrs): + attrs_dict = dict(attrs) + tag_lower = tag.lower() + + if tag_lower == "script": + self._in_script = True + return + if tag_lower == "style": + self._in_style = True + return + + if tag_lower == "body": + self._in_body = True + return + + if tag_lower == "meta": + if attrs_dict.get("name", "").lower() == "viewport": + self.viewport_meta = True + + if not self._in_body: + return + + self._element_position += 1 + + # Buttons + if tag_lower == "button": + self._current_tag = "button" + self._current_text = [] + elif tag_lower == "input": + input_type = attrs_dict.get("type", "text").lower() + if input_type == "submit": + val = attrs_dict.get("value", "Submit") + self.buttons.append({"text": val, "position": self._element_position}) + elif input_type not in ("hidden", "submit"): + self.form_fields += 1 + elif tag_lower == "textarea" or tag_lower == "select": + self.form_fields += 1 + elif tag_lower == "form": + self.forms += 1 + elif tag_lower == "a": + cls = attrs_dict.get("class", "").lower() + href = attrs_dict.get("href", "") + cta_classes = {"btn", "button", "cta", "call-to-action", "signup", "register"} + if any(c in cls for c in cta_classes): + self._current_tag = "a_cta" + self._current_text = [] + elif tag_lower == "img": + src = attrs_dict.get("src", "").lower() + alt = attrs_dict.get("alt", "").lower() + cls = attrs_dict.get("class", "").lower() + if any(kw in src or kw in alt or kw in cls + for kw in ("logo", "partner", "client", "badge", "seal", "award", "cert")): + self.logo_images += 1 + + def handle_endtag(self, tag): + tag_lower = tag.lower() + if tag_lower == "script": + self._in_script = False + elif tag_lower == "style": + self._in_style = False + elif tag_lower == "button" and self._current_tag == "button": + text = " ".join(self._current_text).strip() + self.buttons.append({"text": text, "position": self._element_position}) + self._current_tag = None + self._current_text = [] + elif tag_lower == "a" and self._current_tag == "a_cta": + text = " ".join(self._current_text).strip() + self.links_as_cta.append({"text": text, "position": self._element_position}) + self._current_tag = None + self._current_text = [] + + def handle_data(self, data): + if self._in_script or self._in_style: + return + text = data.strip() + if not text: + return + if self._current_tag in ("button", "a_cta"): + self._current_text.append(text) + if self._in_body: + self.full_text.append(text) + + +# --------------------------------------------------------------------------- +# Text-based signal detection +# --------------------------------------------------------------------------- + +TESTIMONIAL_PATTERNS = [ + r'\b(testimonial|review|quote|said|says|told us|customer story)\b', + r'[""][^""]{20,}[""]', # quoted text + r'\b\d[\d,]+ (reviews?|customers?|users?|clients?|companies)\b', + r'\bstar[s]?\b.{0,10}\b(rating|review)\b', + r'\b(trustpilot|g2|capterra|clutch)\b', +] + +TRUST_PATTERNS = { + "ssl": [r'\b(ssl|https|secure|encrypted|tls|256.bit)\b'], + "guarantee": [r'\b(guarantee|guaranteed|money.back|refund|risk.free|no.risk)\b'], + "privacy": [r'\b(privacy|gdpr|data protection|we never share|no spam|unsubscribe)\b'], +} + +CTA_TEXT_PATTERNS = [ + r'\b(get started|sign up|try free|start free|buy now|order now|get access|' + r'download|schedule|book|claim|join|subscribe|register|contact us|learn more|' + r'get quote|request demo|start trial|get demo)\b', +] + + +def scan_text_signals(full_text: str) -> dict: + text_lower = full_text.lower() + testimonials = sum( + len(re.findall(p, text_lower, re.IGNORECASE)) + for p in TESTIMONIAL_PATTERNS + ) + trust = {} + for key, patterns in TRUST_PATTERNS.items(): + trust[key] = sum(len(re.findall(p, text_lower, re.IGNORECASE)) for p in patterns) + + cta_text_count = sum( + len(re.findall(p, text_lower, re.IGNORECASE)) + for p in CTA_TEXT_PATTERNS + ) + + return { + "testimonial_signals": min(testimonials, 20), + "trust": trust, + "cta_text_count": cta_text_count, + } + + +# --------------------------------------------------------------------------- +# Scoring +# --------------------------------------------------------------------------- + +def score_category(value, thresholds: list) -> int: + """thresholds: [(min_value, score), ...] sorted asc. Returns score for first match.""" + for min_val, score in sorted(thresholds, reverse=True): + if value >= min_val: + return score + return 0 + + +def audit(html: str) -> dict: + parser = CROParser() + parser.feed(html) + + full_text = " ".join(parser.full_text) + text_signals = scan_text_signals(full_text) + + all_ctas = parser.buttons + parser.links_as_cta + total_cta_count = len(all_ctas) + text_signals["cta_text_count"] + + # --- CTA --- + cta_score = score_category(total_cta_count, [(0, 0), (1, 50), (2, 75), (3, 90), (5, 100)]) + cta_above_fold = len([c for c in all_ctas if c["position"] <= 5]) + if cta_above_fold >= 1: + cta_score = min(100, cta_score + 10) + + # --- Forms --- + if parser.forms == 0: + form_score = 60 # not all pages need forms + form_note = "No form detected (OK if not a lead gen page)" + elif parser.form_fields <= 3: + form_score = 100 + form_note = f"{parser.form_fields} field(s) — minimal friction" + elif parser.form_fields <= 5: + form_score = 70 + form_note = f"{parser.form_fields} field(s) — consider trimming" + else: + form_score = max(10, 100 - (parser.form_fields - 3) * 10) + form_note = f"{parser.form_fields} field(s) — too many, high friction" + + # --- Social proof --- + social_signals = text_signals["testimonial_signals"] + parser.logo_images + social_score = score_category(social_signals, [(0, 0), (1, 40), (2, 65), (4, 85), (6, 100)]) + + # --- Trust signals --- + trust = text_signals["trust"] + trust_total = sum(min(1, v) for v in trust.values()) # 0-3 + trust_score = score_category(trust_total, [(0, 20), (1, 60), (2, 80), (3, 100)]) + + # --- Viewport meta --- + viewport_score = 100 if parser.viewport_meta else 0 + + # --- Overall --- + weights = { + "cta": 0.30, + "social_proof": 0.25, + "trust_signals": 0.20, + "forms": 0.15, + "viewport_mobile": 0.10, + } + scores = { + "cta": cta_score, + "social_proof": social_score, + "trust_signals": trust_score, + "forms": form_score, + "viewport_mobile": viewport_score, + } + overall = round(sum(scores[k] * weights[k] for k in weights)) + + return { + "overall_score": overall, + "categories": { + "cta_buttons": { + "score": cta_score, + "button_count": len(parser.buttons), + "cta_link_count": len(parser.links_as_cta), + "cta_text_count": text_signals["cta_text_count"], + "above_fold_ctas": cta_above_fold, + "weight": "30%", + }, + "social_proof": { + "score": social_score, + "testimonial_signals": text_signals["testimonial_signals"], + "logo_badge_images": parser.logo_images, + "total_signals": social_signals, + "weight": "25%", + }, + "trust_signals": { + "score": trust_score, + "ssl_mentions": trust["ssl"], + "guarantee_mentions": trust["guarantee"], + "privacy_mentions": trust["privacy"], + "weight": "20%", + }, + "forms": { + "score": form_score, + "form_count": parser.forms, + "field_count": parser.form_fields, + "note": form_note, + "weight": "15%", + }, + "viewport_mobile": { + "score": viewport_score, + "viewport_meta_present": parser.viewport_meta, + "weight": "10%", + }, + }, + } + + +# --------------------------------------------------------------------------- +# Demo HTML +# --------------------------------------------------------------------------- + +DEMO_HTML = """ + + + + + Get Your Free Marketing Audit + + +
+ + Get Free Audit +
+
+

Stop Wasting Your Ad Budget

+

Join 12,400 marketers who cut wasted spend by 35% in 30 days.

+ +
+ +
+

Get Your Free Audit

+ + + + + +

šŸ”’ SSL secured. We never share your data. Unsubscribe anytime.

+

30-day money-back guarantee. No risk.

+
+ +""" + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="CRO audit — analyzes an HTML page for conversion signals." + ) + parser.add_argument("--file", help="Path to HTML file") + parser.add_argument("--url", help="URL to fetch and analyze") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r", encoding="utf-8", errors="replace") as f: + html = f.read() + elif args.url: + with urllib.request.urlopen(args.url, timeout=10) as resp: + html = resp.read().decode("utf-8", errors="replace") + else: + html = DEMO_HTML + if not args.json: + print("No input provided — running in demo mode.\n") + + result = audit(html) + + if args.json: + print(json.dumps(result, indent=2)) + return + + cats = result["categories"] + overall = result["overall_score"] + + print("=" * 62) + print(f" CRO AUDIT RESULTS Overall Score: {overall}/100") + print("=" * 62) + + rows = [ + ("CTA Buttons", "cta_buttons"), + ("Social Proof", "social_proof"), + ("Trust Signals", "trust_signals"), + ("Forms", "forms"), + ("Mobile Viewport", "viewport_mobile"), + ] + + for label, key in rows: + c = cats[key] + score = c["score"] + weight = c["weight"] + bar_len = round(score / 10) + bar = "ā–ˆ" * bar_len + "ā–‘" * (10 - bar_len) + icon = "āœ…" if score >= 70 else ("āš ļø " if score >= 40 else "āŒ") + print(f" {icon} {label:<18} [{bar}] {score:>3}/100 (weight {weight})") + + print() + # Detail callouts + cta = cats["cta_buttons"] + print(f" CTAs: {cta['button_count']} buttons, {cta['cta_link_count']} CTA links, " + f"{cta['cta_text_count']} CTA text phrases, {cta['above_fold_ctas']} above fold") + + sp = cats["social_proof"] + print(f" Social Proof: {sp['testimonial_signals']} testimonial signals, " + f"{sp['logo_badge_images']} logos/badges") + + ts = cats["trust_signals"] + print(f" Trust: SSL({ts['ssl_mentions']}) Guarantee({ts['guarantee_mentions']}) " + f"Privacy({ts['privacy_mentions']})") + + fm = cats["forms"] + print(f" Forms: {fm['form_count']} form(s), {fm['field_count']} field(s) — {fm['note']}") + + print() + grade = "A" if overall >= 85 else "B" if overall >= 70 else "C" if overall >= 55 else "D" if overall >= 40 else "F" + print("=" * 62) + print(f" Grade: {grade} Score: {overall}/100") + print("=" * 62) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/paid-ads/SKILL.md b/marketing-skill/paid-ads/SKILL.md new file mode 100644 index 0000000..5ee669f --- /dev/null +++ b/marketing-skill/paid-ads/SKILL.md @@ -0,0 +1,347 @@ +--- +name: paid-ads +description: "When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ad copy,' 'ad creative,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' or 'audience targeting.' This skill covers campaign strategy, ad creation, audience targeting, and optimization." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Paid Ads + +You are an expert performance marketer with direct access to ad platform accounts. Your goal is to help create, optimize, and scale paid advertising campaigns that drive efficient customer acquisition. + +## Before Starting + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Gather this context (ask if not provided): + +### 1. Campaign Goals +- What's the primary objective? (Awareness, traffic, leads, sales, app installs) +- What's the target CPA or ROAS? +- What's the monthly/weekly budget? +- Any constraints? (Brand guidelines, compliance, geographic) + +### 2. Product & Offer +- What are you promoting? (Product, free trial, lead magnet, demo) +- What's the landing page URL? +- What makes this offer compelling? + +### 3. Audience +- Who is the ideal customer? +- What problem does your product solve for them? +- What are they searching for or interested in? +- Do you have existing customer data for lookalikes? + +### 4. Current State +- Have you run ads before? What worked/didn't? +- Do you have existing pixel/conversion data? +- What's your current funnel conversion rate? + +--- + +## Platform Selection Guide + +| Platform | Best For | Use When | +|----------|----------|----------| +| **Google Ads** | High-intent search traffic | People actively search for your solution | +| **Meta** | Demand generation, visual products | Creating demand, strong creative assets | +| **LinkedIn** | B2B, decision-makers | Job title/company targeting matters, higher price points | +| **Twitter/X** | Tech audiences, thought leadership | Audience is active on X, timely content | +| **TikTok** | Younger demographics, viral creative | Audience skews 18-34, video capacity | + +--- + +## Campaign Structure Best Practices + +### Account Organization + +``` +Account +ā”œā”€ā”€ Campaign 1: [Objective] - [Audience/Product] +│ ā”œā”€ā”€ Ad Set 1: [Targeting variation] +│ │ ā”œā”€ā”€ Ad 1: [Creative variation A] +│ │ ā”œā”€ā”€ Ad 2: [Creative variation B] +│ │ └── Ad 3: [Creative variation C] +│ └── Ad Set 2: [Targeting variation] +└── Campaign 2... +``` + +### Naming Conventions + +``` +[Platform]_[Objective]_[Audience]_[Offer]_[Date] + +Examples: +META_Conv_Lookalike-Customers_FreeTrial_2024Q1 +GOOG_Search_Brand_Demo_Ongoing +LI_LeadGen_CMOs-SaaS_Whitepaper_Mar24 +``` + +### Budget Allocation + +**Testing phase (first 2-4 weeks):** +- 70% to proven/safe campaigns +- 30% to testing new audiences/creative + +**Scaling phase:** +- Consolidate budget into winning combinations +- Increase budgets 20-30% at a time +- Wait 3-5 days between increases for algorithm learning + +--- + +## Ad Copy Frameworks + +### Key Formulas + +**Problem-Agitate-Solve (PAS):** +> [Problem] → [Agitate the pain] → [Introduce solution] → [CTA] + +**Before-After-Bridge (BAB):** +> [Current painful state] → [Desired future state] → [Your product as bridge] + +**Social Proof Lead:** +> [Impressive stat or testimonial] → [What you do] → [CTA] + +**For detailed templates and headline formulas**: See [references/ad-copy-templates.md](references/ad-copy-templates.md) + +--- + +## Audience Targeting Overview + +### Platform Strengths + +| Platform | Key Targeting | Best Signals | +|----------|---------------|--------------| +| Google | Keywords, search intent | What they're searching | +| Meta | Interests, behaviors, lookalikes | Engagement patterns | +| LinkedIn | Job titles, companies, industries | Professional identity | + +### Key Concepts + +- **Lookalikes**: Base on best customers (by LTV), not all customers +- **Retargeting**: Segment by funnel stage (visitors vs. cart abandoners) +- **Exclusions**: Always exclude existing customers and recent converters + +**For detailed targeting strategies by platform**: See [references/audience-targeting.md](references/audience-targeting.md) + +--- + +## Creative Best Practices + +### Image Ads +- Clear product screenshots showing UI +- Before/after comparisons +- Stats and numbers as focal point +- Human faces (real, not stock) +- Bold, readable text overlay (keep under 20%) + +### Video Ads Structure (15-30 sec) +1. Hook (0-3 sec): Pattern interrupt, question, or bold statement +2. Problem (3-8 sec): Relatable pain point +3. Solution (8-20 sec): Show product/benefit +4. CTA (20-30 sec): Clear next step + +**Production tips:** +- Captions always (85% watch without sound) +- Vertical for Stories/Reels, square for feed +- Native feel outperforms polished +- First 3 seconds determine if they watch + +### Creative Testing Hierarchy +1. Concept/angle (biggest impact) +2. Hook/headline +3. Visual style +4. Body copy +5. CTA + +--- + +## Campaign Optimization + +### Key Metrics by Objective + +| Objective | Primary Metrics | +|-----------|-----------------| +| Awareness | CPM, Reach, Video view rate | +| Consideration | CTR, CPC, Time on site | +| Conversion | CPA, ROAS, Conversion rate | + +### Optimization Levers + +**If CPA is too high:** +1. Check landing page (is the problem post-click?) +2. Tighten audience targeting +3. Test new creative angles +4. Improve ad relevance/quality score +5. Adjust bid strategy + +**If CTR is low:** +- Creative isn't resonating → test new hooks/angles +- Audience mismatch → refine targeting +- Ad fatigue → refresh creative + +**If CPM is high:** +- Audience too narrow → expand targeting +- High competition → try different placements +- Low relevance score → improve creative fit + +### Bid Strategy Progression +1. Start with manual or cost caps +2. Gather conversion data (50+ conversions) +3. Switch to automated with targets based on historical data +4. Monitor and adjust targets based on results + +--- + +## Retargeting Strategies + +### Funnel-Based Approach + +| Funnel Stage | Audience | Message | Goal | +|--------------|----------|---------|------| +| Top | Blog readers, video viewers | Educational, social proof | Move to consideration | +| Middle | Pricing/feature page visitors | Case studies, demos | Move to decision | +| Bottom | Cart abandoners, trial users | Urgency, objection handling | Convert | + +### Retargeting Windows + +| Stage | Window | Frequency Cap | +|-------|--------|---------------| +| Hot (cart/trial) | 1-7 days | Higher OK | +| Warm (key pages) | 7-30 days | 3-5x/week | +| Cold (any visit) | 30-90 days | 1-2x/week | + +### Exclusions to Set Up +- Existing customers (unless upsell) +- Recent converters (7-14 day window) +- Bounced visitors (<10 sec) +- Irrelevant pages (careers, support) + +--- + +## Reporting & Analysis + +### Weekly Review +- Spend vs. budget pacing +- CPA/ROAS vs. targets +- Top and bottom performing ads +- Audience performance breakdown +- Frequency check (fatigue risk) +- Landing page conversion rate + +### Attribution Considerations +- Platform attribution is inflated +- Use UTM parameters consistently +- Compare platform data to GA4 +- Look at blended CAC, not just platform CPA + +--- + +## Platform Setup + +Before launching campaigns, ensure proper tracking and account setup. + +**For complete setup checklists by platform**: See [references/platform-setup-checklists.md](references/platform-setup-checklists.md) + +### Universal Pre-Launch Checklist +- [ ] Conversion tracking tested with real conversion +- [ ] Landing page loads fast (<3 sec) +- [ ] Landing page mobile-friendly +- [ ] UTM parameters working +- [ ] Budget set correctly +- [ ] Targeting matches intended audience + +--- + +## Common Mistakes to Avoid + +### Strategy +- Launching without conversion tracking +- Too many campaigns (fragmenting budget) +- Not giving algorithms enough learning time +- Optimizing for wrong metric + +### Targeting +- Audiences too narrow or too broad +- Not excluding existing customers +- Overlapping audiences competing + +### Creative +- Only one ad per ad set +- Not refreshing creative (fatigue) +- Mismatch between ad and landing page + +### Budget +- Spreading too thin across campaigns +- Making big budget changes (disrupts learning) +- Stopping campaigns during learning phase + +--- + +## Task-Specific Questions + +1. What platform(s) are you currently running or want to start with? +2. What's your monthly ad budget? +3. What does a successful conversion look like (and what's it worth)? +4. Do you have existing creative assets or need to create them? +5. What landing page will ads point to? +6. Do you have pixel/conversion tracking set up? + +--- + +## Tool Integrations + +For implementation, see the [tools registry](../../tools/REGISTRY.md). Key advertising platforms: + +| Platform | Best For | MCP | Guide | +|----------|----------|:---:|-------| +| **Google Ads** | Search intent, high-intent traffic | āœ“ | [google-ads.md](../../tools/integrations/google-ads.md) | +| **Meta Ads** | Demand gen, visual products, B2C | - | [meta-ads.md](../../tools/integrations/meta-ads.md) | +| **LinkedIn Ads** | B2B, job title targeting | - | [linkedin-ads.md](../../tools/integrations/linkedin-ads.md) | +| **TikTok Ads** | Younger demographics, video | - | [tiktok-ads.md](../../tools/integrations/tiktok-ads.md) | + +For tracking, see also: [ga4.md](../../tools/integrations/ga4.md), [segment.md](../../tools/integrations/segment.md) + +--- + +## Related Skills + +- **ad-creative** — WHEN you need deep creative direction for ad visuals, video scripts, or creative concepting beyond basic image/copy guidelines. NOT for campaign strategy, targeting, or bidding decisions. +- **analytics-tracking** — WHEN setting up conversion tracking pixels, UTM parameters, and attribution models before or during campaign launch. NOT for campaign creation or creative work. +- **campaign-analytics** — WHEN analyzing campaign performance data, diagnosing underperforming campaigns, or building reporting dashboards. NOT for initial campaign setup or creative production. +- **copywriting** — WHEN landing pages linked from ads need copy optimization to match ad messaging and improve post-click conversion. NOT for the ad copy itself. +- **marketing-context** — Foundation skill for ICP, positioning, and messaging alignment. ALWAYS load before writing ad copy or selecting targeting to ensure message-market fit. + +--- + +## Communication + +Always confirm conversion tracking is in place before recommending creative or targeting changes — a campaign without proper attribution is guesswork. When recommending budget allocation, state the rationale (testing vs. scaling phase). Deliver ad copy as complete, ready-to-launch sets: headline variants, body copy, and CTA. Proactively flag when a landing page mismatch (ad promise ≠ page promise) is the likely conversion bottleneck. Load `marketing-context` for ICP and positioning before writing any copy. + +--- + +## Proactive Triggers + +- User asks why ROAS is dropping → check creative fatigue and ad frequency before adjusting targeting or bids. +- User wants to launch their first paid campaign → run through the pre-launch checklist (conversion tracking, landing page speed, UTMs) before touching creative. +- User mentions high CTR but low conversions → diagnose landing page, not the ad; redirect to `page-cro` or `copywriting` skill. +- User is scaling budget aggressively → warn about algorithm learning phase disruption; recommend 20-30% incremental increases with 3-5 day stabilization windows. +- User asks about B2B lead generation via ads → recommend LinkedIn for job-title targeting and flag that CPL will be higher but lead quality better than Meta for high-ACV products. + +--- + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| Campaign Architecture | Full account structure with campaign names, ad set targeting, naming conventions, and budget allocation | +| Ad Copy Set | 3 headline variants, body copy, and CTA for each ad format and platform, ready to launch | +| Audience Targeting Brief | Primary audiences, lookalike seeds, retargeting segments, and exclusion lists per platform | +| Pre-Launch Checklist | Platform-specific tracking verification, landing page audit, and UTM parameter setup | +| Weekly Optimization Report Template | Metrics dashboard structure with CPA/ROAS targets, fatigue signals, and decision triggers | diff --git a/marketing-skill/paid-ads/references/ad-copy-templates.md b/marketing-skill/paid-ads/references/ad-copy-templates.md new file mode 100644 index 0000000..1b7620b --- /dev/null +++ b/marketing-skill/paid-ads/references/ad-copy-templates.md @@ -0,0 +1,200 @@ +# Ad Copy Templates Reference + +Detailed formulas and templates for writing high-converting ad copy. + +## Primary Text Formulas + +### Problem-Agitate-Solve (PAS) + +``` +[Problem statement] +[Agitate the pain] +[Introduce solution] +[CTA] +``` + +**Example:** +> Spending hours on manual reporting every week? +> While you're buried in spreadsheets, your competitors are making decisions. +> [Product] automates your reports in minutes. +> Start your free trial → + +--- + +### Before-After-Bridge (BAB) + +``` +[Current painful state] +[Desired future state] +[Your product as the bridge] +``` + +**Example:** +> Before: Chasing down approvals across email, Slack, and spreadsheets. +> After: Every approval tracked, automated, and on time. +> [Product] connects your tools and keeps projects moving. + +--- + +### Social Proof Lead + +``` +[Impressive stat or testimonial] +[What you do] +[CTA] +``` + +**Example:** +> "We cut our reporting time by 75%." — Sarah K., Marketing Director +> [Product] automates the reports you hate building. +> See how it works → + +--- + +### Feature-Benefit Bridge + +``` +[Feature] +[So that...] +[Which means...] +``` + +**Example:** +> Real-time collaboration on documents +> So your team always works from the latest version +> Which means no more version confusion or lost work + +--- + +### Direct Response + +``` +[Bold claim/outcome] +[Proof point] +[CTA with urgency if genuine] +``` + +**Example:** +> Cut your reporting time by 80% +> Join 5,000+ marketing teams already using [Product] +> Start free → First month 50% off + +--- + +## Headline Formulas + +### For Search Ads + +| Formula | Example | +|---------|---------| +| [Keyword] + [Benefit] | "Project Management That Teams Actually Use" | +| [Action] + [Outcome] | "Automate Reports \| Save 10 Hours Weekly" | +| [Question] | "Tired of Manual Data Entry?" | +| [Number] + [Benefit] | "500+ Teams Trust [Product] for [Outcome]" | +| [Keyword] + [Differentiator] | "CRM Built for Small Teams" | +| [Price/Offer] + [Keyword] | "Free Project Management \| No Credit Card" | + +### For Social Ads + +| Type | Example | +|------|---------| +| Outcome hook | "How we 3x'd our conversion rate" | +| Curiosity hook | "The reporting hack no one talks about" | +| Contrarian hook | "Why we stopped using [common tool]" | +| Specificity hook | "The exact template we use for..." | +| Question hook | "What if you could cut your admin time in half?" | +| Number hook | "7 ways to improve your workflow today" | +| Story hook | "We almost gave up. Then we found..." | + +--- + +## CTA Variations + +### Soft CTAs (awareness/consideration) + +Best for: Top of funnel, cold audiences, complex products + +- Learn More +- See How It Works +- Watch Demo +- Get the Guide +- Explore Features +- See Examples +- Read the Case Study + +### Hard CTAs (conversion) + +Best for: Bottom of funnel, warm audiences, clear offers + +- Start Free Trial +- Get Started Free +- Book a Demo +- Claim Your Discount +- Buy Now +- Sign Up Free +- Get Instant Access + +### Urgency CTAs (use when genuine) + +Best for: Limited-time offers, scarcity situations + +- Limited Time: 30% Off +- Offer Ends [Date] +- Only X Spots Left +- Last Chance +- Early Bird Pricing Ends Soon + +### Action-Oriented CTAs + +Best for: Active voice, clear next step + +- Start Saving Time Today +- Get Your Free Report +- See Your Score +- Calculate Your ROI +- Build Your First Project + +--- + +## Platform-Specific Copy Guidelines + +### Google Search Ads + +- **Headline limits:** 30 characters each (up to 15 headlines) +- **Description limits:** 90 characters each (up to 4 descriptions) +- Include keywords naturally +- Use all available headline slots +- Include numbers and stats when possible +- Test dynamic keyword insertion + +### Meta Ads (Facebook/Instagram) + +- **Primary text:** 125 characters visible (can be longer, gets truncated) +- **Headline:** 40 characters recommended +- Front-load the hook (first line matters most) +- Emojis can work but test +- Questions perform well +- Keep image text under 20% + +### LinkedIn Ads + +- **Intro text:** 600 characters max (150 recommended) +- **Headline:** 200 characters max (70 recommended) +- Professional tone (but not boring) +- Specific job outcomes resonate +- Stats and social proof important +- Avoid consumer-style hype + +--- + +## Copy Testing Priority + +When testing ad copy, focus on these elements in order of impact: + +1. **Hook/angle** (biggest impact on performance) +2. **Headline** +3. **Primary benefit** +4. **CTA** +5. **Supporting proof points** + +Test one element at a time for clean data. diff --git a/marketing-skill/paid-ads/references/audience-targeting.md b/marketing-skill/paid-ads/references/audience-targeting.md new file mode 100644 index 0000000..a0f5695 --- /dev/null +++ b/marketing-skill/paid-ads/references/audience-targeting.md @@ -0,0 +1,234 @@ +# Audience Targeting Reference + +Detailed targeting strategies for each major ad platform. + +## Google Ads Audiences + +### Search Campaign Targeting + +**Keywords:** +- Exact match: [keyword] — most precise, lower volume +- Phrase match: "keyword" — moderate precision and volume +- Broad match: keyword — highest volume, use with smart bidding + +**Audience layering:** +- Add audiences in "observation" mode first +- Analyze performance by audience +- Switch to "targeting" mode for high performers + +**RLSA (Remarketing Lists for Search Ads):** +- Bid higher on past visitors searching your terms +- Show different ads to returning searchers +- Exclude converters from prospecting campaigns + +### Display/YouTube Targeting + +**Custom intent audiences:** +- Based on recent search behavior +- Create from your converting keywords +- High intent, good for prospecting + +**In-market audiences:** +- People actively researching solutions +- Pre-built by Google +- Layer with demographics for precision + +**Affinity audiences:** +- Based on interests and habits +- Better for awareness +- Broad but can exclude irrelevant + +**Customer match:** +- Upload email lists +- Retarget existing customers +- Create lookalikes from best customers + +**Similar/lookalike audiences:** +- Based on your customer match lists +- Expand reach while maintaining relevance +- Best when source list is high-quality customers + +--- + +## Meta Audiences + +### Core Audiences (Interest/Demographic) + +**Interest targeting tips:** +- Layer interests with AND logic for precision +- Use Audience Insights to research interests +- Start broad, let algorithm optimize +- Exclude existing customers always + +**Demographic targeting:** +- Age and gender (if product-specific) +- Location (down to zip/postal code) +- Language +- Education and work (limited data now) + +**Behavior targeting:** +- Purchase behavior +- Device usage +- Travel patterns +- Life events + +### Custom Audiences + +**Website visitors:** +- All visitors (last 180 days max) +- Specific page visitors +- Time on site thresholds +- Frequency (visited X times) + +**Customer list:** +- Upload emails/phone numbers +- Match rate typically 30-70% +- Refresh regularly for accuracy + +**Engagement audiences:** +- Video viewers (25%, 50%, 75%, 95%) +- Page/profile engagers +- Form openers +- Instagram engagers + +**App activity:** +- App installers +- In-app events +- Purchase events + +### Lookalike Audiences + +**Source audience quality matters:** +- Use high-LTV customers, not all customers +- Purchasers > leads > all visitors +- Minimum 100 source users, ideally 1,000+ + +**Size recommendations:** +- 1% — most similar, smallest reach +- 1-3% — good balance for most +- 3-5% — broader, good for scale +- 5-10% — very broad, awareness only + +**Layering strategies:** +- Lookalike + interest = more precision early +- Test lookalike-only as you scale +- Exclude the source audience + +--- + +## LinkedIn Audiences + +### Job-Based Targeting + +**Job titles:** +- Be specific (CMO vs. "Marketing") +- LinkedIn normalizes titles, but verify +- Stack related titles +- Exclude irrelevant titles + +**Job functions:** +- Broader than titles +- Combine with seniority level +- Good for awareness campaigns + +**Seniority levels:** +- Entry, Senior, Manager, Director, VP, CXO, Partner +- Layer with function for precision + +**Skills:** +- Self-reported, less reliable +- Good for technical roles +- Use as expansion layer + +### Company-Based Targeting + +**Company size:** +- 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5000+ +- Key filter for B2B + +**Industry:** +- Based on company classification +- Can be broad, layer with other criteria + +**Company names (ABM):** +- Upload target account list +- Minimum 300 companies recommended +- Match rate varies + +**Company growth rate:** +- Hiring rapidly = budget available +- Good signal for timing + +### High-Performing Combinations + +| Use Case | Targeting Combination | +|----------|----------------------| +| Enterprise sales | Company size 1000+ + VP/CXO + Industry | +| SMB sales | Company size 11-200 + Manager/Director + Function | +| Developer tools | Skills + Job function + Company type | +| ABM campaigns | Company list + Decision-maker titles | +| Broad awareness | Industry + Seniority + Geography | + +--- + +## Twitter/X Audiences + +### Targeting options: +- Follower lookalikes (accounts similar to followers of X) +- Interest categories +- Keywords (in tweets) +- Conversation topics +- Events +- Tailored audiences (your lists) + +### Best practices: +- Follower lookalikes of relevant accounts work well +- Keyword targeting catches active conversations +- Lower CPMs than LinkedIn/Meta +- Less precise, better for awareness + +--- + +## TikTok Audiences + +### Targeting options: +- Demographics (age, gender, location) +- Interests (TikTok's categories) +- Behaviors (video interactions) +- Device (iOS/Android, connection type) +- Custom audiences (pixel, customer file) +- Lookalike audiences + +### Best practices: +- Younger skew (18-34 primarily) +- Interest targeting is broad +- Creative matters more than targeting +- Let algorithm optimize with broad targeting + +--- + +## Audience Size Guidelines + +| Platform | Minimum Recommended | Ideal Range | +|----------|-------------------|-------------| +| Google Search | 1,000+ searches/mo | 5,000-50,000 | +| Google Display | 100,000+ | 500K-5M | +| Meta | 100,000+ | 500K-10M | +| LinkedIn | 50,000+ | 100K-500K | +| Twitter/X | 50,000+ | 100K-1M | +| TikTok | 100,000+ | 1M+ | + +Too narrow = expensive, slow learning +Too broad = wasted spend, poor relevance + +--- + +## Exclusion Strategy + +Always exclude: +- Existing customers (unless upsell) +- Recent converters (7-14 days) +- Bounced visitors (<10 sec) +- Employees (by company or email list) +- Irrelevant page visitors (careers, support) +- Competitors (if identifiable) diff --git a/marketing-skill/paid-ads/references/platform-setup-checklists.md b/marketing-skill/paid-ads/references/platform-setup-checklists.md new file mode 100644 index 0000000..16fe2a8 --- /dev/null +++ b/marketing-skill/paid-ads/references/platform-setup-checklists.md @@ -0,0 +1,269 @@ +# Platform Setup Checklists + +Complete setup checklists for major ad platforms. + +## Google Ads Setup + +### Account Foundation + +- [ ] Google Ads account created and verified +- [ ] Billing information added +- [ ] Time zone and currency set correctly +- [ ] Account access granted to team members + +### Conversion Tracking + +- [ ] Google tag installed on all pages +- [ ] Conversion actions created (purchase, lead, signup) +- [ ] Conversion values assigned (if applicable) +- [ ] Enhanced conversions enabled +- [ ] Test conversions firing correctly +- [ ] Import conversions from GA4 (optional) + +### Analytics Integration + +- [ ] Google Analytics 4 linked +- [ ] Auto-tagging enabled +- [ ] GA4 audiences available in Google Ads +- [ ] Cross-domain tracking set up (if multiple domains) + +### Audience Setup + +- [ ] Remarketing tag verified +- [ ] Website visitor audiences created: + - All visitors (180 days) + - Key page visitors (pricing, demo, features) + - Converters (for exclusion) +- [ ] Customer match lists uploaded +- [ ] Similar audiences enabled + +### Campaign Readiness + +- [ ] Negative keyword lists created: + - Universal negatives (free, jobs, careers, reviews, complaints) + - Competitor negatives (if needed) + - Irrelevant industry terms +- [ ] Location targeting set (include/exclude) +- [ ] Language targeting set +- [ ] Ad schedule configured (if B2B, business hours) +- [ ] Device bid adjustments considered + +### Ad Extensions + +- [ ] Sitelinks (4-6 relevant pages) +- [ ] Callouts (key benefits, offers) +- [ ] Structured snippets (features, types, services) +- [ ] Call extension (if phone leads valuable) +- [ ] Lead form extension (if using) +- [ ] Price extensions (if applicable) +- [ ] Image extensions (where available) + +### Brand Protection + +- [ ] Brand campaign running (protect branded terms) +- [ ] Competitor campaigns considered +- [ ] Brand terms in negative lists for non-brand campaigns + +--- + +## Meta Ads Setup + +### Business Manager Foundation + +- [ ] Business Manager created +- [ ] Business verified (if running certain ad types) +- [ ] Ad account created within Business Manager +- [ ] Payment method added +- [ ] Team access configured with proper roles + +### Pixel & Tracking + +- [ ] Meta Pixel installed on all pages +- [ ] Standard events configured: + - PageView (automatic) + - ViewContent (product/feature pages) + - Lead (form submissions) + - Purchase (conversions) + - AddToCart (if e-commerce) + - InitiateCheckout (if e-commerce) +- [ ] Conversions API (CAPI) set up for server-side tracking +- [ ] Event Match Quality score > 6 +- [ ] Test events in Events Manager + +### Domain & Aggregated Events + +- [ ] Domain verified in Business Manager +- [ ] Aggregated Event Measurement configured +- [ ] Top 8 events prioritized in order of importance +- [ ] Web events prioritized for iOS 14+ tracking + +### Audience Setup + +- [ ] Custom audiences created: + - Website visitors (all, 30/60/90/180 days) + - Key page visitors + - Video viewers (25%, 50%, 75%, 95%) + - Page/Instagram engagers + - Customer list uploaded +- [ ] Lookalike audiences created (1%, 1-3%) +- [ ] Saved audiences for common targeting + +### Catalog (E-commerce) + +- [ ] Product catalog connected +- [ ] Product feed updating correctly +- [ ] Catalog sales campaigns enabled +- [ ] Dynamic product ads configured + +### Creative Assets + +- [ ] Images in correct sizes: + - Feed: 1080x1080 (1:1) + - Stories/Reels: 1080x1920 (9:16) + - Landscape: 1200x628 (1.91:1) +- [ ] Videos in correct formats +- [ ] Ad copy variations ready +- [ ] UTM parameters in all destination URLs + +### Compliance + +- [ ] Special Ad Categories declared (if housing, credit, employment, politics) +- [ ] Landing page complies with Meta policies +- [ ] No prohibited content in ads + +--- + +## LinkedIn Ads Setup + +### Campaign Manager Foundation + +- [ ] Campaign Manager account created +- [ ] Company Page connected +- [ ] Billing information added +- [ ] Team access configured + +### Insight Tag & Tracking + +- [ ] LinkedIn Insight Tag installed on all pages +- [ ] Tag verified and firing +- [ ] Conversion tracking configured: + - URL-based conversions + - Event-specific conversions +- [ ] Conversion values set (if applicable) + +### Audience Setup + +- [ ] Matched Audiences created: + - Website retargeting audiences + - Company list uploaded (for ABM) + - Contact list uploaded +- [ ] Lookalike audiences created +- [ ] Saved audiences for common targeting + +### Lead Gen Forms (if using) + +- [ ] Lead gen form templates created +- [ ] Form fields selected (minimize for conversion) +- [ ] Privacy policy URL added +- [ ] Thank you message configured +- [ ] CRM integration set up (or CSV export process) + +### Document Ads (if using) + +- [ ] Documents uploaded (PDF, PowerPoint) +- [ ] Gating configured (full gate or preview) +- [ ] Lead gen form connected + +### Creative Assets + +- [ ] Single image ads: 1200x627 (1.91:1) or 1080x1080 (1:1) +- [ ] Carousel images ready +- [ ] Video specs met (if using) +- [ ] Ad copy within character limits: + - Intro text: 600 max, 150 recommended + - Headline: 200 max, 70 recommended + +### Budget Considerations + +- [ ] Budget realistic for LinkedIn CPCs ($8-15+ typical) +- [ ] Audience size validated (50K+ recommended) +- [ ] Daily vs. lifetime budget decided +- [ ] Bid strategy selected + +--- + +## Twitter/X Ads Setup + +### Account Foundation + +- [ ] Ads account created +- [ ] Payment method added +- [ ] Account verified (if required) + +### Tracking + +- [ ] Twitter Pixel installed +- [ ] Conversion events created +- [ ] Website tag verified + +### Audience Setup + +- [ ] Tailored audiences created: + - Website visitors + - Customer lists +- [ ] Follower lookalikes identified +- [ ] Interest and keyword targets researched + +### Creative + +- [ ] Tweet copy within 280 characters +- [ ] Images: 1200x675 (1.91:1) or 1200x1200 (1:1) +- [ ] Video specs met (if using) +- [ ] Cards configured (website, app, etc.) + +--- + +## TikTok Ads Setup + +### Account Foundation + +- [ ] TikTok Ads Manager account created +- [ ] Business verification completed +- [ ] Payment method added + +### Pixel & Tracking + +- [ ] TikTok Pixel installed +- [ ] Events configured (ViewContent, Purchase, etc.) +- [ ] Events API set up (recommended) + +### Audience Setup + +- [ ] Custom audiences created +- [ ] Lookalike audiences created +- [ ] Interest categories identified + +### Creative + +- [ ] Vertical video (9:16) ready +- [ ] Native-feeling content (not too polished) +- [ ] First 3 seconds are compelling hooks +- [ ] Captions added (most watch without sound) +- [ ] Music/sounds selected (licensed if needed) + +--- + +## Universal Pre-Launch Checklist + +Before launching any campaign: + +- [ ] Conversion tracking tested with real conversion +- [ ] Landing page loads fast (<3 sec) +- [ ] Landing page mobile-friendly +- [ ] UTM parameters working +- [ ] Budget set correctly (daily vs. lifetime) +- [ ] Start/end dates correct +- [ ] Targeting matches intended audience +- [ ] Ad creative approved +- [ ] Team notified of launch +- [ ] Reporting dashboard ready diff --git a/marketing-skill/paid-ads/scripts/roas_calculator.py b/marketing-skill/paid-ads/scripts/roas_calculator.py new file mode 100755 index 0000000..8942a6a --- /dev/null +++ b/marketing-skill/paid-ads/scripts/roas_calculator.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python3 +""" +roas_calculator.py — ROAS and paid-ads metrics calculator +Usage: + python3 roas_calculator.py --spend 5000 --revenue 18000 --conversions 120 --leads 400 --margin 40 + python3 roas_calculator.py --file campaign.json + python3 roas_calculator.py --json # demo + JSON output + python3 roas_calculator.py # demo mode +""" + +import argparse +import json +import sys + + +# --------------------------------------------------------------------------- +# Calculation core +# --------------------------------------------------------------------------- + +def calculate(spend: float, revenue: float = 0.0, conversions: int = 0, + leads: int = 0, margin_pct: float = 0.0, + impressions: int = 0, clicks: int = 0) -> dict: + + results = { + "inputs": { + "ad_spend": spend, + "revenue": revenue, + "conversions": conversions, + "leads": leads, + "margin_pct": margin_pct, + "impressions": impressions, + "clicks": clicks, + } + } + + metrics = {} + + # --- ROAS --- + if revenue > 0 and spend > 0: + roas = revenue / spend + metrics["roas"] = { + "value": round(roas, 2), + "formula": "revenue / ad_spend", + "interpretation": _roas_label(roas), + } + + # --- Break-even ROAS --- + if margin_pct > 0: + be_roas = 100 / margin_pct + metrics["break_even_roas"] = { + "value": round(be_roas, 2), + "formula": "100 / margin_%", + "note": f"Need {be_roas:.1f}x ROAS to cover ad costs at {margin_pct}% margin", + } + if revenue > 0: + actual_roas = revenue / spend + profitable = actual_roas >= be_roas + metrics["profitability"] = { + "is_profitable": profitable, + "gap": round(actual_roas - be_roas, 2), + "note": "Profitable āœ…" if profitable else f"Unprofitable āŒ — need +{be_roas - actual_roas:.2f}x ROAS", + } + + # --- CPA --- + if conversions > 0 and spend > 0: + cpa = spend / conversions + metrics["cpa"] = { + "value": round(cpa, 2), + "formula": "ad_spend / conversions", + "unit": "cost per acquisition", + } + if revenue > 0: + rev_per_conversion = revenue / conversions + metrics["revenue_per_conversion"] = { + "value": round(rev_per_conversion, 2), + "roi_per_conversion": round((rev_per_conversion - cpa) / cpa * 100, 1), + } + + # --- CPL --- + if leads > 0 and spend > 0: + cpl = spend / leads + metrics["cpl"] = { + "value": round(cpl, 2), + "formula": "ad_spend / leads", + "unit": "cost per lead", + } + if conversions > 0: + lead_to_conv_rate = conversions / leads * 100 + metrics["lead_to_conversion_rate"] = { + "value": round(lead_to_conv_rate, 1), + "unit": "%", + } + + # --- Conversion rate --- + if clicks > 0 and conversions > 0: + cvr = conversions / clicks * 100 + metrics["conversion_rate"] = { + "value": round(cvr, 2), + "unit": "%", + "benchmark": "2-5% typical for paid search", + } + if clicks > 0 and leads > 0: + lcr = leads / clicks * 100 + metrics["lead_capture_rate"] = { + "value": round(lcr, 2), + "unit": "%", + } + + # --- CTR --- + if impressions > 0 and clicks > 0: + ctr = clicks / impressions * 100 + metrics["ctr"] = { + "value": round(ctr, 2), + "unit": "%", + "benchmark": "2-5% for search, 0.1-0.5% for display", + } + cpm = spend / impressions * 1000 + metrics["cpm"] = { + "value": round(cpm, 2), + "unit": "cost per 1000 impressions", + } + cpc = spend / clicks + metrics["cpc"] = { + "value": round(cpc, 2), + "unit": "cost per click", + } + + results["metrics"] = metrics + results["recommendations"] = _recommendations(metrics, spend, margin_pct) + return results + + +def _roas_label(roas: float) -> str: + if roas >= 8: + return "Excellent (8x+)" + if roas >= 5: + return "Strong (5-8x)" + if roas >= 3: + return "Good (3-5x)" + if roas >= 2: + return "Acceptable (2-3x) — check margins" + if roas >= 1: + return "Below target (<2x) — likely unprofitable" + return "Losing money (<1x)" + + +def _recommendations(metrics: dict, spend: float, margin_pct: float) -> list: + recs = [] + + roas = metrics.get("roas", {}).get("value") + be_roas = metrics.get("break_even_roas", {}).get("value") + + if roas and be_roas: + if roas < be_roas: + shortfall = round((be_roas - roas) * spend, 2) + recs.append(f"āš ļø Losing ${shortfall:,.2f}/period — pause or restructure campaign immediately") + elif roas < be_roas * 1.5: + recs.append("āš ļø Marginally profitable — optimize creatives and targeting before scaling") + else: + recs.append("āœ… Profitable — consider increasing budget or duplicating campaign") + + cpa = metrics.get("cpa", {}).get("value") + cpl = metrics.get("cpl", {}).get("value") + cvr = metrics.get("conversion_rate", {}).get("value") + + if cvr and cvr < 2: + recs.append(f"āš ļø CVR {cvr}% is low — test new landing pages, headlines, and CTAs") + elif cvr and cvr >= 5: + recs.append(f"āœ… Strong CVR {cvr}% — maximize traffic to this funnel") + + if cpa and cpl: + l2c = metrics.get("lead_to_conversion_rate", {}).get("value", 0) + if l2c < 10: + recs.append(f"āš ļø Lead-to-close rate {l2c}% is low — review sales qualification or nurture sequence") + + ctr = metrics.get("ctr", {}).get("value") + if ctr: + if ctr < 1: + recs.append(f"āš ļø CTR {ctr}% is low — refresh ad copy and audience targeting") + elif ctr >= 5: + recs.append(f"āœ… High CTR {ctr}% — strong creative, ensure LP matches ad message") + + if not recs: + recs.append("Add more data (margin %, impressions, leads) for actionable recommendations") + + return recs + + +# --------------------------------------------------------------------------- +# Demo data +# --------------------------------------------------------------------------- + +DEMO_DATA = { + "spend": 8500, + "revenue": 34200, + "conversions": 142, + "leads": 680, + "margin_pct": 35, + "impressions": 185000, + "clicks": 3700, +} + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="ROAS calculator — paid ads performance metrics and recommendations." + ) + parser.add_argument("--spend", type=float, help="Total ad spend ($)") + parser.add_argument("--revenue", type=float, default=0, help="Total attributed revenue ($)") + parser.add_argument("--conversions", type=int, default=0, help="Number of purchases/conversions") + parser.add_argument("--leads", type=int, default=0, help="Number of leads generated") + parser.add_argument("--margin", type=float, default=0, help="Gross margin %% (e.g. 40)") + parser.add_argument("--impressions", type=int, default=0, help="Total impressions") + parser.add_argument("--clicks", type=int, default=0, help="Total clicks") + parser.add_argument("--file", help="JSON file with campaign data") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r") as f: + data = json.load(f) + elif args.spend: + data = { + "spend": args.spend, + "revenue": args.revenue, + "conversions": args.conversions, + "leads": args.leads, + "margin_pct": args.margin, + "impressions": args.impressions, + "clicks": args.clicks, + } + else: + data = DEMO_DATA + if not args.json: + print("No input provided — running in demo mode.\n") + + result = calculate( + spend=data.get("spend", 0), + revenue=data.get("revenue", 0), + conversions=data.get("conversions", 0), + leads=data.get("leads", 0), + margin_pct=data.get("margin_pct", 0), + impressions=data.get("impressions", 0), + clicks=data.get("clicks", 0), + ) + + if args.json: + print(json.dumps(result, indent=2)) + return + + inp = result["inputs"] + metrics = result["metrics"] + recs = result["recommendations"] + + print("=" * 62) + print(" PAID ADS PERFORMANCE REPORT") + print("=" * 62) + print(f" Spend: ${inp['ad_spend']:>10,.2f}") + if inp["revenue"]: print(f" Revenue: ${inp['revenue']:>10,.2f}") + if inp["conversions"]:print(f" Conversions:{inp['conversions']:>10}") + if inp["leads"]: print(f" Leads: {inp['leads']:>10}") + if inp["impressions"]:print(f" Impressions:{inp['impressions']:>10,}") + if inp["clicks"]: print(f" Clicks: {inp['clicks']:>10,}") + + print() + print(" METRICS") + print(" " + "─" * 58) + + metric_labels = [ + ("roas", "ROAS", lambda m: f"{m['value']}x — {m['interpretation']}"), + ("break_even_roas", "Break-even ROAS", lambda m: f"{m['value']}x — {m['note']}"), + ("profitability", "Profitability", lambda m: m['note']), + ("cpa", "CPA", lambda m: f"${m['value']:,.2f} / {m['unit']}"), + ("revenue_per_conversion", "Rev/Conversion", lambda m: f"${m['value']:,.2f} (ROI {m['roi_per_conversion']}%)"), + ("cpl", "CPL", lambda m: f"${m['value']:,.2f} / {m['unit']}"), + ("lead_to_conversion_rate","Lead→Conv Rate", lambda m: f"{m['value']}%"), + ("conversion_rate", "Conversion Rate", lambda m: f"{m['value']}% ({m['benchmark']})"), + ("ctr", "CTR", lambda m: f"{m['value']}%"), + ("cpc", "CPC", lambda m: f"${m['value']:,.2f}"), + ("cpm", "CPM", lambda m: f"${m['value']:,.2f}"), + ] + + for key, label, fmt in metric_labels: + if key in metrics: + try: + detail = fmt(metrics[key]) + print(f" {label:<24} {detail}") + except Exception: + pass + + print() + print(" RECOMMENDATIONS") + print(" " + "─" * 58) + for rec in recs: + print(f" {rec}") + print("=" * 62) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/paywall-upgrade-cro/SKILL.md b/marketing-skill/paywall-upgrade-cro/SKILL.md new file mode 100644 index 0000000..d96dc10 --- /dev/null +++ b/marketing-skill/paywall-upgrade-cro/SKILL.md @@ -0,0 +1,260 @@ +--- +name: paywall-upgrade-cro +description: When the user wants to create or optimize in-app paywalls, upgrade screens, upsell modals, or feature gates. Also use when the user mentions "paywall," "upgrade screen," "upgrade modal," "upsell," "feature gate," "convert free to paid," "freemium conversion," "trial expiration screen," "limit reached screen," "plan upgrade prompt," or "in-app pricing." Distinct from public pricing pages (see page-cro) — this skill focuses on in-product upgrade moments where the user has already experienced value. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Paywall and Upgrade Screen CRO + +You are an expert in in-app paywalls and upgrade flows. Your goal is to convert free users to paid, or upgrade users to higher tiers, at moments when they've experienced enough value to justify the commitment. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, understand: + +1. **Upgrade Context** - Freemium → Paid? Trial → Paid? Tier upgrade? Feature upsell? Usage limit? + +2. **Product Model** - What's free? What's behind paywall? What triggers prompts? Current conversion rate? + +3. **User Journey** - When does this appear? What have they experienced? What are they trying to do? + +--- + +## Core Principles + +### 1. Value Before Ask +- User should have experienced real value first +- Upgrade should feel like natural next step +- Timing: After "aha moment," not before + +### 2. Show, Don't Just Tell +- Demonstrate the value of paid features +- Preview what they're missing +- Make the upgrade feel tangible + +### 3. Friction-Free Path +- Easy to upgrade when ready +- Don't make them hunt for pricing + +### 4. Respect the No +- Don't trap or pressure +- Make it easy to continue free +- Maintain trust for future conversion + +--- + +## Paywall Trigger Points + +### Feature Gates +When user clicks a paid-only feature: +- Clear explanation of why it's paid +- Show what the feature does +- Quick path to unlock +- Option to continue without + +### Usage Limits +When user hits a limit: +- Clear indication of limit reached +- Show what upgrading provides +- Don't block abruptly + +### Trial Expiration +When trial is ending: +- Early warnings (7, 3, 1 day) +- Clear "what happens" on expiration +- Summarize value received + +### Time-Based Prompts +After X days of free use: +- Gentle upgrade reminder +- Highlight unused paid features +- Easy to dismiss + +--- + +## Paywall Screen Components + +1. **Headline** - Focus on what they get: "Unlock [Feature] to [Benefit]" + +2. **Value Demonstration** - Preview, before/after, "With Pro you could..." + +3. **Feature Comparison** - Highlight key differences, current plan marked + +4. **Pricing** - Clear, simple, annual vs. monthly options + +5. **Social Proof** - Customer quotes, "X teams use this" + +6. **CTA** - Specific and value-oriented: "Start Getting [Benefit]" + +7. **Escape Hatch** - Clear "Not now" or "Continue with Free" + +--- + +## Specific Paywall Types + +### Feature Lock Paywall +``` +[Lock Icon] +This feature is available on Pro + +[Feature preview/screenshot] + +[Feature name] helps you [benefit]: +• [Capability] +• [Capability] + +[Upgrade to Pro - $X/mo] +[Maybe Later] +``` + +### Usage Limit Paywall +``` +You've reached your free limit + +[Progress bar at 100%] + +Free: 3 projects | Pro: Unlimited + +[Upgrade to Pro] [Delete a project] +``` + +### Trial Expiration Paywall +``` +Your trial ends in 3 days + +What you'll lose: +• [Feature used] +• [Data created] + +What you've accomplished: +• Created X projects + +[Continue with Pro] +[Remind me later] [Downgrade] +``` + +--- + +## Timing and Frequency + +### When to Show +- After value moment, before frustration +- After activation/aha moment +- When hitting genuine limits + +### When NOT to Show +- During onboarding (too early) +- When they're in a flow +- Repeatedly after dismissal + +### Frequency Rules +- Limit per session +- Cool-down after dismiss (days, not hours) +- Track annoyance signals + +--- + +## Upgrade Flow Optimization + +### From Paywall to Payment +- Minimize steps +- Keep in-context if possible +- Pre-fill known information + +### Post-Upgrade +- Immediate access to features +- Confirmation and receipt +- Guide to new features + +--- + +## A/B Testing + +### What to Test +- Trigger timing +- Headline/copy variations +- Price presentation +- Trial length +- Feature emphasis +- Design/layout + +### Metrics to Track +- Paywall impression rate +- Click-through to upgrade +- Completion rate +- Revenue per user +- Churn rate post-upgrade + +**For comprehensive experiment ideas**: See [references/experiments.md](references/experiments.md) + +--- + +## Anti-Patterns to Avoid + +### Dark Patterns +- Hiding the close button +- Confusing plan selection +- Guilt-trip copy + +### Conversion Killers +- Asking before value delivered +- Too frequent prompts +- Blocking critical flows +- Complicated upgrade process + +--- + +## Task-Specific Questions + +1. What's your current free → paid conversion rate? +2. What triggers upgrade prompts today? +3. What features are behind the paywall? +4. What's your "aha moment" for users? +5. What pricing model? (per seat, usage, flat) +6. Mobile app, web app, or both? + +--- + +## Related Skills + +- **page-cro** — WHEN the public-facing pricing page needs optimization (before users are in-app). NOT for in-product upgrade screens or feature gates. +- **onboarding-cro** — WHEN users haven't reached their activation moment and are hitting paywalls too early; fix onboarding first. NOT when value has already been delivered. +- **ab-test-setup** — WHEN running controlled experiments on paywall trigger timing, copy, pricing display, or layout. NOT for initial paywall design. +- **email-sequence** — WHEN setting up trial expiration or upgrade reminder email sequences to complement in-app prompts. NOT as a replacement for in-app paywall design. +- **marketing-context** — Foundation skill for understanding ICP, pricing model, and value proposition. Load before designing paywall copy and positioning. + +--- + +## Communication + +Paywall recommendations must account for where the user is in their value journey — always confirm whether the aha moment has been reached before recommending upgrade prompt placement. When writing paywall copy, deliver complete screen copy: headline, value statement, feature list, CTA, and escape hatch text. Flag dark patterns proactively and recommend ethical alternatives. Load `marketing-context` for pricing model and plan structure context before writing copy. + +--- + +## Proactive Triggers + +- User reports low free-to-paid conversion rate → ask where in the journey the paywall appears and whether the aha moment is reached first. +- User mentions users hitting limits and churning → distinguish between limit frustration (fix timing/messaging) vs. wrong ICP (fix acquisition). +- User asks about freemium model design → help define what's free vs. paid, then design paywall moments around natural value gaps. +- User shares a trial expiration screen → audit for dark patterns, missing escape hatches, and unclear value summarization. +- User mentions mobile app monetization → flag platform-specific considerations (App Store IAP rules, Google Play billing requirements). + +--- + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| Paywall Trigger Map | All paywall trigger points with timing rules, cooldown periods, and frequency caps | +| Full Paywall Screen Copy | Headline, value demonstration, feature comparison, CTA, and escape hatch for each paywall type | +| Upgrade Flow Diagram | Step-by-step from paywall click to post-upgrade confirmation with friction reduction notes | +| Anti-Pattern Audit | Review of existing paywall for dark patterns, trust-damaging copy, and conversion killers | +| A/B Test Backlog | Prioritized experiment ideas for trigger timing, copy, and pricing display | diff --git a/marketing-skill/popup-cro/SKILL.md b/marketing-skill/popup-cro/SKILL.md new file mode 100644 index 0000000..afd3b7b --- /dev/null +++ b/marketing-skill/popup-cro/SKILL.md @@ -0,0 +1,486 @@ +--- +name: popup-cro +description: When the user wants to create or optimize popups, modals, overlays, slide-ins, or banners for conversion purposes. Also use when the user mentions "exit intent," "popup conversions," "modal optimization," "lead capture popup," "email popup," "announcement banner," or "overlay." For forms outside of popups, see form-cro. For general page conversion optimization, see page-cro. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Popup CRO + +You are an expert in popup and modal optimization. Your goal is to create popups that convert without annoying users or damaging brand perception. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, understand: + +1. **Popup Purpose** + - Email/newsletter capture + - Lead magnet delivery + - Discount/promotion + - Announcement + - Exit intent save + - Feature promotion + - Feedback/survey + +2. **Current State** + - Existing popup performance? + - What triggers are used? + - User complaints or feedback? + - Mobile experience? + +3. **Traffic Context** + - Traffic sources (paid, organic, direct) + - New vs. returning visitors + - Page types where shown + +--- + +## Core Principles + +### 1. Timing Is Everything +- Too early = annoying interruption +- Too late = missed opportunity +- Right time = helpful offer at moment of need + +### 2. Value Must Be Obvious +- Clear, immediate benefit +- Relevant to page context +- Worth the interruption + +### 3. Respect the User +- Easy to dismiss +- Don't trap or trick +- Remember preferences +- Don't ruin the experience + +--- + +## Trigger Strategies + +### Time-Based +- **Not recommended**: "Show after 5 seconds" +- **Better**: "Show after 30-60 seconds" (proven engagement) +- Best for: General site visitors + +### Scroll-Based +- **Typical**: 25-50% scroll depth +- Indicates: Content engagement +- Best for: Blog posts, long-form content +- Example: "You're halfway through—get more like this" + +### Exit Intent +- Detects cursor moving to close/leave +- Last chance to capture value +- Best for: E-commerce, lead gen +- Mobile alternative: Back button or scroll up + +### Click-Triggered +- User initiates (clicks button/link) +- Zero annoyance factor +- Best for: Lead magnets, gated content, demos +- Example: "Download PDF" → Popup form + +### Page Count / Session-Based +- After visiting X pages +- Indicates research/comparison behavior +- Best for: Multi-page journeys +- Example: "Been comparing? Here's a summary..." + +### Behavior-Based +- Add to cart abandonment +- Pricing page visitors +- Repeat page visits +- Best for: High-intent segments + +--- + +## Popup Types + +### Email Capture Popup +**Goal**: Newsletter/list subscription + +**Best practices:** +- Clear value prop (not just "Subscribe") +- Specific benefit of subscribing +- Single field (email only) +- Consider incentive (discount, content) + +**Copy structure:** +- Headline: Benefit or curiosity hook +- Subhead: What they get, how often +- CTA: Specific action ("Get Weekly Tips") + +### Lead Magnet Popup +**Goal**: Exchange content for email + +**Best practices:** +- Show what they get (cover image, preview) +- Specific, tangible promise +- Minimal fields (email, maybe name) +- Instant delivery expectation + +### Discount/Promotion Popup +**Goal**: First purchase or conversion + +**Best practices:** +- Clear discount (10%, $20, free shipping) +- Deadline creates urgency +- Single use per visitor +- Easy to apply code + +### Exit Intent Popup +**Goal**: Last-chance conversion + +**Best practices:** +- Acknowledge they're leaving +- Different offer than entry popup +- Address common objections +- Final compelling reason to stay + +**Formats:** +- "Wait! Before you go..." +- "Forget something?" +- "Get 10% off your first order" +- "Questions? Chat with us" + +### Announcement Banner +**Goal**: Site-wide communication + +**Best practices:** +- Top of page (sticky or static) +- Single, clear message +- Dismissable +- Links to more info +- Time-limited (don't leave forever) + +### Slide-In +**Goal**: Less intrusive engagement + +**Best practices:** +- Enters from corner/bottom +- Doesn't block content +- Easy to dismiss or minimize +- Good for chat, support, secondary CTAs + +--- + +## Design Best Practices + +### Visual Hierarchy +1. Headline (largest, first seen) +2. Value prop/offer (clear benefit) +3. Form/CTA (obvious action) +4. Close option (easy to find) + +### Sizing +- Desktop: 400-600px wide typical +- Don't cover entire screen +- Mobile: Full-width bottom or center, not full-screen +- Leave space to close (visible X, click outside) + +### Close Button +- Always visible (top right is convention) +- Large enough to tap on mobile +- "No thanks" text link as alternative +- Click outside to close + +### Mobile Considerations +- Can't detect exit intent (use alternatives) +- Full-screen overlays feel aggressive +- Bottom slide-ups work well +- Larger touch targets +- Easy dismiss gestures + +### Imagery +- Product image or preview +- Face if relevant (increases trust) +- Minimal for speed +- Optional—copy can work alone + +--- + +## Copy Formulas + +### Headlines +- Benefit-driven: "Get [result] in [timeframe]" +- Question: "Want [desired outcome]?" +- Command: "Don't miss [thing]" +- Social proof: "Join [X] people who..." +- Curiosity: "The one thing [audience] always get wrong about [topic]" + +### Subheadlines +- Expand on the promise +- Address objection ("No spam, ever") +- Set expectations ("Weekly tips in 5 min") + +### CTA Buttons +- First person works: "Get My Discount" vs "Get Your Discount" +- Specific over generic: "Send Me the Guide" vs "Submit" +- Value-focused: "Claim My 10% Off" vs "Subscribe" + +### Decline Options +- Polite, not guilt-trippy +- "No thanks" / "Maybe later" / "I'm not interested" +- Avoid manipulative: "No, I don't want to save money" + +--- + +## Frequency and Rules + +### Frequency Capping +- Show maximum once per session +- Remember dismissals (cookie/localStorage) +- 7-30 days before showing again +- Respect user choice + +### Audience Targeting +- New vs. returning visitors (different needs) +- By traffic source (match ad message) +- By page type (context-relevant) +- Exclude converted users +- Exclude recently dismissed + +### Page Rules +- Exclude checkout/conversion flows +- Consider blog vs. product pages +- Match offer to page context + +--- + +## Compliance and Accessibility + +### GDPR/Privacy +- Clear consent language +- Link to privacy policy +- Don't pre-check opt-ins +- Honor unsubscribe/preferences + +### Accessibility +- Keyboard navigable (Tab, Enter, Esc) +- Focus trap while open +- Screen reader compatible +- Sufficient color contrast +- Don't rely on color alone + +### Google Guidelines +- Intrusive interstitials hurt SEO +- Mobile especially sensitive +- Allow: Cookie notices, age verification, reasonable banners +- Avoid: Full-screen before content on mobile + +--- + +## Measurement + +### Key Metrics +- **Impression rate**: Visitors who see popup +- **Conversion rate**: Impressions → Submissions +- **Close rate**: How many dismiss immediately +- **Engagement rate**: Interaction before close +- **Time to close**: How long before dismissing + +### What to Track +- Popup views +- Form focus +- Submission attempts +- Successful submissions +- Close button clicks +- Outside clicks +- Escape key + +### Benchmarks +- Email popup: 2-5% conversion typical +- Exit intent: 3-10% conversion +- Click-triggered: Higher (10%+, self-selected) + +--- + +## Output Format + +### Popup Design +- **Type**: Email capture, lead magnet, etc. +- **Trigger**: When it appears +- **Targeting**: Who sees it +- **Frequency**: How often shown +- **Copy**: Headline, subhead, CTA, decline +- **Design notes**: Layout, imagery, mobile + +### Multiple Popup Strategy +If recommending multiple popups: +- Popup 1: [Purpose, trigger, audience] +- Popup 2: [Purpose, trigger, audience] +- Conflict rules: How they don't overlap + +### Test Hypotheses +Ideas to A/B test with expected outcomes + +--- + +## Common Popup Strategies + +### E-commerce +1. Entry/scroll: First-purchase discount +2. Exit intent: Bigger discount or reminder +3. Cart abandonment: Complete your order + +### B2B SaaS +1. Click-triggered: Demo request, lead magnets +2. Scroll: Newsletter/blog subscription +3. Exit intent: Trial reminder or content offer + +### Content/Media +1. Scroll-based: Newsletter after engagement +2. Page count: Subscribe after multiple visits +3. Exit intent: Don't miss future content + +### Lead Generation +1. Time-delayed: General list building +2. Click-triggered: Specific lead magnets +3. Exit intent: Final capture attempt + +--- + +## Experiment Ideas + +### Placement & Format Experiments + +**Banner Variations** +- Top bar vs. banner below header +- Sticky banner vs. static banner +- Full-width vs. contained banner +- Banner with countdown timer vs. without + +**Popup Formats** +- Center modal vs. slide-in from corner +- Full-screen overlay vs. smaller modal +- Bottom bar vs. corner popup +- Top announcements vs. bottom slideouts + +**Position Testing** +- Test popup sizes on desktop and mobile +- Left corner vs. right corner for slide-ins +- Test visibility without blocking content + +--- + +### Trigger Experiments + +**Timing Triggers** +- Exit intent vs. 30-second delay vs. 50% scroll depth +- Test optimal time delay (10s vs. 30s vs. 60s) +- Test scroll depth percentage (25% vs. 50% vs. 75%) +- Page count trigger (show after X pages viewed) + +**Behavior Triggers** +- Show based on user intent prediction +- Trigger based on specific page visits +- Return visitor vs. new visitor targeting +- Show based on referral source + +**Click Triggers** +- Click-triggered popups for lead magnets +- Button-triggered vs. link-triggered modals +- Test in-content triggers vs. sidebar triggers + +--- + +### Messaging & Content Experiments + +**Headlines & Copy** +- Test attention-grabbing vs. informational headlines +- "Limited-time offer" vs. "New feature alert" messaging +- Urgency-focused copy vs. value-focused copy +- Test headline length and specificity + +**CTAs** +- CTA button text variations +- Button color testing for contrast +- Primary + secondary CTA vs. single CTA +- Test decline text (friendly vs. neutral) + +**Visual Content** +- Add countdown timers to create urgency +- Test with/without images +- Product preview vs. generic imagery +- Include social proof in popup + +--- + +### Personalization Experiments + +**Dynamic Content** +- Personalize popup based on visitor data +- Show industry-specific content +- Tailor content based on pages visited +- Use progressive profiling (ask more over time) + +**Audience Targeting** +- New vs. returning visitor messaging +- Segment by traffic source +- Target based on engagement level +- Exclude already-converted visitors + +--- + +### Frequency & Rules Experiments + +- Test frequency capping (once per session vs. once per week) +- Cool-down period after dismissal +- Test different dismiss behaviors +- Show escalating offers over multiple visits + +--- + +## Task-Specific Questions + +1. What's the primary goal for this popup? +2. What's your current popup performance (if any)? +3. What traffic sources are you optimizing for? +4. What incentive can you offer? +5. Are there compliance requirements (GDPR, etc.)? +6. Mobile vs. desktop traffic split? + +--- + +## Related Skills + +- **form-cro** — WHEN the form inside the popup needs deep optimization (field count, validation, error states). NOT for the popup trigger, design, or copy. +- **page-cro** — WHEN the surrounding page context needs conversion optimization and the popup is just one element. NOT when the popup is the sole focus. +- **onboarding-cro** — WHEN popups or modals are part of in-app onboarding flows (tooltips, checklists, feature announcements). NOT for external marketing site popups. +- **email-sequence** — WHEN setting up the nurture or welcome sequence that fires after a popup lead capture. NOT for the popup itself. +- **ab-test-setup** — WHEN running split tests on popup trigger timing, copy, or design. NOT for initial strategy or design ideation. + +--- + +## Communication + +Deliver popup recommendations with specificity: name the trigger type, target audience segment, and frequency rule for every popup proposed. When writing copy, provide headline, subhead, CTA button text, and decline text as a complete set — never partial. Reference compliance requirements (GDPR, Google intrusive interstitials policy) proactively when relevant. Load `marketing-context` for brand voice and ICP alignment before writing copy. + +--- + +## Proactive Triggers + +- User mentions low email list growth or lead capture → ask about current popup strategy before recommending new channels. +- User reports high bounce rate on blog or landing page → suggest exit-intent popup as a low-friction capture mechanism. +- User is running paid traffic → recommend behavior-based or source-matched popup targeting to improve ROAS. +- User mentions GDPR or compliance concerns → proactively cover consent, opt-in mechanics, and Google's intrusive interstitials policy. +- User asks about increasing free trial signups → recommend click-triggered or scroll-depth popup on pricing/features pages before assuming acquisition is the bottleneck. + +--- + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| Popup Strategy Map | Full popup inventory: type, trigger, audience segment, frequency rules, and conflict resolution | +| Complete Popup Copy Set | Headline, subhead, CTA button, decline text, and preview text for each popup | +| Mobile Adaptation Notes | Specific adjustments for mobile trigger, sizing, and dismiss behavior | +| Compliance Checklist | GDPR consent language, privacy link placement, opt-in mechanic review | +| A/B Test Plan | Prioritized hypotheses with expected lift and success metrics | diff --git a/marketing-skill/pricing-strategy/SKILL.md b/marketing-skill/pricing-strategy/SKILL.md new file mode 100644 index 0000000..01e1519 --- /dev/null +++ b/marketing-skill/pricing-strategy/SKILL.md @@ -0,0 +1,323 @@ +--- +name: pricing-strategy +description: "Design, optimize, and communicate SaaS pricing — tier structure, value metrics, pricing pages, and price increase strategy. Use when building a pricing model from scratch, redesigning existing pricing, planning a price increase, or improving a pricing page. Trigger keywords: pricing tiers, pricing page, price increase, packaging, value metric, per seat pricing, usage-based pricing, freemium, good-better-best, pricing strategy, monetization, pricing page conversion, Van Westendorp. NOT for broader product strategy — use product-strategist for that. NOT for customer success or renewals — use customer-success-manager for expansion revenue." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Pricing Strategy + +You are an expert in SaaS pricing and monetization. Your goal is to design pricing that captures the value you deliver, converts at a healthy rate, and scales with your customers. + +Pricing is not math — it's positioning. The right price isn't the one that covers costs + margin. It's the one that sits between what your next-best alternative costs and what your customers believe they get in return. Most SaaS products are underpriced. This skill is about fixing that, clearly and defensibly. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for what's missing. + +Gather this context: + +### 1. Current State +- Do you have pricing today? If so: what plans, what price points, what's the billing model? +- What's your conversion rate from trial/free to paid? (If known) +- What's your average revenue per customer? +- What's your monthly churn rate? + +### 2. Business Context +- Product type: B2B or B2C? Self-serve or sales-assisted? +- Customer segments: who are your best customers vs. casual users? +- Competitors: who do customers compare you to, and what do those cost? +- Cost structure: what does serving one customer cost you per month? + +### 3. Goals +- Are you designing, optimizing, or planning a price increase? +- Any constraints? (e.g., grandfathered customers, contractual limits, channel partner margins) + +## How This Skill Works + +### Mode 1: Design Pricing From Scratch +Starting without a pricing model, or rebuilding entirely. We'll work through value metric selection, tier structure, price point research, and pricing page design. + +### Mode 2: Optimize Existing Pricing +Pricing exists but conversion is low, expansion is flat, or customers feel mispriced. We'll audit what's there, benchmark, and identify specific improvements. + +### Mode 3: Plan a Price Increase +Prices need to go up — because of inflation, value improvements, or market repositioning. We'll design a strategy that increases revenue without burning customers. + +--- + +## The Three Pricing Axes + +Every pricing decision lives across three axes. Get all three right. + +``` + ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” + │ PACKAGING │ What's in each tier? + │ (what you get) │ + ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ + │ + ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” + │ VALUE METRIC │ What do you charge for? + │ (how it scales) │ + ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ + │ + ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” + │ PRICE POINT │ How much? + │ (the number) │ + ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ +``` + +Most teams skip straight to price point. That's backwards. Lock in the metric first, then packaging, then test the number. + +--- + +## Value Metric Selection + +Your value metric determines how pricing scales with customer value. Choose wrong and you either leave money on the table or create friction that kills growth. + +### Common Value Metrics for SaaS + +| Metric | Best For | Example | +|--------|---------|---------| +| **Per seat / user** | Collaboration tools, CRMs | Salesforce, Notion, Linear | +| **Per usage** | API tools, infrastructure, AI | Stripe, Twilio, OpenAI | +| **Per feature** | Platform plays, add-ons | Intercom, HubSpot | +| **Flat fee** | Unlimited-feel, SMB tools | Basecamp, Calendly Basic | +| **Per outcome** | High-value, measurable ROI | Commission-based tools | +| **Hybrid** | Mix of above | Most mature SaaS | + +### How to Choose + +Answer these questions: + +1. **What makes a customer willing to pay more?** → That's your value metric +2. **Does the metric scale with their success?** → If they grow, you grow +3. **Is it easy to understand?** → Complexity kills conversion +4. **Is it hard to game?** → Customers shouldn't be able to work around it + +**Red flags:** +- "Per seat" in a tool where one power user does all the work → seats don't scale with value +- "Flat fee" when some customers derive 10x the value of others → you're subsidizing heavy users +- "Per API call" when call count varies wildly week to week → unpredictable bills = churn + +--- + +## Good-Better-Best Tier Structure + +Three tiers is the standard. Not because of tradition — because it anchors perception. + +### Tier Design Principles + +**Entry tier (Good):** +- Captures the segment that will churn if priced higher +- Limited — either by features, usage, or support +- NOT free. Free is a separate strategy (freemium), not a tier. +- Should cover your costs at minimum + +**Middle tier (Better) — your default:** +- This is where you push most customers +- Price: 2-3x the entry tier +- Features: everything a growing company needs +- Call it out visually as recommended + +**Top tier (Best):** +- For high-value customers with enterprise needs +- May be "Contact us" or custom pricing +- Unlocks: SSO, audit logs, SLA, dedicated support, custom contracts +- If you have enterprise deals >$1k MRR, this tier exists to capture them + +### What Goes in Each Tier + +| Feature Category | Entry | Better | Best | +|----------------|-------|--------|------| +| Core product | āœ… (limited) | āœ… (full) | āœ… (full) | +| Usage limits | Low | Medium | High / unlimited | +| Users/seats | 1-3 | 5-unlimited | Unlimited | +| Integrations | Basic | Full | Full + custom | +| Reporting | Basic | Advanced | Custom | +| Support | Email | Priority | Dedicated CSM | +| Admin features | — | — | SSO, audit log, SCIM | +| SLA | — | — | āœ… | + +See [references/pricing-models.md](references/pricing-models.md) for model deep dives and SaaS examples. + +--- + +## Value-Based Pricing + +Price between the next-best alternative and your perceived value. + +``` +[Cost of doing nothing] ... [Next-best alternative] ... [YOUR PRICE] ... [Perceived value delivered] +``` + +**Step 1: Define the next-best alternative** +- What would the customer do if your product didn't exist? +- A competitor? A spreadsheet? Manual process? Hiring someone? +- What does that cost them? + +**Step 2: Estimate value delivered** +- Time saved Ɨ hourly rate of the person using it +- Revenue generated or protected +- Cost of error/risk avoided +- Ask your best customers: "What would you lose if you stopped using us tomorrow?" + +**Step 3: Price in the middle** +- A rough heuristic: price at 10-20% of documented value delivered +- Don't price at 50% of value — customers feel they're overpaying +- Don't price below the next-best alternative — signals you don't believe in your own product + +**Conversion rate as a signal:** +- >40% trial-to-paid: likely underpriced — test a price increase +- 15-30%: healthy for most SaaS +- <10%: pricing may be high, or trial-to-paid funnel has friction + +--- + +## Pricing Research Methods + +### Van Westendorp Price Sensitivity Meter + +Four questions, asked to current customers or target segment: + +1. At what price would this product be so cheap you'd question its quality? +2. At what price would this product be a bargain — great deal? +3. At what price would this product start to feel expensive — still acceptable? +4. At what price would this product be too expensive to consider? + +**Interpret the results:** Plot the four curves. The intersection of "too cheap" and "too expensive" gives your acceptable price range. The intersection of "bargain" and "expensive" gives the optimal price point. + +**When to use:** B2B SaaS, n≄30 respondents, existing customers or qualified prospects. + +### MaxDiff Analysis + +Show respondents sets of features/prices and ask which they value most and least. Statistical analysis reveals relative value of each feature — informs packaging more than price point. + +**When to use:** When deciding which features to put in which tier. + +### Competitor Benchmarking + +| Step | What to Do | +|------|-----------| +| 1 | List direct competitors and alternatives customers consider | +| 2 | Record their published pricing (plan names, prices, value metrics) | +| 3 | Note what's included at each price point | +| 4 | Identify where your product over- and under-delivers vs. each | +| 5 | Price relative to positioning: premium = 20-40% above market, value = at or below | + +**Don't just copy competitor prices** — their pricing reflects their cost structure and positioning, not yours. + +--- + +## Price Increase Strategies + +Raising prices is one of the highest-ROI moves available to SaaS companies. Most wait too long. + +### Strategy Selection + +| Strategy | Use When | Risk | +|---------|---------|------| +| **New customers only** | Significant pushback expected | Low — doesn't touch existing base | +| **Grandfather + delayed** | Loyal customer base, contract risk | Medium — existing customers feel respected | +| **Tied to value delivery** | Clear new features/improvement | Low — justifiable | +| **Plan restructure** | Significant packaging change | Medium — complexity for customers | +| **Uniform increase** | Confident in value, price is clearly below market | Medium-High | + +### Execution Checklist + +1. **Quantify the move:** Calculate new MRR at 100%, 80%, 70% retention of existing customers +2. **Segment by risk:** Annual contracts, champions vs. detractors, usage-based at-risk accounts +3. **Set the date:** 60-90 days notice for existing customers. 30 days minimum. +4. **Communicate the reason:** New features, rising costs, investment in [X] — be specific +5. **Offer a path:** Lock in current price for annual commitment, or give a 3-month window +6. **Arm your CS team:** FAQ, talking points, approved offer authority +7. **Monitor for 60 days:** Churn rate, downgrade rate, support ticket volume + +**Expected churn from a 20-30% price increase:** 5-15%. If your net revenue impact is positive, proceed. + +--- + +## Pricing Page Design + +The pricing page converts intent to purchase. Design it with that job in mind. + +### Above the Fold + +Must have: +- Plan names (simple: Starter / Pro / Enterprise, or named after customer segment) +- Price with billing toggle (monthly/annual — annual should show savings) +- 3-5 bullet differentiators per plan +- CTA button per plan +- "Most popular" badge on recommended tier + +### Below the Fold + +- **Full feature comparison table** — comprehensive, scannable, uses āœ… and āŒ not walls of text +- **FAQ section** — address the 5 objections that stop people from buying: + - "Can I cancel anytime?" + - "What happens when I hit limits?" + - "Do you offer refunds?" + - "Is my data secure?" + - "What if I need to upgrade/downgrade?" +- **Social proof** — logos, quotes, or case studies relevant to each tier +- **Security badges** if B2B enterprise (SOC2, ISO 27001, GDPR) + +### Annual vs. Monthly Toggle + +- Show annual pricing by default (or highlight it) — it improves LTV +- Show savings explicitly: "Save 20%" or "2 months free" +- Don't hide the monthly price — hiding it builds distrust + +See [references/pricing-page-playbook.md](references/pricing-page-playbook.md) for design specs and copy templates. + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Conversion rate >40% trial-to-paid** → Strong signal of underpricing. Flag: test 20-30% price increase. +- **All customers on the middle tier** → No upsell path. Flag: enterprise tier needed or feature lock-in missing. +- **Customer asked for features that aren't in their tier** → Expansion revenue being left on the table. Flag: feature gatekeeping review. +- **Churn rate >5% monthly** → Before raising prices, fix churn. Price increases accelerate churners. +- **Price hasn't changed in 2+ years** → Inflation alone justifies 10-15% increase. Flag for strategic review. +- **Only one pricing option** → No anchoring, no upsell. Flag: add a third tier even if rarely purchased. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|--------------------|-----------| +| "Design pricing" | Three-tier structure with value metric, feature grid, price points, and rationale | +| "Audit my pricing" | Pricing scorecard (0-100), conversion rate benchmarks, gap analysis, quick wins | +| "Plan a price increase" | Increase strategy selection, communication templates, risk model, 90-day rollout plan | +| "Design a pricing page" | Above-fold layout spec, feature comparison table structure, CTA copy, FAQ copy | +| "Research pricing" | Van Westendorp survey questions + MaxDiff framework for your specific product | +| "Model pricing scenarios" | Run `scripts/pricing_modeler.py` with your inputs | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — recommendation before justification +- **What + Why + How** — every recommendation has all three +- **Actions have owners and deadlines** — no vague "consider" +- **Confidence tagging** — 🟢 verified benchmark / 🟔 estimated / šŸ”“ assumed + +--- + +## Related Skills + +- **product-strategist**: Use for product roadmap and broader monetization strategy. NOT for pricing page or price increase execution. +- **copywriting**: Use for pricing page copy polish. NOT for pricing structure or tier design. +- **churn-prevention**: Use when churn is the underlying issue — fix retention before raising prices. +- **ab-test-setup**: Use to A/B test price points or pricing page layouts after initial design. +- **customer-success-manager**: Use for expansion revenue through upselling. NOT for pricing design or packaging. +- **competitor-alternatives**: Use for competitive comparison pages that complement pricing pages. diff --git a/marketing-skill/pricing-strategy/references/pricing-models.md b/marketing-skill/pricing-strategy/references/pricing-models.md new file mode 100644 index 0000000..00fdc56 --- /dev/null +++ b/marketing-skill/pricing-strategy/references/pricing-models.md @@ -0,0 +1,194 @@ +# Pricing Models — Deep Dive + +Comprehensive reference for SaaS pricing models with real-world examples and when to use each. + +--- + +## Model 1: Per-Seat / Per-User + +**How it works:** Price is multiplied by the number of users who access the product. + +**Best for:** +- Collaboration tools where more users = more value +- CRMs where every sales rep needs access +- Tools where the organization is the buyer and seats map to headcount + +**Examples:** Salesforce ($25-300/seat/mo), Linear ($8/seat/mo), Figma ($12/seat/mo), Notion ($8/seat/mo) + +**Expansion mechanics:** Automatic as companies hire. No upsell conversation needed — new hire gets a seat, revenue grows. + +**Failure modes:** +- Single-power-user tools (one person does all the work, team just views results) → seat pricing punishes the customer for your product's design +- Tools used by contractors or external stakeholders → billing becomes a negotiation +- Products where sharing credentials is easy and enforcement is hard + +**Seat pricing variants:** + +| Variant | Description | Example | +|---------|-------------|---------| +| Named seat | Specific user assigned to each license | Salesforce | +| Concurrent seat | N users can be logged in simultaneously | Legacy enterprise software | +| Creator/viewer split | Creators pay, viewers free or low-cost | Figma, Miro | +| Minimum seat count | Plan requires minimum X seats | Most enterprise deals | + +**Tip:** Creator/viewer pricing is powerful for B2B tools where one team creates and dozens consume. It drives virality (free viewers) while capturing revenue from actual users. + +--- + +## Model 2: Usage-Based (Consumption) + +**How it works:** Customer pays for what they use — API calls, storage, compute, messages sent, emails delivered. + +**Best for:** +- Infrastructure and developer tools +- AI/ML tools where compute cost scales with usage +- Communication platforms (email, SMS, video) +- Products where usage is highly variable across customers + +**Examples:** Stripe (2.9% + $0.30/transaction), Twilio ($0.0075/SMS), AWS (varies), OpenAI ($0.002-0.06/1K tokens) + +**Expansion mechanics:** Natural — as customer grows, their usage grows, revenue grows without any action. Best CAC:LTV dynamics in SaaS. + +**Failure modes:** +- Unpredictable bills → customers cap usage to avoid overages → you've engineered your own ceiling +- High churn during market downturns → when usage drops, revenue drops +- Hard to forecast for both you and the customer + +**Usage pricing variants:** + +| Variant | Description | Example | +|---------|-------------|---------| +| Pure consumption | Pay only for what you use | AWS Lambda | +| Prepaid credits | Buy credits, consume at your pace | OpenAI, Resend | +| Committed use + overage | Flat fee with usage ceiling, then per-unit | Stripe, Twilio volume | +| Tiered usage | Lower per-unit price at higher volumes | Mailchimp email tiers | + +**Hybrid approach:** Most mature usage-based companies add a platform fee (small flat monthly charge) to ensure revenue floor and reduce churn from low-usage months. + +--- + +## Model 3: Feature-Based (Tiered Flat Fee) + +**How it works:** Different bundles of features at different flat price points. The Good-Better-Best model. + +**Best for:** +- Products with clear feature differentiation between customer segments +- Markets where predictable spend matters (CFOs love this) +- SMB-to-enterprise products where enterprise features are genuinely different + +**Examples:** HubSpot (Starter/Professional/Enterprise), Intercom (Starter/Pro/Premium), most SaaS + +**Expansion mechanics:** Requires upsell motion — customer has to outgrow a tier and move up. Less automatic than usage-based but more predictable. + +**Failure modes:** +- Feature tiers that don't match actual customer needs → customers cluster in one tier, none move +- Enterprise features that aren't compelling enough to justify the jump → stuck mid-market +- Too many tiers → analysis paralysis + +--- + +## Model 4: Flat Fee + +**How it works:** One price, everything included, unlimited use. + +**Best for:** +- Small tools with predictable cost structure +- Markets where simplicity is the differentiator +- Products where usage genuinely doesn't vary much + +**Examples:** Basecamp ($99/mo flat), Transistor.fm (by podcast, not listeners), Calendly Basic + +**Expansion mechanics:** None. You need a premium tier or add-ons, or you're relying purely on new customer acquisition. + +**Failure modes:** +- Heavy users subsidized by light users → heavy users stay forever, light users churn → adverse selection +- No path to grow revenue with existing customers → stuck unless you add tiers or raise prices + +**When flat fee works:** When your cost to serve is genuinely flat, or when market positioning around simplicity is worth more than the revenue you'd capture with usage-based pricing. + +--- + +## Model 5: Freemium + +**Note:** Freemium is an acquisition strategy, not a pricing model. It's compatible with any of the above. + +**How it works:** Free tier with limited functionality, paid tiers above. + +**Best for:** +- Developer tools (PLG) +- Collaboration tools that spread virally +- Products where network effects increase value with more users + +**Examples:** Slack, Notion, Figma, GitHub, Airtable + +**The freemium math:** +- Free users cost money to serve +- You need paid conversion rate high enough to cover free users +- Rule of thumb: 2-5% free-to-paid conversion is viable at scale, 1-2% usually isn't + +**Free vs. trial vs. freemium:** + +| Model | Description | Best For | +|-------|-------------|---------| +| Free forever tier | Permanently limited free plan | PLG, viral loops | +| Time-limited trial | Full access for 14-30 days | Sales-assisted, complex products | +| Usage-limited trial | Full access until limit hit | Developer tools, AI | +| Freemium | Permanently limited, upsell to paid | Bottoms-up enterprise | + +--- + +## Model 6: Hybrid Pricing + +Most mature SaaS companies end up with hybrid pricing. Common combinations: + +| Combination | Example | +|------------|---------| +| Platform fee + per seat | Base access + user licenses | +| Platform fee + usage | Monthly minimum + overage | +| Feature tiers + usage | Plan determines included usage, overage above | +| Per seat + usage | Seat license + volume pricing for heavy users | + +**When to go hybrid:** +- You have both fixed infrastructure costs and variable serving costs +- You want revenue floors (platform fee) + upside (usage) +- Different customer segments have very different value profiles + +--- + +## Pricing Model Selection Framework + +Answer these questions to identify the right model: + +**1. Does value scale with users?** +- Yes, linearly → per-seat +- Yes, but not linearly → creator/viewer or per-seat with role tiers + +**2. Does value scale with usage?** +- Yes, measurably → usage-based +- Yes, but usage is hard to measure → feature tiers with usage caps + +**3. Is your customer a small business wanting simplicity?** +- Yes → flat fee or simple 2-3 tier feature pricing +- No → skip flat fee, go feature or usage-based + +**4. Do you have enterprise customers with governance/compliance needs?** +- Yes → enterprise tier required (even if "Contact us") +- No → three tiers max + +**5. Is this a developer/technical product?** +- Yes → usage-based or consumption with free tier is the market norm +- No → feature tiers with flat fee is more accessible + +--- + +## Pricing Model Benchmarks + +| Metric | Early Stage | Growth | Scale | +|--------|------------|--------|-------| +| **Trial-to-paid rate** | 15-25% | 20-35% | 25-40% | +| **Annual vs monthly mix** | 30-50% annual | 40-60% annual | 50-70% annual | +| **Expansion revenue** | 0-10% of MRR | 10-20% | 20-40% | +| **Price increase frequency** | Ad hoc | Annually | Annually | +| **Churn rate (monthly)** | 2-8% | 1-4% | 0.5-2% | + +**The LTV:CAC rule:** LTV should be ≄3x CAC. If it's below 3x, pricing or retention (or both) needs fixing. diff --git a/marketing-skill/pricing-strategy/references/pricing-page-playbook.md b/marketing-skill/pricing-strategy/references/pricing-page-playbook.md new file mode 100644 index 0000000..ee6d99c --- /dev/null +++ b/marketing-skill/pricing-strategy/references/pricing-page-playbook.md @@ -0,0 +1,221 @@ +# Pricing Page Playbook + +Design specs, copy frameworks, and conversion tactics for SaaS pricing pages. + +--- + +## What a Pricing Page Actually Has to Do + +One job: get the right customer to click the right plan's CTA. Everything on the page should serve that job or get removed. + +The visitor landing on your pricing page has already decided they're interested. They're now asking: +1. "Which plan is for me?" +2. "Is it worth the price?" +3. "What's the catch?" + +Your page answers those three questions, in that order. + +--- + +## Page Structure (Scroll Order) + +### Above the Fold + +**Billing toggle (monthly/annual)** +- Default to annual if annual is your preference (most conversions happen here) +- Show savings clearly: "Save 20%" badge, not just the math +- Position toggle at the top, before plan cards + +**Plan cards (3-column)** +``` +ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” +│ Starter │ Pro │ Enterprise │ +│ │ ā˜… Popular │ │ +│ $29/mo │ $99/mo │ Custom │ +│ │ │ │ +│ For small │ For growing │ For teams │ +│ teams │ teams │ needing │ +│ │ │ control │ +│ • Feature │ • Feature │ • Feature │ +│ • Feature │ • Feature │ • Feature │ +│ • Feature │ • Feature │ • Feature │ +│ │ │ │ +│ [Start free]│[Start free] │[Contact us] │ +ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ +``` + +**Each plan card must include:** +- Plan name (customer-segment-oriented, not just "Basic/Pro") +- Price (with billing period and per-seat notation if applicable) +- 1-line positioning sentence ("For growing teams who need X") +- 4-6 bullet differentiators (what they get at this tier) +- CTA button (clear, action-oriented — not just "Sign Up") +- "Most popular" / "Recommended" badge on middle tier + +### Below the Fold + +**Full Feature Comparison Table** +- Exhaustive list of all features +- Group by category: Core, Collaboration, Analytics, Admin, Support +- Use āœ… / āŒ or checkmarks/dashes — no conditional language +- Sticky header so plan names stay visible while scrolling +- Make this scannable, not a wall of text + +**Social Proof Section** +- 3 customer quotes relevant to each tier if possible +- Company logos of recognizable customers +- Stats if they're real: "Trusted by 10,000+ teams" + +**FAQ Section (5-7 questions)** + +Non-negotiable FAQs: +1. "Can I cancel anytime?" → Yes. Cancel from settings. No calls required. +2. "What happens at the end of my trial?" → We'll ask if you want to continue. +3. "Can I switch plans?" → Yes, upgrade or downgrade anytime. Prorated billing. +4. "What payment methods do you accept?" → Credit card, invoice for annual enterprise. +5. "Is my data secure?" → SOC 2 Type II / ISO 27001 / brief security statement. +6. "What if I need more than the top plan offers?" → Talk to us: [link to enterprise form]. + +**Enterprise Call-to-Action** +- Separate row or section below cards +- "Need custom pricing or a demo?" → [Talk to Sales] button +- Who it's for: teams over X seats, specific compliance needs, custom contracts + +--- + +## Copy Frameworks + +### Plan Names + +Avoid generic names if possible. Named plans anchor to identity, not just price. + +| Generic | Better | Why | +|---------|--------|-----| +| Free / Basic / Pro | Solo / Studio / Agency | Maps to customer segment | +| Starter / Growth / Enterprise | Developer / Team / Business | Maps to use case | +| Individual / Team / Organization | Creator / Collaborator / Company | Maps to role | + +If your categories are genuinely vague, stick with simple names. Don't force creative names that confuse. + +### CTA Copy + +Match the CTA to the ask: + +| Context | CTA | +|---------|-----| +| Has a free trial | "Start free trial" | +| Freemium | "Get started free" | +| No trial, direct purchase | "Get [Plan Name]" | +| Enterprise / contact sales | "Talk to us" or "Get a demo" | +| Annual commitment, high price | "Schedule a call" | + +Avoid: +- "Sign Up" — generic, no value +- "Subscribe" — sounds like a newsletter +- "Buy Now" — transactional, not benefit-oriented +- "Learn More" — on a pricing page, this is a dead end + +### Pricing Display + +| Scenario | How to Show It | +|----------|---------------| +| Monthly pricing | "$99/month" | +| Annual pricing, billed monthly | "$83/month, billed annually" | +| Annual pricing, billed upfront | "$996/year" with "/mo equivalent" note | +| Per-seat | "$15/user/month" | +| Usage-based | "From $0.002 per call" | +| Enterprise | "Custom" or "Starting at $X" | + +Always show annual savings as a percentage OR dollar amount (whichever is larger visually). + +--- + +## Conversion Tactics + +### Anchoring + +**Price anchoring:** The first number shown sets the reference frame. If you show a $500/month plan first, $99 feels cheap. + +If you want to push the middle tier: +- Show plans left-to-right: Premium → Pro (recommended) → Starter +- OR highlight the middle tier with visual treatment (larger card, border, color) +- The eye goes to the visually differentiated option + +### The "Recommended" Badge + +Don't just label the middle tier. Make it visually obvious: +- Darker background or brand color +- Slightly taller card +- "Most Popular" or "Recommended for Most Teams" label +- First CTA in the tab order + +### Annual Toggle Default + +Research consistently shows defaulting to annual pricing increases annual plan take rate. Show the toggle, but default to annual. + +If you want more monthly customers (for cash flow testing, or lower commitment products), default to monthly. + +### Pricing Page SEO Consideration + +Pricing pages often rank for "[Company] pricing" queries. This matters because: +- Competitors may be running ads on your brand pricing keywords +- The page needs to load fast and be well-structured +- Include your pricing in structured data (JSON-LD Schema: PriceSpecification) + +--- + +## Pricing Page Audit Checklist + +Score each item 0-2 (0 = missing, 1 = exists but weak, 2 = done well): + +**Above the Fold** +- [ ] Billing toggle visible +- [ ] Annual savings shown clearly +- [ ] Three plan cards with clear differentiation +- [ ] "Most popular" / recommended tier highlighted +- [ ] CTA per plan + +**Content** +- [ ] Full feature comparison table +- [ ] FAQ section (5+ questions) +- [ ] Social proof / logos +- [ ] Enterprise CTA + +**Copy** +- [ ] Plan names are meaningful (not just Basic/Pro) +- [ ] Price is unambiguous (per user? per month? billed how?) +- [ ] CTAs are action-oriented +- [ ] Positioning line per plan + +**Trust** +- [ ] Security badges (if B2B) +- [ ] Money-back guarantee or cancellation policy visible +- [ ] "Cancel anytime" stated explicitly + +**Score interpretation:** +- 22-24: Strong page. Test specific elements. +- 16-21: Good foundation. Fix weak sections. +- <16: Material gaps. Rebuild using this playbook. + +--- + +## Pricing Page A/B Test Ideas + +**High impact, easier to test:** +1. Default billing toggle (annual vs. monthly) +2. "Most popular" badge placement +3. CTA copy (Start free trial vs. Get Pro) +4. Price display ($/mo vs. $/year) + +**Medium impact, more setup:** +5. Plan name messaging (segment-based vs. feature-based) +6. Number of features shown in above-fold cards (3 vs. 6) +7. Social proof placement (above vs. below fold) +8. FAQ accordion vs. expanded + +**High impact, harder to execute:** +9. Actual price points (statistical significance takes longer) +10. Three tiers vs. two tiers +11. Adding vs. removing free tier + +**Minimum traffic for pricing tests:** 500+ visitors per variant per week. Below that, results won't be statistically meaningful. diff --git a/marketing-skill/pricing-strategy/scripts/pricing_modeler.py b/marketing-skill/pricing-strategy/scripts/pricing_modeler.py new file mode 100644 index 0000000..89f18ae --- /dev/null +++ b/marketing-skill/pricing-strategy/scripts/pricing_modeler.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python3 +"""Pricing modeler — projects revenue at different price points and recommends tier structure.""" + +import json +import sys +import math + +SAMPLE_INPUT = { + "current_mrr": 45000, + "current_customers": 300, + "monthly_new_customers": 25, + "monthly_churn_rate_pct": 3.5, + "trial_to_paid_rate_pct": 18, + "current_plans": [ + {"name": "Starter", "price": 29, "customer_count": 180}, + {"name": "Pro", "price": 79, "customer_count": 100}, + {"name": "Enterprise", "price": 199, "customer_count": 20} + ], + "competitor_prices": [49, 89, 249], + "cogs_per_customer_monthly": 8, + "target_gross_margin_pct": 75 +} + + +def calculate_arpu(plans): + total_rev = sum(p["price"] * p["customer_count"] for p in plans) + total_cust = sum(p["customer_count"] for p in plans) + return total_rev / total_cust if total_cust > 0 else 0 + + +def project_revenue_at_price(base_customers, base_arpu, new_arpu, + new_customers_monthly, churn_rate, months=12): + """Project MRR over N months at a new ARPU, assuming some churn from price change.""" + price_increase_pct = (new_arpu - base_arpu) / base_arpu if base_arpu > 0 else 0 + + # Estimate churn uplift from price increase + # Empirical: each 10% price increase causes ~2-4% additional one-time churn + if price_increase_pct > 0: + price_churn_hit = price_increase_pct * 0.25 # 25% of increase leaks as churn + else: + price_churn_hit = 0 + + monthly_churn = churn_rate / 100 + + mrr_series = [] + customers = base_customers * (1 - price_churn_hit) # initial price churn hit + mrr = customers * new_arpu + + for month in range(1, months + 1): + mrr_series.append(round(mrr, 0)) + customers = customers * (1 - monthly_churn) + new_customers_monthly + mrr = customers * new_arpu + + return { + "month_1_mrr": mrr_series[0], + "month_6_mrr": mrr_series[5], + "month_12_mrr": mrr_series[11], + "total_12mo_revenue": sum(mrr_series), + "customers_after_price_churn": round(base_customers * (1 - price_churn_hit), 0) + } + + +def recommend_tier_structure(plans, competitor_prices, cogs, target_margin_pct): + """Recommend Good-Better-Best tier structure based on current state and competitors.""" + current_arpu = calculate_arpu(plans) + comp_avg = sum(competitor_prices) / len(competitor_prices) if competitor_prices else current_arpu + comp_min = min(competitor_prices) if competitor_prices else current_arpu * 0.7 + comp_max = max(competitor_prices) if competitor_prices else current_arpu * 1.5 + + # Minimum price based on cost structure + min_viable_price = cogs / (1 - target_margin_pct / 100) + + # Recommended tier anchors + entry_price = max(min_viable_price, comp_min * 0.9) + mid_price = entry_price * 2.5 + premium_price = mid_price * 2.5 + + # Round to psychologically clean prices + def clean_price(p): + if p < 30: + return round(p / 5) * 5 - 1 # e.g., 19, 29 + elif p < 100: + return round(p / 10) * 10 - 1 # e.g., 49, 79, 99 + elif p < 500: + return round(p / 25) * 25 - 1 # e.g., 149, 199, 299 + else: + return round(p / 100) * 100 - 1 # e.g., 499, 999 + + return { + "entry": { + "name": "Starter", + "recommended_price": clean_price(entry_price), + "positioning": "For individuals and small teams getting started" + }, + "mid": { + "name": "Professional", + "recommended_price": clean_price(mid_price), + "positioning": "For growing teams that need the full feature set — recommended for most" + }, + "premium": { + "name": "Enterprise", + "recommended_price": clean_price(premium_price), + "positioning": "For larger organizations needing security, compliance, and dedicated support" + }, + "rationale": { + "current_arpu": round(current_arpu, 2), + "competitor_range": f"${comp_min}-${comp_max}", + "min_viable_price": round(min_viable_price, 2), + "pricing_vs_market": "at-market" if abs(current_arpu - comp_avg) / comp_avg < 0.15 else + "below-market" if current_arpu < comp_avg else "above-market" + } + } + + +def elasticity_estimate(trial_to_paid_pct, current_arpu): + """Rough price elasticity signal based on conversion rate.""" + if trial_to_paid_pct > 40: + signal = "strong-underpricing" + note = "Conversion >40% — strong signal of underpricing. Test 20-30% increase." + headroom = 0.30 + elif trial_to_paid_pct > 25: + signal = "possible-underpricing" + note = "Conversion 25-40% — healthy, but may have room for modest price increase." + headroom = 0.15 + elif trial_to_paid_pct > 15: + signal = "market-priced" + note = "Conversion 15-25% — likely market-priced. Focus on tier structure and packaging." + headroom = 0.05 + elif trial_to_paid_pct > 8: + signal = "possible-overpricing" + note = "Conversion 8-15% — possible price friction. Audit trial experience before reducing price." + headroom = -0.05 + else: + signal = "high-friction" + note = "Conversion <8% — significant friction. May be pricing, trial experience, or ICP fit." + headroom = -0.15 + + return { + "signal": signal, + "note": note, + "estimated_price_headroom_pct": round(headroom * 100, 0), + "suggested_test_price": round(current_arpu * (1 + headroom), 2) + } + + +def print_report(result, inputs): + cur = result["current_state"] + elast = result["elasticity"] + tiers = result["tier_recommendation"] + scenarios = result["price_scenarios"] + + print("\n" + "="*65) + print(" PRICING MODELER") + print("="*65) + + print(f"\nšŸ“Š CURRENT STATE") + print(f" MRR: ${cur['current_mrr']:,.0f}") + print(f" Customers: {cur['customers']}") + print(f" ARPU: ${cur['arpu']:.2f}/mo") + print(f" Trial-to-paid rate: {inputs['trial_to_paid_rate_pct']}%") + print(f" Monthly churn rate: {inputs['monthly_churn_rate_pct']}%") + print(f" Gross margin (est.): {cur['gross_margin_pct']:.1f}%") + + print(f"\nšŸ’” PRICE ELASTICITY SIGNAL") + print(f" Signal: {elast['signal'].replace('-', ' ').upper()}") + print(f" Note: {elast['note']}") + print(f" Headroom: {'+' if elast['estimated_price_headroom_pct'] >= 0 else ''}" + f"{elast['estimated_price_headroom_pct']:.0f}%") + print(f" Test at: ${elast['suggested_test_price']:.2f}/mo ARPU") + + print(f"\nšŸ“ RECOMMENDED TIER STRUCTURE") + tier_rat = tiers['rationale'] + print(f" Market position: {tier_rat['pricing_vs_market'].replace('-', ' ').title()}") + print(f" Competitor range: {tier_rat['competitor_range']}") + print(f" Min viable price: ${tier_rat['min_viable_price']:.2f}/mo") + print(f"\n ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”") + print(f" │ Tier │ Price │ Positioning │") + print(f" ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤") + for key in ["entry", "mid", "premium"]: + t = tiers[key] + name = t["name"].ljust(15) + price = f"${t['recommended_price']}/mo".ljust(10) + pos = t["positioning"][:34].ljust(34) + print(f" │ {name} │ {price} │ {pos} │") + print(f" ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜") + + print(f"\nšŸ“ˆ REVENUE SCENARIOS (12-month projection)") + print(f" {'Scenario':<25} {'Mo 1 MRR':>10} {'Mo 6 MRR':>10} {'Mo 12 MRR':>10} {'12mo Total':>12}") + print(f" {'-'*67}") + for s in scenarios: + print(f" {s['scenario']:<25} " + f"${s['month_1_mrr']:>9,.0f} " + f"${s['month_6_mrr']:>9,.0f} " + f"${s['month_12_mrr']:>9,.0f} " + f"${s['total_12mo_revenue']:>11,.0f}") + + print(f"\nšŸŽÆ RECOMMENDATION") + best = max(scenarios, key=lambda s: s['total_12mo_revenue']) + current = next((s for s in scenarios if s['scenario'] == 'Current pricing'), scenarios[0]) + uplift = best['total_12mo_revenue'] - current['total_12mo_revenue'] + print(f" Best scenario: {best['scenario']}") + print(f" 12-month uplift: ${uplift:,.0f} vs. current") + print(f" Note: Projections assume trial volume and churn hold constant.") + print(f" Test price increases on new customers first.") + + print("\n" + "="*65 + "\n") + + +def main(): + if len(sys.argv) > 1 and sys.argv[1] != "--json": + with open(sys.argv[1]) as f: + inputs = json.load(f) + else: + if "--json" not in sys.argv: + print("No input file provided. Running with sample data...\n") + inputs = SAMPLE_INPUT + + current_arpu = calculate_arpu(inputs["current_plans"]) + total_customers = inputs["current_customers"] + cogs = inputs["cogs_per_customer_monthly"] + target_margin = inputs["target_gross_margin_pct"] + + gross_margin = ((current_arpu - cogs) / current_arpu * 100) if current_arpu > 0 else 0 + + tier_rec = recommend_tier_structure( + inputs["current_plans"], + inputs.get("competitor_prices", []), + cogs, + target_margin + ) + + elast = elasticity_estimate(inputs["trial_to_paid_rate_pct"], current_arpu) + + # Model multiple scenarios + churn = inputs["monthly_churn_rate_pct"] + new_mo = inputs["monthly_new_customers"] + + scenarios = [] + for label, arpu in [ + ("Current pricing", current_arpu), + ("5% price increase", current_arpu * 1.05), + ("15% price increase", current_arpu * 1.15), + ("25% price increase", current_arpu * 1.25), + ("Recommended tiers", tier_rec["mid"]["recommended_price"]) + ]: + proj = project_revenue_at_price(total_customers, current_arpu, arpu, new_mo, churn) + scenarios.append({"scenario": label, "arpu": round(arpu, 2), **proj}) + + result = { + "current_state": { + "current_mrr": inputs["current_mrr"], + "customers": total_customers, + "arpu": round(current_arpu, 2), + "gross_margin_pct": round(gross_margin, 1) + }, + "elasticity": elast, + "tier_recommendation": tier_rec, + "price_scenarios": scenarios + } + + print_report(result, inputs) + + if "--json" in sys.argv: + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/programmatic-seo/SKILL.md b/marketing-skill/programmatic-seo/SKILL.md new file mode 100644 index 0000000..1e43c28 --- /dev/null +++ b/marketing-skill/programmatic-seo/SKILL.md @@ -0,0 +1,280 @@ +--- +name: programmatic-seo +description: When the user wants to create SEO-driven pages at scale using templates and data. Also use when the user mentions "programmatic SEO," "template pages," "pages at scale," "directory pages," "location pages," "[keyword] + [city] pages," "comparison pages," "integration pages," or "building many pages for SEO." For auditing existing SEO issues, see seo-audit. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Programmatic SEO + +You are an expert in programmatic SEO—building SEO-optimized pages at scale using templates and data. Your goal is to create pages that rank, provide value, and avoid thin content penalties. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before designing a programmatic SEO strategy, understand: + +1. **Business Context** + - What's the product/service? + - Who is the target audience? + - What's the conversion goal for these pages? + +2. **Opportunity Assessment** + - What search patterns exist? + - How many potential pages? + - What's the search volume distribution? + +3. **Competitive Landscape** + - Who ranks for these terms now? + - What do their pages look like? + - Can you realistically compete? + +--- + +## Core Principles + +### 1. Unique Value Per Page +- Every page must provide value specific to that page +- Not just swapped variables in a template +- Maximize unique content—the more differentiated, the better + +### 2. Proprietary Data Wins +Hierarchy of data defensibility: +1. Proprietary (you created it) +2. Product-derived (from your users) +3. User-generated (your community) +4. Licensed (exclusive access) +5. Public (anyone can use—weakest) + +### 3. Clean URL Structure +**Always use subfolders, not subdomains**: +- Good: `yoursite.com/templates/resume/` +- Bad: `templates.yoursite.com/resume/` + +### 4. Genuine Search Intent Match +Pages must actually answer what people are searching for. + +### 5. Quality Over Quantity +Better to have 100 great pages than 10,000 thin ones. + +### 6. Avoid Google Penalties +- No doorway pages +- No keyword stuffing +- No duplicate content +- Genuine utility for users + +--- + +## The 12 Playbooks (Overview) + +| Playbook | Pattern | Example | +|----------|---------|---------| +| Templates | "[Type] template" | "resume template" | +| Curation | "best [category]" | "best website builders" | +| Conversions | "[X] to [Y]" | "$10 USD to GBP" | +| Comparisons | "[X] vs [Y]" | "webflow vs wordpress" | +| Examples | "[type] examples" | "landing page examples" | +| Locations | "[service] in [location]" | "dentists in austin" | +| Personas | "[product] for [audience]" | "crm for real estate" | +| Integrations | "[product A] [product B] integration" | "slack asana integration" | +| Glossary | "what is [term]" | "what is pSEO" | +| Translations | Content in multiple languages | Localized content | +| Directory | "[category] tools" | "ai copywriting tools" | +| Profiles | "[entity name]" | "stripe ceo" | + +**For detailed playbook implementation**: See [references/playbooks.md](references/playbooks.md) + +--- + +## Choosing Your Playbook + +| If you have... | Consider... | +|----------------|-------------| +| Proprietary data | Directories, Profiles | +| Product with integrations | Integrations | +| Design/creative product | Templates, Examples | +| Multi-segment audience | Personas | +| Local presence | Locations | +| Tool or utility product | Conversions | +| Content/expertise | Glossary, Curation | +| Competitor landscape | Comparisons | + +You can layer multiple playbooks (e.g., "Best coworking spaces in San Diego"). + +--- + +## Implementation Framework + +### 1. Keyword Pattern Research + +**Identify the pattern:** +- What's the repeating structure? +- What are the variables? +- How many unique combinations exist? + +**Validate demand:** +- Aggregate search volume +- Volume distribution (head vs. long tail) +- Trend direction + +### 2. Data Requirements + +**Identify data sources:** +- What data populates each page? +- Is it first-party, scraped, licensed, public? +- How is it updated? + +### 3. Template Design + +**Page structure:** +- Header with target keyword +- Unique intro (not just variables swapped) +- Data-driven sections +- Related pages / internal links +- CTAs appropriate to intent + +**Ensuring uniqueness:** +- Each page needs unique value +- Conditional content based on data +- Original insights/analysis per page + +### 4. Internal Linking Architecture + +**Hub and spoke model:** +- Hub: Main category page +- Spokes: Individual programmatic pages +- Cross-links between related spokes + +**Avoid orphan pages:** +- Every page reachable from main site +- XML sitemap for all pages +- Breadcrumbs with structured data + +### 5. Indexation Strategy + +- Prioritize high-volume patterns +- Noindex very thin variations +- Manage crawl budget thoughtfully +- Separate sitemaps by page type + +--- + +## Quality Checks + +### Pre-Launch Checklist + +**Content quality:** +- [ ] Each page provides unique value +- [ ] Answers search intent +- [ ] Readable and useful + +**Technical SEO:** +- [ ] Unique titles and meta descriptions +- [ ] Proper heading structure +- [ ] Schema markup implemented +- [ ] Page speed acceptable + +**Internal linking:** +- [ ] Connected to site architecture +- [ ] Related pages linked +- [ ] No orphan pages + +**Indexation:** +- [ ] In XML sitemap +- [ ] Crawlable +- [ ] No conflicting noindex + +### Post-Launch Monitoring + +Track: Indexation rate, Rankings, Traffic, Engagement, Conversion + +Watch for: Thin content warnings, Ranking drops, Manual actions, Crawl errors + +--- + +## Common Mistakes + +- **Thin content**: Just swapping city names in identical content +- **Keyword cannibalization**: Multiple pages targeting same keyword +- **Over-generation**: Creating pages with no search demand +- **Poor data quality**: Outdated or incorrect information +- **Ignoring UX**: Pages exist for Google, not users + +--- + +## Output Format + +### Strategy Document +- Opportunity analysis +- Implementation plan +- Content guidelines + +### Page Template +- URL structure +- Title/meta templates +- Content outline +- Schema markup + +--- + +## Task-Specific Questions + +1. What keyword patterns are you targeting? +2. What data do you have (or can acquire)? +3. How many pages are you planning? +4. What does your site authority look like? +5. Who currently ranks for these terms? +6. What's your technical stack? + +--- + +## Related Skills + +- **seo-audit** — WHEN: programmatic pages are live and you need to verify indexation, detect thin content penalties, or diagnose ranking drops across the page set. WHEN NOT: don't run an audit before you've even designed the template strategy. +- **schema-markup** — WHEN: the chosen playbook benefits from structured data (e.g., Product, Review, FAQ, LocalBusiness schemas on location or comparison pages). WHEN NOT: don't prioritize schema before the core template and data pipeline are working. +- **competitor-alternatives** — WHEN: the playbook selected is Comparisons ("[X] vs [Y]") or Alternatives; that skill has dedicated comparison page frameworks. WHEN NOT: don't overlap with it for non-comparison playbooks like Locations or Glossary. +- **content-strategy** — WHEN: user needs to decide which pSEO playbook to pursue or how it fits into a broader editorial strategy. WHEN NOT: don't use when the playbook is decided and the task is pure implementation. +- **site-architecture** — WHEN: the pSEO build is large (500+ pages) and hub-and-spoke or crawl budget management decisions need explicit architectural planning. WHEN NOT: skip for small pSEO pilots (<100 pages) where default hub-and-spoke is sufficient. +- **marketing-context** — WHEN: always check `.claude/product-marketing-context.md` first to understand ICP, value prop, and conversion goals before keyword pattern research. WHEN NOT: skip if the user has provided all context directly in the conversation. + +--- + +## Communication + +All programmatic SEO output follows this quality standard: +- Lead with the **Opportunity Analysis** — estimated page count, aggregate search volume, and data source feasibility +- Strategy documents use the **Strategy → Template → Checklist** structure consistently +- Every playbook recommendation is paired with a real-world example and a data source suggestion +- Call out thin-content risk explicitly when the data source is public/scraped +- Pre-launch checklists are always included before any "go build it" instruction +- Post-launch monitoring metrics are defined before launch, not after problems appear + +--- + +## Proactive Triggers + +Automatically surface programmatic-seo when: + +1. **"We want to rank for hundreds of keywords"** — User describes a large keyword set with a repeating pattern; immediately map it to one of the 12 playbooks. +2. **Competitor has a directory or integration page set** — When competitive analysis reveals a rival ranking via pSEO; proactively propose matching or superior playbook. +3. **Product has many integrations or use-case personas** — Detect integration or persona variety in the product description; suggest Integrations or Personas playbooks. +4. **Location-based service** — Any mention of serving multiple cities or regions triggers the Locations playbook discussion. +5. **seo-audit reveals keyword gap cluster** — When seo-audit finds dozens of unaddressed queries following a pattern, proactively suggest a pSEO build to fill the gap at scale. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Opportunity Analysis | Markdown table | Keyword patterns Ɨ estimated volume Ɨ data source Ɨ difficulty rating | +| Playbook Selection Matrix | Table | If/then mapping of business context to recommended playbook with rationale | +| Page Template Spec | Markdown with annotated sections | URL pattern, title/meta templates, content block structure, unique value rules | +| Pre-Launch Checklist | Checkbox list | Content quality, technical SEO, internal linking, indexation gates | +| Post-Launch Monitoring Plan | Table | Metrics to track Ɨ tools Ɨ alert thresholds Ɨ review cadence | diff --git a/marketing-skill/programmatic-seo/scripts/url_pattern_generator.py b/marketing-skill/programmatic-seo/scripts/url_pattern_generator.py new file mode 100644 index 0000000..d7924f4 --- /dev/null +++ b/marketing-skill/programmatic-seo/scripts/url_pattern_generator.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" +URL Pattern Generator for Programmatic SEO + +Generates URL patterns and page templates from a data source. +Helps plan template-based page generation at scale. + +Usage: + python3 url_pattern_generator.py # Demo mode + python3 url_pattern_generator.py data.json # From data file + python3 url_pattern_generator.py data.json --json # JSON output + +Input format (JSON): +{ + "template": "{tool}-vs-{competitor}-comparison", + "variables": { + "tool": ["slack", "teams", "discord"], + "competitor": ["zoom", "webex"] + }, + "base_url": "https://example.com/compare" +} +""" + +import json +import sys +import os +from itertools import product as cartesian_product + + +def generate_urls(config): + """Generate all URL combinations from template and variables.""" + template = config["template"] + variables = config["variables"] + base_url = config.get("base_url", "https://example.com") + + var_names = list(variables.keys()) + var_values = [variables[name] for name in var_names] + + urls = [] + for combo in cartesian_product(*var_values): + mapping = dict(zip(var_names, combo)) + + # Skip self-comparisons + values = list(mapping.values()) + if len(values) != len(set(values)): + continue + + slug = template + for key, val in mapping.items(): + slug = slug.replace("{" + key + "}", str(val).lower().replace(" ", "-")) + + url = f"{base_url}/{slug}" + urls.append({ + "url": url, + "slug": slug, + "variables": mapping + }) + + return urls + + +def analyze_patterns(urls, config): + """Analyze generated URL patterns for SEO concerns.""" + issues = [] + warnings = [] + + # Check total page count + total = len(urls) + if total > 10000: + issues.append(f"Generating {total:,} pages — risk of thin content penalty. Consider narrowing variables.") + elif total > 1000: + warnings.append(f"Generating {total:,} pages — ensure each has unique, substantial content.") + + # Check URL length + long_urls = [u for u in urls if len(u["url"]) > 75] + if long_urls: + warnings.append(f"{len(long_urls)} URLs exceed 75 chars — may truncate in SERPs.") + + # Check for potential duplicate intent + template = config["template"] + var_names = list(config["variables"].keys()) + if len(var_names) >= 2: + # Check if swapped variables create duplicate intent + # e.g., "slack-vs-zoom" and "zoom-vs-slack" + seen_pairs = set() + dupes = 0 + for u in urls: + vals = tuple(sorted(u["variables"].values())) + if vals in seen_pairs: + dupes += 1 + seen_pairs.add(vals) + if dupes > 0: + warnings.append(f"{dupes} URL pairs may have duplicate search intent (e.g., 'A vs B' and 'B vs A'). Consider canonicalizing.") + + # Score + score = 100 + score -= len(issues) * 20 + score -= len(warnings) * 5 + score = max(0, min(100, score)) + + return { + "total_pages": total, + "avg_url_length": sum(len(u["url"]) for u in urls) // max(len(urls), 1), + "long_urls": len(long_urls), + "issues": issues, + "warnings": warnings, + "score": score + } + + +def format_report(urls, analysis, config): + """Format human-readable report.""" + lines = [] + lines.append("") + lines.append("=" * 60) + lines.append(" PROGRAMMATIC SEO — URL PATTERN REPORT") + lines.append("=" * 60) + lines.append("") + lines.append(f" Template: {config['template']}") + lines.append(f" Base URL: {config.get('base_url', 'https://example.com')}") + lines.append(f" Variables: {len(config['variables'])} ({', '.join(config['variables'].keys())})") + lines.append(f" Total Pages: {analysis['total_pages']:,}") + lines.append(f" Avg URL Len: {analysis['avg_url_length']} chars") + lines.append("") + + # Score + score = analysis["score"] + bar_filled = score // 5 + bar = "ā–ˆ" * bar_filled + "ā–‘" * (20 - bar_filled) + lines.append(f" PATTERN SCORE: {score}/100") + lines.append(f" [{bar}]") + lines.append("") + + # Issues + if analysis["issues"]: + lines.append(" šŸ”“ ISSUES:") + for issue in analysis["issues"]: + lines.append(f" • {issue}") + lines.append("") + + if analysis["warnings"]: + lines.append(" 🟔 WARNINGS:") + for warn in analysis["warnings"]: + lines.append(f" • {warn}") + lines.append("") + + # Sample URLs + lines.append(" šŸ“‹ SAMPLE URLS (first 10):") + for u in urls[:10]: + lines.append(f" {u['url']}") + if len(urls) > 10: + lines.append(f" ... and {len(urls) - 10} more") + lines.append("") + + return "\n".join(lines) + + +SAMPLE_CONFIG = { + "template": "{tool}-vs-{competitor}-comparison", + "variables": { + "tool": ["slack", "microsoft-teams", "discord", "zoom"], + "competitor": ["slack", "microsoft-teams", "discord", "zoom", "webex", "google-meet"] + }, + "base_url": "https://example.com/compare" +} + + +def main(): + use_json = "--json" in sys.argv + args = [a for a in sys.argv[1:] if a != "--json"] + + if args and os.path.isfile(args[0]): + with open(args[0]) as f: + config = json.load(f) + else: + if not args: + print("[Demo mode — using sample comparison page config]") + config = SAMPLE_CONFIG + + urls = generate_urls(config) + analysis = analyze_patterns(urls, config) + + if use_json: + print(json.dumps({ + "config": config, + "urls": urls, + "analysis": analysis + }, indent=2)) + else: + print(format_report(urls, analysis, config)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/prompt-engineer-toolkit/SKILL.md b/marketing-skill/prompt-engineer-toolkit/SKILL.md index c25b83d..033c52b 100644 --- a/marketing-skill/prompt-engineer-toolkit/SKILL.md +++ b/marketing-skill/prompt-engineer-toolkit/SKILL.md @@ -1,3 +1,14 @@ +--- +name: prompt-engineer-toolkit +description: "When the user wants to improve prompts for AI-assisted marketing, build prompt templates, or optimize AI content workflows. Also use when the user mentions 'prompt engineering,' 'improve my prompts,' 'AI writing quality,' 'prompt templates,' or 'AI content workflow.'" +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + # Prompt Engineer Toolkit **Tier:** POWERFUL @@ -150,3 +161,32 @@ This enables deterministic grading across prompt variants. - Optimizing for one benchmark while harming edge cases - Missing audit trail for prompt edits in multi-author teams - Model swap without rerunning baseline A/B suite + +## Proactive Triggers + +- **AI output sounds generic** → Prompts lack brand voice context. Include voice guidelines. +- **Inconsistent output quality** → Prompts too vague. Add specific examples and constraints. +- **No quality checks on AI content** → AI output needs human review. Never publish without editing. +- **Same prompt style for all tasks** → Different tasks need different prompt structures. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Improve my prompts" | Prompt audit with specific rewrites for better output | +| "Prompt templates" | Task-specific prompt templates for marketing use cases | +| "AI content workflow" | End-to-end AI-assisted content production workflow | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **content-production**: For the full content pipeline. Prompt engineering supports AI-assisted writing. +- **ad-creative**: For generating ad variations using prompt techniques. +- **content-humanizer**: For refining AI-generated output to sound natural. +- **marketing-context**: Provides brand context that improves prompt outputs. diff --git a/marketing-skill/referral-program/SKILL.md b/marketing-skill/referral-program/SKILL.md new file mode 100644 index 0000000..9d18c1c --- /dev/null +++ b/marketing-skill/referral-program/SKILL.md @@ -0,0 +1,286 @@ +--- +name: referral-program +description: "When the user wants to design, launch, or optimize a referral or affiliate program. Use when they mention 'referral program,' 'affiliate program,' 'word of mouth,' 'refer a friend,' 'incentive program,' 'customer referrals,' 'brand ambassador,' 'partner program,' 'referral link,' or 'growth through referrals.' Covers program mechanics, incentive design, and optimization — not just the idea of referrals but the actual system." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Referral Program + +You are a growth engineer who has designed referral and affiliate programs for SaaS companies, marketplaces, and consumer apps. You know the difference between programs that compound and programs that collect dust. Your goal is to build a referral system that actually runs — one with the right mechanics, triggers, incentives, and measurement to make customers do your acquisition for you. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered. + +Gather this context (ask if not provided): + +### 1. Product & Customer +- What are you selling? (SaaS, marketplace, service, ecommerce) +- Who is your ideal customer and what do they love about your product? +- What's your average LTV? (This determines incentive ceiling) +- What's your current CAC via other channels? + +### 2. Program Goals +- What outcome do you want? (More signups, more revenue, brand reach) +- Is this B2C or B2B? (Different mechanics apply) +- Do you want customers referring customers, or partners promoting your product? + +### 3. Current State (if optimizing) +- What program exists today? +- What are the key metrics? (Referral rate, conversion rate, active referrers %) +- What's the reward structure? +- Where does the loop break down? + +--- + +## How This Skill Works + +### Mode 1: Design a New Program +Starting from scratch. Build the full referral program — loop, incentives, triggers, and measurement. + +**Workflow:** +1. Define the referral loop (4 stages) +2. Choose program type (customer referral vs. affiliate) +3. Design the incentive structure (what, when, for whom) +4. Identify trigger moments (when to ask for referrals) +5. Plan the share mechanics (how referrals actually happen) +6. Define measurement framework + +### Mode 2: Optimize an Existing Program +You have something running but it's underperforming. Diagnose where the loop breaks. + +**Workflow:** +1. Audit current metrics against benchmarks +2. Identify the specific weak point (low awareness, low share rate, low conversion, reward friction) +3. Run a focused fix — don't redesign everything at once +4. Measure the impact before moving to the next lever + +### Mode 3: Launch an Affiliate Program +Different from customer referrals. Affiliates are external promoters — bloggers, influencers, complementary SaaS, industry newsletters — motivated by commission, not loyalty. + +**Workflow:** +1. Define affiliate tiers and commission structure +2. Identify and recruit initial affiliate partners +3. Build the affiliate toolkit (links, assets, copy) +4. Set tracking and payout mechanics +5. Onboard and activate your first 10 affiliates + +--- + +## Referral vs. Affiliate — Choose the Right Mechanism + +| | Customer Referral | Affiliate Program | +|---|---|---| +| **Who promotes** | Your existing customers | External partners, publishers, influencers | +| **Motivation** | Loyalty, reward, social currency | Commission, audience alignment | +| **Best for** | B2C, prosumer, SMB SaaS | B2B SaaS, high LTV products, content-heavy niches | +| **Activation** | Triggered by aha moment, milestone | Recruited proactively, onboarded | +| **Payout timing** | Account credit, discount, cash reward | Revenue share or flat fee per conversion | +| **CAC impact** | Low — reward < CAC | Variable — commission % determines | +| **Scale** | Scales with user base | Scales with partner recruitment | + +**Rule of thumb:** If your customers are enthusiastic and social, start with customer referrals. If your customers are businesses buying on behalf of a team, start with affiliates. + +--- + +## The Referral Loop + +Every referral program runs on the same 4-stage loop. If any stage is weak, the loop breaks. + +``` +[Trigger Moment] → [Share Action] → [Referred User Converts] → [Reward Delivered] → [Loop] +``` + +### Stage 1: Trigger Moment +This is when you ask customers to refer. Timing is everything. + +**High-signal trigger moments:** +- **After aha moment** — when the customer first experiences core value (not at signup — too early) +- **After a milestone** — "You just saved your 100th hour" / "Your 10th team member joined" +- **After great support** — post-resolution NPS prompt → if 9-10, ask for referral +- **After renewal** — customers who renew are telling you they're satisfied +- **After a public win** — customer tweets about you → follow up with referral link + +**What doesn't work:** Asking on day 1, asking in onboarding emails, asking in the footer of every email. + +### Stage 2: Share Action +Remove every possible point of friction. + +- Pre-filled share message (editable, not locked) +- Personal referral link (not a generic coupon code) +- Share options: email invite, link copy, social share, Slack/Teams share for B2B +- Mobile-optimized for consumer products +- One-click send — no manual copy-paste required + +### Stage 3: Referred User Converts +The referred user lands on your product. Now what? + +- Personalized landing ("Your friend Alex invited you — here's your bonus...") +- Incentive visible on landing page +- Referral attribution tracked from landing to conversion +- Clear CTA — don't make them hunt for what to do + +### Stage 4: Reward Delivered +Reward must be fast and clear. Delayed rewards break the loop. + +- Confirm reward eligibility as soon as referral signs up (not when they pay) +- Notify the referrer immediately — don't wait until month-end +- Status visible in dashboard ("2 friends joined — you've earned $40") + +--- + +## Incentive Design + +### Single-Sided vs. Double-Sided + +**Single-sided** (referrer only gets rewarded): Use when your product has strong viral hooks and customers are already enthusiastic. Lower cost per referral. + +**Double-sided** (both referrer and referred get rewarded): Use when you need to overcome inertia on both sides. Higher cost, higher conversion. Dropbox made this famous. + +**Rule:** If your referral rate is <1%, go double-sided. If it's >5%, single-sided is more profitable. + +### Reward Types + +| Type | Best For | Examples | +|------|----------|---------| +| Account credit | SaaS / subscription | "Get $20 credit" | +| Discount | Ecommerce / usage-based | "Get 1 month free" | +| Cash | High LTV, B2C | "$50 per referral" | +| Feature unlock | Freemium | "Unlock advanced analytics" | +| Status / recognition | Community / loyalty | "Ambassador status, exclusive badge" | +| Charity donation | Enterprise / mission-driven | "$25 to a cause you choose" | + +**Sizing rule:** Reward should be ≄10% of first month's value for account credit. For cash, cap at 30% of first payment. Run `scripts/referral_roi_calculator.py` to model reward sizing against your LTV and CAC. + +### Tiered Rewards (Gamification) +When you want referrers to go from 1 referral to 10: + +``` +1 referral → $20 credit +3 referrals → $75 credit (25/referral) + bonus feature +10 referrals → $300 cash + ambassador status +``` + +Keep tiers simple. Three levels maximum. Each tier should feel meaningfully better, not just slightly better. + +--- + +## Optimization Levers + +Don't optimize randomly. Diagnose first, then pull the right lever. + +| Metric | Benchmark | If Below Benchmark | +|--------|-----------|-------------------| +| Referral program awareness | >40% of active users know it exists | Promote in-app, post-activation emails | +| Active referrers (%) | 5–15% of active user base | Improve trigger moments and visibility | +| Referral share rate | 20–40% of those who see it share | Simplify share flow, improve messaging | +| Referred conversion rate | 15–25% (vs. 5-10% organic) | Improve referred landing page, add incentive | +| Reward redemption rate | >70% within 30 days | Reduce friction, send reminders | + +### Improving Referral Rate +- Move the trigger moment earlier (after aha, not after 90 days) +- Add referral prompt to success states ("You just hit 1,000 contacts — share this with a colleague?") +- Surface the program in the product dashboard, not just in emails +- Test double-sided vs. single-sided rewards + +### Improving Referred User Conversion +- Personalize the landing page ("Invited by [Name]") +- Show the referred user their specific benefit above the fold +- Reduce signup friction — if they're referred, they're warm; don't make them jump through hoops +- A/B test the referral landing page like a paid traffic landing page + +--- + +## Key Metrics + +Track these weekly: + +| Metric | Formula | Why It Matters | +|--------|---------|----------------| +| Referral rate | Referrals sent / active users | Health of the program | +| Active referrers % | Users who sent ≄1 referral / total active users | Engagement depth | +| Referral conversion rate | Referrals that converted / referrals sent | Quality of referred traffic | +| CAC via referral | Reward cost / new customers via referral | Program economics vs. other channels | +| Referral revenue contribution | Revenue from referred customers / total revenue | Business impact | +| Virality coefficient (K) | Referrals per user Ɨ conversion rate | K >1 = viral growth | + +See [references/measurement-framework.md](references/measurement-framework.md) for benchmarks by industry and optimization playbook. + +--- + +## Affiliate Program Launch Checklist + +If launching an affiliate program specifically: + +**Before Launch** +- [ ] Commission structure defined (% of revenue or flat fee per conversion) +- [ ] Cookie window set (30 days minimum, 90 days for B2B) +- [ ] Affiliate tracking platform selected (Impact, ShareASale, Rewardful, PartnerStack, or custom) +- [ ] Affiliate agreement drafted (legal review recommended) +- [ ] Payment terms clear (threshold, frequency, method) + +**Partner Toolkit** +- [ ] Unique tracking links for each affiliate +- [ ] Pre-written copy and email swipes +- [ ] Approved images and banner ads +- [ ] Product explanation sheet (what to tell their audience) +- [ ] Landing page optimized for affiliate traffic + +**Recruitment** +- [ ] List of 50 target affiliates (complementary SaaS, newsletters, bloggers, agencies) +- [ ] Personalized outreach — not a generic "join our affiliate program" email +- [ ] 10-affiliate pilot before scaling + +See [references/program-mechanics.md](references/program-mechanics.md) for detailed program patterns and real-world examples. + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Asking at signup** → Flag immediately. Asking a new user to refer before they've experienced value is a conversion killer. Move trigger to post-aha moment. +- **Reward too small relative to LTV** → If reward is <5% of LTV and referral rate is low, the math is broken. Surface the sizing issue. +- **No reward notification system** → If referred users convert but referrers aren't notified immediately, the loop breaks. Flag the need for instant notification. +- **Generic share message** → Pre-filled messages that sound like marketing copy get deleted. Flag and rewrite in first-person customer voice. +- **No attribution after the landing page** → If referral tracking stops at first visit but conversion requires multiple sessions, referral is being undercounted. Flag tracking gap. +- **Affiliate program without a partner kit** → If affiliates don't have approved copy and assets, they'll promote inaccurately or not at all. Flag before launch. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Design a referral program" | Full program spec: loop design, incentive structure, trigger moments, share mechanics, measurement plan | +| "Audit our referral program" | Metric scorecard vs. benchmarks, weak link diagnosis, prioritized optimization plan | +| "Model our incentive options" | ROI comparison of 3-5 reward structures using your LTV and CAC data | +| "Write referral program copy" | In-app prompts, referral email, referred user landing page headline, share messages | +| "Launch an affiliate program" | Launch checklist, commission structure recommendation, partner recruitment list template, affiliate kit outline | +| "What should our K-factor be?" | Virality model with your numbers — current K, target K, what needs to change to get there | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — answer before explanation +- **Numbers-grounded** — every recommendation tied to your LTV/CAC inputs +- **Confidence tagging** — 🟢 verified / 🟔 medium / šŸ”“ assumed +- **Actions have owners** — "define reward structure" → assign an owner and timeline + +--- + +## Related Skills + +- **launch-strategy**: Use when planning the go-to-market for a product launch. NOT for building a referral program (different mechanics, different timeline). +- **email-sequence**: Use when building the email flow that supports the referral program (trigger emails, reward notifications). NOT for the program design itself. +- **marketing-demand-acquisition**: Use for multi-channel paid and organic acquisition strategy. NOT for referral-specific mechanics. +- **ab-test-setup**: Use when A/B testing referral landing pages, reward structures, or trigger messaging. NOT for the program design. +- **content-creator**: Use for creating affiliate partner content or referral-related blog posts. NOT for program mechanics. diff --git a/marketing-skill/referral-program/references/measurement-framework.md b/marketing-skill/referral-program/references/measurement-framework.md new file mode 100644 index 0000000..89e4a99 --- /dev/null +++ b/marketing-skill/referral-program/references/measurement-framework.md @@ -0,0 +1,199 @@ +# Measurement Framework — Referral Program Metrics, Benchmarks, and Optimization Playbook + +The metrics that tell you if your referral program is working, what's broken, and what to fix first. + +--- + +## The Core Metric Stack + +Track these weekly. Everything else is secondary. + +| Metric | Formula | Benchmark (SaaS) | What It Tells You | +|--------|---------|-----------------|------------------| +| Program awareness | (Users who know about program / Total active users) Ɨ 100 | >40% | Are you even promoting it? | +| Active referrer rate | (Users who sent ≄1 referral / Total active users) Ɨ 100 | 5–15% | How many users are actually participating | +| Referrals sent per active referrer | Total referrals / Active referrers | 2–5 per period | How motivated referrers are | +| Referral conversion rate | (Referrals that converted / Referrals sent) Ɨ 100 | 15–30% | Quality of referred traffic | +| Reward redemption rate | (Rewards redeemed / Rewards issued) Ɨ 100 | >70% | Is the reward actually desirable? | +| CAC via referral | Total reward cost / New customers via referral | <50% of channel CAC | Program efficiency | +| K-factor (virality coefficient) | Referrals per user Ɨ Referral conversion rate | >0.5 for meaningful growth | Is it self-sustaining? | + +--- + +## Benchmarks by Stage and Model + +### Early-Stage SaaS (<$1M ARR) +| Metric | Expected | Strong | +|--------|---------|--------| +| Active referrer rate | 2–5% | >8% | +| Referral conversion rate | 10–20% | >25% | +| CAC via referral vs. paid | 30–50% of paid CAC | <25% of paid CAC | + +### Growth-Stage SaaS ($1M–$10M ARR) +| Metric | Expected | Strong | +|--------|---------|--------| +| Active referrer rate | 5–10% | >12% | +| Referral contribution to new signups | 10–20% | >25% | +| Referral contribution to revenue | 5–15% | >20% | + +### Consumer / Prosumer Products +| Metric | Expected | Strong | +|--------|---------|--------| +| Active referrer rate | 8–20% | >25% | +| Referral conversion rate | 20–40% | >50% (with double-sided reward) | +| K-factor | 0.3–0.7 | >1.0 (true viral loop) | + +### B2B Mid-Market (ACV $10k+) +| Metric | Expected | Strong | +|--------|---------|--------| +| Active referrer rate | 3–8% | >10% | +| Referral conversion rate | 20–40% (warm intros convert higher) | >50% | +| Average deal size via referral vs. standard | Similar | 20–40% higher (trust shortens negotiation) | + +--- + +## Diagnosing the Broken Stage + +### Diagnosis Framework + +``` +Is referral rate low? + └── Is awareness low? → Promote the program + └── Is trigger placement wrong? → Move to better moment + └── Is reward insufficient? → Test higher reward + └── Is share flow too complex? → Simplify + +Is referral conversion low? + └── Is the landing page cold? → Personalize for referred users + └── Is the incentive for the referred user unclear? → Make it above the fold + └── Is signup friction high? → Reduce required fields + +Is reward redemption low? + └── Is reward notification delayed? → Send immediately on qualifying event + └── Is reward type wrong? → Test cash vs. credit vs. feature unlock + └── Is the redemption process complex? → Auto-apply credits, remove steps +``` + +--- + +## The Optimization Playbook + +Work in this order. Don't try to fix everything at once. + +### Phase 1: Foundation (Month 1) +**Goal:** Get to baseline awareness and share rate. + +1. Audit whether users know the program exists +2. Add in-app promotion: dashboard banner, post-activation prompt, success state trigger +3. Add referral program to the weekly/monthly activation email +4. Ensure share flow works on mobile + +**Success gate:** Program awareness >30%, Active referrer rate >3% + +### Phase 2: Trigger Optimization (Month 2) +**Goal:** Ask at the right moment, not just any moment. + +1. Map all current trigger points +2. Move or add trigger to first aha moment (define aha moment first) +3. A/B test: trigger after aha vs. trigger after 7-day retention +4. Add NPS-linked trigger: score of 9-10 → immediate referral ask + +**Success gate:** Active referrer rate increases by 30% over Phase 1 + +### Phase 3: Incentive Tuning (Month 3) +**Goal:** Right reward, right timing, right delivery. + +1. Survey churned referrers — why did they stop? +2. Test single-sided vs. double-sided if not already tested +3. Test reward type: credit vs. cash vs. feature unlock +4. Add reward status widget to dashboard: "You've earned $X. [View details]" +5. Reduce reward payout delay — reward immediately on qualifying event, not month-end + +**Success gate:** Reward redemption rate >70%, CAC via referral <40% of paid CAC + +### Phase 4: Conversion of Referred Users (Month 4) +**Goal:** Referred users should convert at 2Ɨ organic rate. + +1. Personalize referred user landing page (use referrer name if available) +2. Highlight referred user's incentive above the fold — don't bury it +3. A/B test: direct to product vs. direct to dedicated referral landing page +4. Add "referred by" onboarding track: faster to aha, lower time to first value + +**Success gate:** Referred user conversion rate 20%+ (vs. organic baseline) + +### Phase 5: Scale and Gamification (Month 5+) +**Goal:** Turn your top 5% of referrers into a real advocacy channel. + +1. Identify top referrers — reach out personally +2. Offer top referrers early access, ambassador status, or product input role +3. Launch tiered reward structure +4. Quarterly referral challenges: "Top 10 referrers this quarter win X" + +--- + +## CAC via Referral — Full Calculation + +``` +CAC via referral = (Reward cost per referral Ɨ Successful referrals) + Program overhead costs + ─────────────────────────────────────────────────────────────────────────── + New customers acquired via referral + +Where: +- Reward cost per referral = referrer reward + referred user reward +- Program overhead = platform cost + engineering time + support time (amortized) +- Successful referrals = referrals that converted to paying customer +``` + +**Example:** +- 200 referrals sent → 40 conversions (20% conversion rate) +- Referrer reward: $30 per successful referral +- Referred user reward: $20 (discount on first month) +- Platform cost: $100/mo, engineering: $500/mo (amortized) → $600/mo overhead +- Program overhead per conversion: $600 / 40 = $15 + +**CAC via referral** = ($30 + $20) Ɨ 40 + $600 / 40 = **$65 per customer** + +Compare to paid CAC, and you know if the program is worth it. + +Use `scripts/referral_roi_calculator.py` to model this for your numbers. + +--- + +## Affiliate-Specific Metrics + +| Metric | Formula | Benchmark | +|--------|---------|-----------| +| Active affiliate rate | Active affiliates / Enrolled affiliates | 20–40% | +| Revenue per active affiliate | Total affiliate revenue / Active affiliates | Varies by niche | +| Affiliate-driven CAC | Commission paid / New customers via affiliate | Should be 80% of affiliate revenue is from 1–2 partners, you have concentration risk. One partner leaving could tank the channel overnight. Diversify proactively. + +--- + +## Reporting Template + +Weekly referral program summary: + +``` +REFERRAL PROGRAM — Week of [DATE] + +Active referrers: X (↑/↓ vs. last week) +Referrals sent: X +Conversions: X (rate: X%) +Rewards issued: $X +New customers via referral: X +CAC via referral: $X (vs. $X paid CAC) + +TOP THIS WEEK: +- [Name/segment] sent 12 referrals, 4 converted +- [Trigger optimization test] is showing +18% referrer rate + +ISSUES: +- [What's broken and the plan to fix it] + +NEXT ACTION: +- [One thing we're doing this week to improve the program] +``` diff --git a/marketing-skill/referral-program/references/program-mechanics.md b/marketing-skill/referral-program/references/program-mechanics.md new file mode 100644 index 0000000..cc6f55f --- /dev/null +++ b/marketing-skill/referral-program/references/program-mechanics.md @@ -0,0 +1,212 @@ +# Program Mechanics — Referral and Affiliate Design Patterns + +Detailed design patterns with real-world examples. Use this as a reference when designing programs — these are the mechanics that separate programs with 10% referral rates from ones with 0.5%. + +--- + +## The Two Fundamental Program Types + +### Type A: Customer-to-Customer Referral +Your best customers refer their peers. Classic example: Dropbox, Airbnb, Uber. + +**Core mechanics:** +- Referral link generated per user +- Reward given when referred user completes a qualifying action (sign up, first purchase, first month paid) +- Referrer sees their dashboard: links sent, signed up, rewards earned + +**What makes it work:** +- Existing customer trust transfers. Being referred by someone you trust removes 80% of purchase skepticism. +- The referrer's reputation is on the line — they only refer people they think will benefit +- Natural social proof at the moment of conversion + +### Type B: Partner / Affiliate Program +External publishers, influencers, agencies, or complementary SaaS tools promote you in exchange for commission. + +**Core mechanics:** +- Unique affiliate link or coupon per partner +- Attribution tracked via cookie (30-90 day window typical) +- Payout on qualifying events (first payment, monthly recurring, flat fee) + +**What makes it work:** +- Partners have existing audiences who trust them +- Content-driven promotion outlasts a single ad — a blog post with your affiliate link can generate leads for 3 years +- Commission-aligned incentives mean partners promote more when you convert better + +--- + +## Real-World Program Patterns + +### Pattern 1: Double-Sided Reward (Dropbox Model) +**How it worked:** Refer a friend = 500MB for you + 500MB for them. + +**Why it worked:** +- Both sides had skin in the game +- The reward was intrinsic to the product (not a discount on something unrelated) +- The referred user's incentive made them more likely to complete registration +- Referrer felt generous, not transactional + +**When to use:** When your core product has a natural "shareable" dimension. Digital products with quantity-based rewards (storage, credits, messages, seats) are perfect candidates. + +**When NOT to use:** When your product has no natural unit to give. Don't give $10 Amazon gift cards just to copy Dropbox — tie the reward to product value. + +--- + +### Pattern 2: Tiered Ambassador Program (Referral + Status) +**How it works:** Customers unlock higher reward tiers by referring more users. Top tier gets named ambassador status, exclusive access, or direct relationship with the company. + +**Example structure:** +``` +Bronze (1-2 referrals): $20 credit per referral +Silver (3-9 referrals): $30 credit per referral + priority support +Gold (10+ referrals): $50 credit per referral + product advisory board invite + named case study +``` + +**Why it works:** For highly enthusiastic customers, status beats cash. Naming someone an "ambassador" triggers identity — they become advocates rather than just referrers. + +**When to use:** Strong community around the product. Developer tools, creative SaaS, agency tools where practitioners identify with the category. + +--- + +### Pattern 3: Milestone Trigger (Conditional Reward) +**How it works:** Reward is not given at signup — it's given when the referred user reaches a specific milestone. + +**Example:** +- "Your friend gets $50 when they make their first withdrawal" +- "You get 1 free month when your referral upgrades to a paid plan" + +**Why it works:** Referred users are incentivized to actually use the product to unlock the reward. Referrers are incentivized to encourage their referral to stay active. Reduces reward fraud (fake accounts). + +**When to use:** High-volume consumer products where gaming the system is a real risk. Financial services, marketplaces, usage-based products. + +--- + +### Pattern 4: Cohort-Based Referral Window +**How it works:** Referral rewards expire if the referred user doesn't convert within a set window. + +**Standard windows:** +- B2C: 7–14 days (high intent = fast decision) +- B2B SMB: 30 days +- B2B Enterprise: 90+ days (longer evaluation cycles) + +**Why it matters:** Open-ended referral attribution creates accounting complexity and gaming risk. Time-bounded windows create urgency and clean accounting. + +--- + +### Pattern 5: Affiliate Commission Tiers by Partner Type + +Not all affiliates are equal. Tiering by partner type lets you reward your best partners appropriately. + +**Example tier structure:** +``` +Standard affiliates (bloggers, small newsletters): +└── 20% of first payment, 30-day cookie + +Premium affiliates (high-traffic publications, active agencies): +└── 25% MRR for 12 months, 60-day cookie, co-marketing support + +Strategic partners (complementary SaaS, resellers): +└── 30% MRR ongoing, white-label option, dedicated account manager +``` + +**Key principle:** The higher the traffic quality and deal size, the higher the commission can go. An agency that sends you 5 enterprise deals per year is worth more than 100 bloggers who send you occasional trials. + +--- + +### Pattern 6: Product-Embedded Referral (Virality by Design) + +The referral mechanism is built into the product experience, not bolted on as a "refer a friend" email. + +**Examples:** +- Calendar invite: "Powered by [Product]" link in email footer that every invitee sees +- "Created with [Product]" watermark on exported documents (Canva, Notion) +- "Invite your team" prompt mid-onboarding with a clear reason to do it now +- "Share your results" on high-value output screens + +**Why it works:** The referral happens at the moment of peak product value, using the product itself as the promotional vehicle. No separate "referral program" needed. + +**When to use:** Productivity tools, creative tools, any product that produces shareable output. Build this alongside the product, not as an afterthought. + +--- + +### Pattern 7: B2B Account-Based Referral + +In B2B, referrals are more targeted — you're asking for warm intros to specific account types, not a spray-and-pray link share. + +**How it works:** +- Identify which customers have the broadest networks in your ICP +- Equip them with a referral kit (email template, one-pager, LinkedIn intro script) +- Reward for completed intro + reward uplift for closed deal +- Keep the referrer informed on progress (increases likelihood of them championing internally) + +**Example mechanics:** +``` +Step 1: Customer completes an intro call → $200 gift card +Step 2: Intro converts to a demo → $500 additional +Step 3: Demo converts to a deal → 10% of first year's contract value (capped at $5,000) +``` + +**Why it works:** High-trust referrals from B2B customers often shorten sales cycles dramatically. The referrer becomes an internal champion at the referred company, not just a warm lead. + +--- + +## Share Mechanics Deep Dive + +### The 3 Share Channels That Drive Volume + +| Channel | How It Works | Best For | +|---------|------------|---------| +| Personal referral link | User copies/shares their link to a friend | Universal | +| Direct email invite | User enters friend's email, platform sends invite on their behalf | Consumer, prosumer | +| Social share | One-click to Twitter, LinkedIn, WhatsApp with pre-filled message | Consumer, community products | + +### Pre-Written Share Messages — What Works + +**Works:** +> "I've been using [Product] for 3 months and it's saved me hours on [specific task]. You can get started free using my link: [link]" + +**Doesn't work:** +> "Check out this amazing product I use! [link]" + +The difference: specificity and personal endorsement. Pre-fill your share messages with the actual benefit, not generic praise. Make it easy for users to be specific advocates, not just sharers. + +--- + +## Fraud Prevention + +Referral fraud happens when users game the system (fake accounts, self-referrals, incentivized referrals). + +**Minimum safeguards:** +- Email verification required before reward is credited +- Device fingerprinting to detect same-device self-referral +- Reward withheld until referred user completes a qualifying action (first payment, 7-day active use) +- Rate limiting on referral link sends per user + +**Warning signs of fraud:** +- Referral conversion rate suddenly spikes above 60% (normal is 15–30%) +- High number of referrals from a single user (>20 in a week) +- Referrals with similar email patterns or same IP block + +--- + +## Technology Options + +### For Customer Referral Programs + +| Tool | Best For | Pricing Tier | +|------|---------|-------------| +| ReferralHero | SMB SaaS, waitlist referral | $49–$199/mo | +| Viral Loops | Consumer apps, e-commerce | $49–$199/mo | +| Referral Rock | Mid-market SaaS | $175–$800/mo | +| Custom (in-house) | When you want full control + have engineering | Build cost only | + +### For Affiliate Programs + +| Tool | Best For | Notes | +|------|---------|-------| +| Rewardful | SaaS, Stripe-based | $49–$299/mo, easiest Stripe integration | +| PartnerStack | B2B SaaS | $500+/mo, best for partner tiers | +| Impact | Enterprise, multi-channel | Custom pricing | +| ShareASale | E-commerce, consumer | 20% of commissions + fees | + +### For Product-Embedded Viral Loops +Build these in-house. The "powered by" footer, "created with" watermark, or "invite your team" prompt needs to be native to the product experience, not a third-party widget. diff --git a/marketing-skill/referral-program/scripts/referral_roi_calculator.py b/marketing-skill/referral-program/scripts/referral_roi_calculator.py new file mode 100644 index 0000000..31325f3 --- /dev/null +++ b/marketing-skill/referral-program/scripts/referral_roi_calculator.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python3 +""" +referral_roi_calculator.py — Calculates referral program ROI. + +Models the economics of a referral program given your LTV, CAC, referral rate, +reward cost, and conversion rate. Outputs program ROI, break-even referral rate, +and optimal reward sizing. + +Usage: + python3 referral_roi_calculator.py # runs embedded sample + python3 referral_roi_calculator.py params.json # uses your params + echo '{"ltv": 1200, "cac": 300}' | python3 referral_roi_calculator.py + +JSON input format: + { + "ltv": 1200, # Customer Lifetime Value ($) + "cac": 300, # Current avg CAC via paid channels ($) + "active_users": 500, # Active users who could refer + "referral_rate": 0.05, # % of active users who refer each month (0.05 = 5%) + "referrals_per_referrer": 2.5, # Avg referrals sent per active referrer + "referral_conversion_rate": 0.20, # % of referrals who become customers + "referrer_reward": 50, # Reward paid to referrer per successful referral ($) + "referred_reward": 30, # Reward paid to referred user (0 if single-sided) ($) + "program_overhead_monthly": 200, # Platform + ops cost per month ($) + "churn_rate_monthly": 0.03, # Monthly churn rate (used for LTV validation) + "months_to_model": 12 # How many months to project + } +""" + +import json +import sys +from collections import OrderedDict + + +# --------------------------------------------------------------------------- +# Core calculation functions +# --------------------------------------------------------------------------- + +def calculate_referrals_per_month(params): + """How many successful referrals per month?""" + active_users = params["active_users"] + referral_rate = params["referral_rate"] + referrals_per_referrer = params["referrals_per_referrer"] + conversion_rate = params["referral_conversion_rate"] + + active_referrers = active_users * referral_rate + referrals_sent = active_referrers * referrals_per_referrer + conversions = referrals_sent * conversion_rate + + return { + "active_referrers": round(active_referrers, 1), + "referrals_sent": round(referrals_sent, 1), + "new_customers_per_month": round(conversions, 1), + } + + +def calculate_monthly_program_cost(params, new_customers_per_month): + """Total cost of running the program for one month.""" + reward_per_conversion = params["referrer_reward"] + params["referred_reward"] + reward_cost = reward_per_conversion * new_customers_per_month + overhead = params["program_overhead_monthly"] + return { + "reward_cost": round(reward_cost, 2), + "overhead_cost": round(overhead, 2), + "total_cost": round(reward_cost + overhead, 2), + "reward_per_conversion": round(reward_per_conversion, 2), + } + + +def calculate_monthly_revenue(params, new_customers_per_month): + """Revenue generated from referred customers in the first month.""" + # First-month value is LTV / (1 / monthly_churn) = LTV * monthly_churn + # Simplified: use LTV * monthly_churn as first-month expected revenue contribution + # More conservative: just count as one acquisition with full LTV expected + ltv = params["ltv"] + revenue = new_customers_per_month * ltv + return round(revenue, 2) + + +def calculate_cac_via_referral(cost_data, new_customers_per_month): + if new_customers_per_month == 0: + return float('inf') + return round(cost_data["total_cost"] / new_customers_per_month, 2) + + +def calculate_break_even_referral_rate(params): + """ + What referral rate do we need so that CAC via referral equals + reward_per_conversion + overhead_per_customer_amortized? + + We want: total_cost / new_customers = cac_target + Solving for referral_rate where cac_target = 50% of paid CAC (our target) + """ + target_cac = params["cac"] * 0.5 # goal: 50% of current CAC + ltv = params["ltv"] + active_users = params["active_users"] + referrals_per_referrer = params["referrals_per_referrer"] + conversion_rate = params["referral_conversion_rate"] + reward_per_conversion = params["referrer_reward"] + params["referred_reward"] + overhead = params["program_overhead_monthly"] + + # CAC_referral = (reward Ɨ conversions + overhead) / conversions + # = reward + overhead/conversions + # Solve: target_cac = reward + overhead / (active_users Ɨ rate Ɨ referrals_per_referrer Ɨ conversion_rate) + # conversions_needed = overhead / (target_cac - reward) + + if target_cac <= reward_per_conversion: + return None # impossible — reward alone exceeds target CAC + + conversions_needed = overhead / (target_cac - reward_per_conversion) + referral_rate_needed = conversions_needed / (active_users * referrals_per_referrer * conversion_rate) + + return round(referral_rate_needed, 4) + + +def calculate_optimal_reward(params): + """ + What's the maximum reward you can afford while keeping CAC via referral + under 60% of paid CAC? + + max_total_reward = 0.60 Ɨ paid_CAC (using conversion-amortized overhead) + """ + target_cac = params["cac"] * 0.60 + overhead_amortized = params["program_overhead_monthly"] / max( + calculate_referrals_per_month(params)["new_customers_per_month"], 1 + ) + max_reward = target_cac - overhead_amortized + + # Split recommendation: 60% referrer, 40% referred (double-sided) + referrer_portion = round(max_reward * 0.60, 2) + referred_portion = round(max_reward * 0.40, 2) + + return { + "max_total_reward": round(max(max_reward, 0), 2), + "recommended_referrer_reward": max(referrer_portion, 0), + "recommended_referred_reward": max(referred_portion, 0), + "reward_as_pct_ltv": round((max_reward / params["ltv"]) * 100, 1) if params["ltv"] > 0 else 0, + } + + +def calculate_roi(params): + """ + Program ROI over the modeling period. + ROI = (Revenue from referred customers - Program costs) / Program costs + """ + months = params["months_to_model"] + monthly = calculate_referrals_per_month(params) + new_customers = monthly["new_customers_per_month"] + costs = calculate_monthly_program_cost(params, new_customers) + + total_cost = costs["total_cost"] * months + total_ltv_generated = new_customers * params["ltv"] * months + net_benefit = total_ltv_generated - total_cost + roi = (net_benefit / total_cost * 100) if total_cost > 0 else 0 + + return { + "total_cost": round(total_cost, 2), + "total_ltv_generated": round(total_ltv_generated, 2), + "net_benefit": round(net_benefit, 2), + "roi_pct": round(roi, 1), + } + + +def build_monthly_projection(params): + """Build a month-by-month projection table.""" + months = params["months_to_model"] + monthly = calculate_referrals_per_month(params) + new_per_month = monthly["new_customers_per_month"] + costs = calculate_monthly_program_cost(params, new_per_month) + ltv = params["ltv"] + + rows = [] + cumulative_customers = 0 + cumulative_cost = 0 + cumulative_revenue = 0 + + for m in range(1, months + 1): + cumulative_customers += new_per_month + month_cost = costs["total_cost"] + month_revenue = new_per_month * ltv + cumulative_cost += month_cost + cumulative_revenue += month_revenue + cumulative_net = cumulative_revenue - cumulative_cost + + rows.append({ + "month": m, + "new_customers": round(new_per_month, 1), + "cumulative_customers": round(cumulative_customers, 1), + "monthly_cost": round(month_cost, 2), + "cumulative_cost": round(cumulative_cost, 2), + "monthly_ltv": round(month_revenue, 2), + "cumulative_net": round(cumulative_net, 2), + }) + + return rows + + +def find_break_even_month(projection): + for row in projection: + if row["cumulative_net"] >= 0: + return row["month"] + return None + + +# --------------------------------------------------------------------------- +# Formatting +# --------------------------------------------------------------------------- + +def format_currency(value): + return f"${value:,.2f}" + + +def format_pct(value): + return f"{value:.1f}%" + + +def print_report(params, results): + monthly = results["monthly_referrals"] + costs = results["monthly_costs"] + cac = results["cac_via_referral"] + roi = results["roi"] + break_even_rate = results["break_even_referral_rate"] + optimal_reward = results["optimal_reward"] + projection = results["monthly_projection"] + break_even_month = results["break_even_month"] + + paid_cac = params["cac"] + ltv = params["ltv"] + + print("\n" + "=" * 60) + print("REFERRAL PROGRAM ROI CALCULATOR") + print("=" * 60) + + print("\nšŸ“Š INPUT PARAMETERS") + print(f" LTV per customer: {format_currency(ltv)}") + print(f" Current paid CAC: {format_currency(paid_cac)}") + print(f" Active users: {params['active_users']:,}") + print(f" Referral rate (monthly): {format_pct(params['referral_rate'] * 100)}") + print(f" Referrals per referrer: {params['referrals_per_referrer']}") + print(f" Referral conversion rate: {format_pct(params['referral_conversion_rate'] * 100)}") + print(f" Referrer reward: {format_currency(params['referrer_reward'])}") + print(f" Referred user reward: {format_currency(params['referred_reward'])}") + print(f" Program overhead/month: {format_currency(params['program_overhead_monthly'])}") + + print("\nšŸ“ˆ MONTHLY PERFORMANCE (STEADY STATE)") + print(f" Active referrers/month: {monthly['active_referrers']}") + print(f" Referrals sent/month: {monthly['referrals_sent']}") + print(f" New customers/month: {monthly['new_customers_per_month']}") + print(f" Monthly program cost: {format_currency(costs['total_cost'])}") + print(f" ↳ Reward cost: {format_currency(costs['reward_cost'])}") + print(f" ↳ Overhead: {format_currency(costs['overhead_cost'])}") + print(f" CAC via referral: {format_currency(cac)}") + print(f" Paid CAC: {format_currency(paid_cac)}") + savings_pct = ((paid_cac - cac) / paid_cac * 100) if paid_cac > 0 else 0 + savings_label = f"{savings_pct:.0f}% cheaper than paid" if cac < paid_cac else "āš ļø More expensive than paid" + print(f" CAC comparison: {savings_label}") + + print(f"\nšŸ’° ROI OVER {params['months_to_model']} MONTHS") + print(f" Total program cost: {format_currency(roi['total_cost'])}") + print(f" Total LTV generated: {format_currency(roi['total_ltv_generated'])}") + print(f" Net benefit: {format_currency(roi['net_benefit'])}") + print(f" Program ROI: {format_pct(roi['roi_pct'])}") + + if break_even_month: + print(f" Break-even: Month {break_even_month}") + else: + print(f" Break-even: Not reached in {params['months_to_model']} months") + + print("\nšŸŽÆ OPTIMIZATION INSIGHTS") + if break_even_rate: + current_rate = params["referral_rate"] + rate_gap = break_even_rate - current_rate + if rate_gap > 0: + print(f" Break-even referral rate: {format_pct(break_even_rate * 100)} " + f"(you're at {format_pct(current_rate * 100)} — need +{format_pct(rate_gap * 100)})") + else: + print(f" Break-even referral rate: {format_pct(break_even_rate * 100)} āœ… Already above break-even") + else: + print(f" Break-even referral rate: āš ļø Reward alone exceeds target CAC — reduce reward or increase LTV") + + print(f"\n Optimal reward sizing (to keep CAC at ≤60% of paid CAC):") + print(f" Max total reward/referral: {format_currency(optimal_reward['max_total_reward'])}") + print(f" Recommended referrer: {format_currency(optimal_reward['recommended_referrer_reward'])}") + print(f" Recommended referred user: {format_currency(optimal_reward['recommended_referred_reward'])}") + print(f" Reward as % of LTV: {format_pct(optimal_reward['reward_as_pct_ltv'])}") + + current_total_reward = params["referrer_reward"] + params["referred_reward"] + if current_total_reward > optimal_reward["max_total_reward"] and optimal_reward["max_total_reward"] > 0: + print(f" āš ļø Your current reward ({format_currency(current_total_reward)}) " + f"exceeds optimal ({format_currency(optimal_reward['max_total_reward'])})") + elif optimal_reward["max_total_reward"] > 0: + print(f" āœ… Your current reward ({format_currency(current_total_reward)}) is within optimal range") + + print(f"\nšŸ“… MONTHLY PROJECTION (first {min(6, len(projection))} months)") + print(f" {'Month':>5} {'New Cust':>9} {'Cumul Cust':>11} {'Monthly Cost':>13} {'Cumul Net':>11}") + print(f" {'-'*5} {'-'*9} {'-'*11} {'-'*13} {'-'*11}") + for row in projection[:6]: + net_str = format_currency(row["cumulative_net"]) + if row["cumulative_net"] < 0: + net_str = f"({format_currency(abs(row['cumulative_net']))})" + print(f" {row['month']:>5} {row['new_customers']:>9.1f} {row['cumulative_customers']:>11.1f} " + f"{format_currency(row['monthly_cost']):>13} {net_str:>11}") + + print("\n" + "=" * 60) + + +# --------------------------------------------------------------------------- +# Default parameters + sample +# --------------------------------------------------------------------------- + +DEFAULT_PARAMS = { + "ltv": 1200, + "cac": 350, + "active_users": 800, + "referral_rate": 0.06, + "referrals_per_referrer": 2.0, + "referral_conversion_rate": 0.20, + "referrer_reward": 50, + "referred_reward": 30, + "program_overhead_monthly": 200, + "churn_rate_monthly": 0.04, + "months_to_model": 12, +} + + +def run(params): + monthly = calculate_referrals_per_month(params) + new_customers = monthly["new_customers_per_month"] + costs = calculate_monthly_program_cost(params, new_customers) + cac = calculate_cac_via_referral(costs, new_customers) + break_even_rate = calculate_break_even_referral_rate(params) + optimal_reward = calculate_optimal_reward(params) + roi = calculate_roi(params) + projection = build_monthly_projection(params) + break_even_month = find_break_even_month(projection) + + results = { + "monthly_referrals": monthly, + "monthly_costs": costs, + "cac_via_referral": cac, + "break_even_referral_rate": break_even_rate, + "optimal_reward": optimal_reward, + "roi": roi, + "monthly_projection": projection, + "break_even_month": break_even_month, + } + + return results + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + params = None + + if len(sys.argv) > 1: + try: + with open(sys.argv[1]) as f: + params = json.load(f) + except Exception as e: + print(f"Error reading file: {e}", file=sys.stderr) + sys.exit(1) + elif not sys.stdin.isatty(): + raw = sys.stdin.read().strip() + if raw: + try: + params = json.loads(raw) + except Exception as e: + print(f"Error reading stdin: {e}", file=sys.stderr) + sys.exit(1) + else: + print("No input provided — running with sample parameters.\n") + params = DEFAULT_PARAMS + else: + print("No input provided — running with sample parameters.\n") + params = DEFAULT_PARAMS + + # Fill in defaults for any missing keys + for k, v in DEFAULT_PARAMS.items(): + params.setdefault(k, v) + + results = run(params) + print_report(params, results) + + # JSON output + json_output = { + "inputs": params, + "results": { + "monthly_new_customers": results["monthly_referrals"]["new_customers_per_month"], + "cac_via_referral": results["cac_via_referral"], + "program_roi_pct": results["roi"]["roi_pct"], + "break_even_month": results["break_even_month"], + "break_even_referral_rate": results["break_even_referral_rate"], + "optimal_total_reward": results["optimal_reward"]["max_total_reward"], + "net_benefit_12mo": results["roi"]["net_benefit"], + } + } + + print("\n--- JSON Output ---") + print(json.dumps(json_output, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/schema-markup/SKILL.md b/marketing-skill/schema-markup/SKILL.md new file mode 100644 index 0000000..96f0d8e --- /dev/null +++ b/marketing-skill/schema-markup/SKILL.md @@ -0,0 +1,233 @@ +--- +name: schema-markup +description: "When the user wants to implement, audit, or validate structured data (schema markup) on their website. Use when the user mentions 'structured data,' 'schema.org,' 'JSON-LD,' 'rich results,' 'rich snippets,' 'schema markup,' 'FAQ schema,' 'Product schema,' 'HowTo schema,' or 'structured data errors in Search Console.' Also use when someone asks why their content isn't showing rich results or wants to improve AI search visibility. NOT for general SEO audits (use seo-audit) or technical SEO crawl issues (use site-architecture)." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Schema Markup Implementation + +You are an expert in structured data and schema.org markup. Your goal is to help implement, audit, and validate JSON-LD schema that earns rich results in Google, improves click-through rates, and makes content legible to AI search systems. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. Use that context and only ask for what's missing. + +Gather this context: + +### 1. Current State +- Do they have any existing schema markup? (Check source, GSC Coverage report, or run the validator script) +- Any rich results currently showing in Google? +- Any structured data errors in Search Console? + +### 2. Site Details +- CMS platform (WordPress, Webflow, custom, etc.) +- Page types that need markup (homepage, articles, products, FAQ, local business) +- Can they edit `` tags, or do they need a plugin/GTM? + +### 3. Goals +- Rich results target (FAQ dropdowns, star ratings, breadcrumbs, HowTo steps, etc.) +- AI search visibility (getting cited in AI Overviews, Perplexity, etc.) +- Fix existing errors vs implement net new + +--- + +## How This Skill Works + +### Mode 1: Audit Existing Markup +When they have a site and want to know what schema exists and what's broken. + +1. Run `scripts/schema_validator.py` on the page HTML (or paste URL for manual check) +2. Review Google Search Console → Enhancements → check all schema error reports +3. Cross-reference against `references/schema-types-guide.md` for required fields +4. Deliver audit report: what's present, what's broken, what's missing, priority order + +### Mode 2: Implement New Schema +When they need to add structured data to pages — from scratch or to a new page type. + +1. Identify the page type and the right schema types (see schema selection table below) +2. Pull the JSON-LD pattern from `references/implementation-patterns.md` +3. Populate with real page content +4. Advise on placement (inline ` + +``` + +Multiple schema blocks per page are fine — use separate ` + + +``` + +Or combine into a single `@graph` array: + +```html + +``` + +Both approaches are valid. `@graph` is cleaner for sites with many schema types per page. + +--- + +## WebSite (Homepage Only) + +```json +{ + "@context": "https://schema.org", + "@type": "WebSite", + "url": "https://YOURDOMAIN.COM", + "name": "SITE_NAME", + "potentialAction": { + "@type": "SearchAction", + "target": { + "@type": "EntryPoint", + "urlTemplate": "https://YOURDOMAIN.COM/search?q={search_term_string}" + }, + "query-input": "required name=search_term_string" + } +} +``` + +**Note:** Only add this if you have a working internal search at the URL template path. + +--- + +## Duration Format Reference (ISO 8601) + +| Duration | ISO 8601 | +|----------|----------| +| 30 minutes | `PT30M` | +| 1 hour | `PT1H` | +| 1 hour 30 minutes | `PT1H30M` | +| 2 hours 15 minutes | `PT2H15M` | +| 5 minutes 30 seconds | `PT5M30S` | +| 12 minutes 30 seconds | `PT12M30S` | + +## Availability Values Reference + +Always use the full schema.org URL — not just the word. + +| Status | Value | +|--------|-------| +| In stock | `https://schema.org/InStock` | +| Out of stock | `https://schema.org/OutOfStock` | +| Pre-order | `https://schema.org/PreOrder` | +| Back order | `https://schema.org/BackOrder` | +| Limited availability | `https://schema.org/LimitedAvailability` | +| Discontinued | `https://schema.org/Discontinued` | diff --git a/marketing-skill/schema-markup/references/schema-types-guide.md b/marketing-skill/schema-markup/references/schema-types-guide.md new file mode 100644 index 0000000..dfafb47 --- /dev/null +++ b/marketing-skill/schema-markup/references/schema-types-guide.md @@ -0,0 +1,285 @@ +# Schema Types Guide + +A practitioner's reference for schema.org types — what they do, what fields matter, and what Google actually uses for rich results. + +--- + +## How to Read This Guide + +Each type lists: +- **Purpose** — what it tells search engines +- **Rich result** — what you can earn in Google (if anything) +- **Required fields** — missing these = no rich result +- **Recommended fields** — fill these to maximize eligibility +- **Gotchas** — the field mistakes that waste everyone's time + +--- + +## Article + +**Purpose:** Marks editorial content — news, blog posts, opinion pieces. + +**Rich result:** Article rich result (expanded card in Google News, Discover, and some search results). Also influences AI Overview citation likelihood. + +**Required fields:** +- `headline` — the article title (max 110 characters for display) +- `image` — at least one image, minimum 1200px wide for rich results +- `datePublished` — ISO 8601 format +- `author` — Person or Organization type + +**Recommended fields:** +- `dateModified` — keep current; freshness signal +- `publisher` — Organization type with `logo` +- `description` — 150-300 char summary +- `url` — canonical URL of the article + +**Subtypes:** Use `NewsArticle` for news content, `BlogPosting` for blog posts. Both inherit from Article. Google treats them similarly. + +**Gotchas:** +- `image` must be absolute URL. Relative URLs fail silently. +- `headline` should match the visible `

` on the page. Google cross-validates. +- Multiple `author` values are valid — use an array: `"author": [{"@type": "Person", "name": "..."}, ...]` + +--- + +## HowTo + +**Purpose:** Step-by-step instructions for completing a task. + +**Rich result:** HowTo steps appear directly in Google search results as expandable steps (desktop and mobile). + +**Required fields:** +- `name` — title of the how-to (e.g., "How to change a bike tire") +- `step` — array of HowToStep objects, each with: + - `name` — step title + - `text` — step instructions + +**Recommended fields:** +- `image` — overall how-to image +- `totalTime` — ISO 8601 duration (e.g., `"PT30M"` = 30 minutes) +- `tool` — list of tools needed (HowToTool type) +- `supply` — list of materials (HowToSupply type) +- `estimatedCost` — MonetaryAmount type + +**Gotchas:** +- Steps must appear on the page in readable form — hidden steps fail Google's content matching. +- HowToStep `image` is different from the main `image` — each step can have its own. +- Don't use HowTo for recipe content — use Recipe type instead. + +--- + +## FAQPage + +**Purpose:** A page containing a list of frequently asked questions and their answers. + +**Rich result:** FAQ accordion dropdowns directly in Google search results. High-value visibility — shows your Q&A without clicking. + +**Required fields:** +- `mainEntity` — array of Question objects, each with: + - `name` — the question text + - `acceptedAnswer` — Answer type with `text` field containing the answer + +**Recommended fields:** +- No additional fields required — this type is simple by design. + +**Gotchas:** +- Both the question AND the answer must be visible on the page. Google explicitly checks. +- Answers with HTML tags (links, bold) may or may not render — keep answers as clean text. +- Google limits FAQ rich results to 3-5 Q&A pairs visible in search, even if you have more. +- Don't use FAQPage for Q&A that requires a login to view — Google can't verify it. + +--- + +## Product + +**Purpose:** Describes a product for sale, including pricing, availability, and reviews. + +**Rich result:** Product rich results with price, availability, rating stars. Eligible for Google Shopping surfaces. + +**Required fields (for rich results):** +- `name` — product name +- `offers` — Offer type with: + - `price` — numeric price (not formatted with currency symbol) + - `priceCurrency` — ISO 4217 currency code (e.g., `"USD"`, `"EUR"`) + - `availability` — schema.org availability URL (e.g., `"https://schema.org/InStock"`) + +**Recommended fields:** +- `image` — product image(s), absolute URLs +- `description` — product description +- `sku` — stock-keeping unit +- `brand` — Brand or Organization type +- `aggregateRating` — AggregateRating type (required for star ratings) +- `review` — individual Review objects + +**AggregateRating required fields:** +- `ratingValue` — average rating +- `reviewCount` — number of reviews (or `ratingCount`) +- `bestRating` — maximum rating value (default: 5) + +**Gotchas:** +- Price must be a number, not a string: `"price": 29.99` not `"price": "$29.99"` +- `availability` must use the full schema.org URL, not just "InStock" +- If you show ratings, you must have real reviews — fabricated ratings violate Google's policies +- Price shown in schema must match the price visible on the page + +--- + +## Organization + +**Purpose:** Identifies your company/organization as an entity to search engines and knowledge graphs. + +**Rich result:** Knowledge panel information, logo in search results, organization entity recognition. + +**Required fields:** +- `name` — official organization name +- `url` — organization website + +**Recommended fields:** +- `logo` — ImageObject with absolute URL to logo +- `sameAs` — array of URLs to your organization's profiles elsewhere (LinkedIn, Twitter/X, Facebook, Crunchbase, Wikidata, Wikipedia) +- `contactPoint` — ContactPoint type with `telephone` and `contactType` +- `address` — PostalAddress type +- `foundingDate` — year or ISO date +- `numberOfEmployees` — QuantitativeValue type +- `description` — brief company description + +**Gotchas:** +- `sameAs` is the most important field for entity establishment — the more authoritative sources you include, the stronger the entity signal. +- Use `https://www.wikidata.org/wiki/Q[ID]` in `sameAs` if your company has a Wikidata entry. +- Only one Organization schema per domain — put it on every page if you want, but keep it consistent. + +--- + +## LocalBusiness + +**Purpose:** Extends Organization for businesses with a physical location. Used for local search results and map listings. + +**Rich result:** Local knowledge panel, map pin details, opening hours, star ratings in local results. + +**Required fields:** +- `name` — business name +- `address` — PostalAddress with `streetAddress`, `addressLocality`, `postalCode`, `addressCountry` + +**Recommended fields:** +- `telephone` — with country code (e.g., `"+1-800-555-1234"`) +- `openingHoursSpecification` — array by day with opens/closes times +- `geo` — GeoCoordinates with `latitude` and `longitude` +- `priceRange` — string like `"$$"` or `"€€"` or `"$10-$50"` +- `image` — photos of the business +- `url` — website URL +- `aggregateRating` — if you have reviews + +**Subtypes:** Use the most specific subtype available. `Restaurant`, `MedicalClinic`, `LegalService`, `Hotel` all extend LocalBusiness and unlock additional rich result fields. + +**Gotchas:** +- Address must exactly match what's in Google Business Profile for local SEO to connect. +- Hours must use 24-hour format in `openingHoursSpecification`. +- If closed on a day, omit that day rather than using `"00:00"`. + +--- + +## BreadcrumbList + +**Purpose:** Represents the breadcrumb trail shown on a page — the hierarchy from homepage to current page. + +**Rich result:** Breadcrumb path shown in Google search results instead of the raw URL. Cleaner appearance, more clicks. + +**Required fields:** +- `itemListElement` — array of ListItem objects, each with: + - `position` — integer starting at 1 + - `name` — breadcrumb label + - `item` — absolute URL of that breadcrumb level + +**Recommended fields:** +None required beyond the above. + +**Gotchas:** +- Positions must be sequential integers starting at 1. Gaps or non-integers fail validation. +- The last breadcrumb (current page) may omit `item` since it's the current URL — but including it is safer. +- Breadcrumb schema must match the visible breadcrumbs on the page. +- Use on every non-homepage if you have visible breadcrumbs. + +--- + +## VideoObject + +**Purpose:** Describes an embedded or hosted video. + +**Rich result:** Video carousels, video badges on search results, timestamp markers that appear in results. + +**Required fields:** +- `name` — video title +- `description` — video description +- `thumbnailUrl` — absolute URL to thumbnail image +- `uploadDate` — ISO 8601 date + +**Recommended fields:** +- `duration` — ISO 8601 duration (e.g., `"PT12M30S"` = 12 min 30 sec) +- `contentUrl` — direct URL to the video file +- `embedUrl` — URL of the embeddable player +- `hasPart` — array of Clip objects with start/end times for key moments +- `interactionStatistic` — view count (InteractionCounter type) + +**Key moments (Clip type for timestamp markers):** +```json +"hasPart": [ + { + "@type": "Clip", + "name": "Introduction", + "startOffset": 0, + "endOffset": 60, + "url": "https://example.com/video#t=0" + } +] +``` + +**Gotchas:** +- `thumbnailUrl` must resolve to an actual image — Google checks it. +- Without `contentUrl` or `embedUrl`, Google may not index the video. +- Videos behind login/paywall are not eligible for video rich results. + +--- + +## WebSite + +**Purpose:** Identifies your website and enables the sitelinks search box in Google results. + +**Rich result:** Sitelinks search box — a search field that appears under your domain in branded searches. + +**Required fields:** +- `url` — homepage URL +- `potentialAction` — SearchAction type for sitelinks search box: + ```json + "potentialAction": { + "@type": "SearchAction", + "target": { + "@type": "EntryPoint", + "urlTemplate": "https://example.com/search?q={search_term_string}" + }, + "query-input": "required name=search_term_string" + } + ``` + +**Gotchas:** +- Only put WebSite schema on the homepage. +- The `urlTemplate` must point to a working search endpoint. +- Sitelinks search box only appears for branded queries — this won't help you rank for generic terms. + +--- + +## Schema Eligibility Summary + +Quick-reference: what actually earns a rich result vs what's just entity data. + +| Schema Type | Rich Result Available | Rich Result Type | +|-------------|----------------------|-----------------| +| Article | āœ… | Top stories card, article rich result | +| HowTo | āœ… | Step-by-step in SERP | +| FAQPage | āœ… | Accordion Q&A in SERP | +| Product + Offer | āœ… | Price/availability badge | +| Product + AggregateRating | āœ… | Star ratings | +| LocalBusiness | āœ… | Local knowledge panel | +| BreadcrumbList | āœ… | Breadcrumb path in SERP | +| VideoObject | āœ… | Video carousel, key moments | +| Organization | āš ļø | Knowledge panel (not guaranteed) | +| WebSite | āš ļø | Sitelinks search box (not guaranteed) | diff --git a/marketing-skill/schema-markup/scripts/schema_validator.py b/marketing-skill/schema-markup/scripts/schema_validator.py new file mode 100644 index 0000000..ce334c3 --- /dev/null +++ b/marketing-skill/schema-markup/scripts/schema_validator.py @@ -0,0 +1,430 @@ +#!/usr/bin/env python3 +""" +schema_validator.py — Extracts and validates JSON-LD structured data from HTML. + +Usage: + python3 schema_validator.py [file.html] + cat page.html | python3 schema_validator.py + +If no file is provided, runs on embedded sample HTML for demonstration. + +Output: Human-readable validation report + JSON summary. +Scoring: 0-100 per schema block based on required/recommended field coverage. +""" + +import json +import sys +import re +import select +from html.parser import HTMLParser +from typing import List, Dict, Any, Optional + + +# ─── Required and recommended fields per schema type ───────────────────────── + +SCHEMA_RULES: Dict[str, Dict[str, List[str]]] = { + "Article": { + "required": ["headline", "image", "datePublished", "author"], + "recommended": ["dateModified", "publisher", "description", "url", "mainEntityOfPage"], + }, + "BlogPosting": { + "required": ["headline", "image", "datePublished", "author"], + "recommended": ["dateModified", "publisher", "description", "url", "mainEntityOfPage"], + }, + "NewsArticle": { + "required": ["headline", "image", "datePublished", "author"], + "recommended": ["dateModified", "publisher", "description", "url"], + }, + "HowTo": { + "required": ["name", "step"], + "recommended": ["description", "image", "totalTime", "tool", "supply", "estimatedCost"], + }, + "FAQPage": { + "required": ["mainEntity"], + "recommended": [], + }, + "Product": { + "required": ["name", "offers"], + "recommended": ["description", "image", "sku", "brand", "aggregateRating"], + }, + "Organization": { + "required": ["name", "url"], + "recommended": ["logo", "sameAs", "contactPoint", "description", "foundingDate"], + }, + "LocalBusiness": { + "required": ["name", "address"], + "recommended": ["telephone", "openingHoursSpecification", "geo", "priceRange", "image", "url"], + }, + "BreadcrumbList": { + "required": ["itemListElement"], + "recommended": [], + }, + "VideoObject": { + "required": ["name", "description", "thumbnailUrl", "uploadDate"], + "recommended": ["duration", "contentUrl", "embedUrl", "interactionStatistic", "hasPart"], + }, + "WebSite": { + "required": ["url"], + "recommended": ["name", "potentialAction"], + }, + "Event": { + "required": ["name", "startDate", "location"], + "recommended": ["endDate", "description", "image", "organizer", "offers"], + }, + "Recipe": { + "required": ["name", "image", "author", "datePublished"], + "recommended": ["description", "cookTime", "prepTime", "totalTime", "recipeYield", + "recipeIngredient", "recipeInstructions", "aggregateRating"], + }, +} + +KNOWN_TYPES = set(SCHEMA_RULES.keys()) + + +# ─── HTML Parser to extract JSON-LD blocks ─────────────────────────────────── + +class JSONLDExtractor(HTMLParser): + """Extracts all + + + + + + + + + +

How to Write Cold Emails That Get Replies

+

Cold email works when it sounds human...

+ + +""" + + +# ─── Main ───────────────────────────────────────────────────────────────────── + +def main(): + if len(sys.argv) > 1: + arg = sys.argv[1] + if arg == "-": + html = sys.stdin.read() + else: + try: + with open(arg, "r", encoding="utf-8") as f: + html = f.read() + except FileNotFoundError: + print(f"Error: File not found: {arg}", file=sys.stderr) + sys.exit(1) + else: + print("No file provided — running on embedded sample HTML.\n") + html = SAMPLE_HTML + + extractor = JSONLDExtractor() + extractor.feed(html) + + all_results = [] + for i, block in enumerate(extractor.blocks, start=1): + results = validate_block(block, i) + all_results.extend(results) + + print_report(all_results, html) + + # JSON output for programmatic use + summary = { + "blocks_found": len(extractor.blocks), + "schemas_validated": len(all_results), + "average_score": (sum(r.get("score", 0) for r in all_results) // len(all_results)) if all_results else 0, + "results": all_results, + } + print("\n── JSON Output ──") + print(json.dumps(summary, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/seo-audit/SKILL.md b/marketing-skill/seo-audit/SKILL.md new file mode 100644 index 0000000..730d4a3 --- /dev/null +++ b/marketing-skill/seo-audit/SKILL.md @@ -0,0 +1,437 @@ +--- +name: seo-audit +description: When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," or "SEO health check." For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema-markup. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# SEO Audit + +You are an expert in search engine optimization. Your goal is to identify SEO issues and provide actionable recommendations to improve organic search performance. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before auditing, understand: + +1. **Site Context** + - What type of site? (SaaS, e-commerce, blog, etc.) + - What's the primary business goal for SEO? + - What keywords/topics are priorities? + +2. **Current State** + - Any known issues or concerns? + - Current organic traffic level? + - Recent changes or migrations? + +3. **Scope** + - Full site audit or specific pages? + - Technical + on-page, or one focus area? + - Access to Search Console / analytics? + +--- + +## Audit Framework + +### Priority Order +1. **Crawlability & Indexation** (can Google find and index it?) +2. **Technical Foundations** (is the site fast and functional?) +3. **On-Page Optimization** (is content optimized?) +4. **Content Quality** (does it deserve to rank?) +5. **Authority & Links** (does it have credibility?) + +--- + +## Technical SEO Audit + +### Crawlability + +**Robots.txt** +- Check for unintentional blocks +- Verify important pages allowed +- Check sitemap reference + +**XML Sitemap** +- Exists and accessible +- Submitted to Search Console +- Contains only canonical, indexable URLs +- Updated regularly +- Proper formatting + +**Site Architecture** +- Important pages within 3 clicks of homepage +- Logical hierarchy +- Internal linking structure +- No orphan pages + +**Crawl Budget Issues** (for large sites) +- Parameterized URLs under control +- Faceted navigation handled properly +- Infinite scroll with pagination fallback +- Session IDs not in URLs + +### Indexation + +**Index Status** +- site:domain.com check +- Search Console coverage report +- Compare indexed vs. expected + +**Indexation Issues** +- Noindex tags on important pages +- Canonicals pointing wrong direction +- Redirect chains/loops +- Soft 404s +- Duplicate content without canonicals + +**Canonicalization** +- All pages have canonical tags +- Self-referencing canonicals on unique pages +- HTTP → HTTPS canonicals +- www vs. non-www consistency +- Trailing slash consistency + +### Site Speed & Core Web Vitals + +**Core Web Vitals** +- LCP (Largest Contentful Paint): < 2.5s +- INP (Interaction to Next Paint): < 200ms +- CLS (Cumulative Layout Shift): < 0.1 + +**Speed Factors** +- Server response time (TTFB) +- Image optimization +- JavaScript execution +- CSS delivery +- Caching headers +- CDN usage +- Font loading + +**Tools** +- PageSpeed Insights +- WebPageTest +- Chrome DevTools +- Search Console Core Web Vitals report + +### Mobile-Friendliness + +- Responsive design (not separate m. site) +- Tap target sizes +- Viewport configured +- No horizontal scroll +- Same content as desktop +- Mobile-first indexing readiness + +### Security & HTTPS + +- HTTPS across entire site +- Valid SSL certificate +- No mixed content +- HTTP → HTTPS redirects +- HSTS header (bonus) + +### URL Structure + +- Readable, descriptive URLs +- Keywords in URLs where natural +- Consistent structure +- No unnecessary parameters +- Lowercase and hyphen-separated + +--- + +## On-Page SEO Audit + +### Title Tags + +**Check for:** +- Unique titles for each page +- Primary keyword near beginning +- 50-60 characters (visible in SERP) +- Compelling and click-worthy +- Brand name placement (end, usually) + +**Common issues:** +- Duplicate titles +- Too long (truncated) +- Too short (wasted opportunity) +- Keyword stuffing +- Missing entirely + +### Meta Descriptions + +**Check for:** +- Unique descriptions per page +- 150-160 characters +- Includes primary keyword +- Clear value proposition +- Call to action + +**Common issues:** +- Duplicate descriptions +- Auto-generated garbage +- Too long/short +- No compelling reason to click + +### Heading Structure + +**Check for:** +- One H1 per page +- H1 contains primary keyword +- Logical hierarchy (H1 → H2 → H3) +- Headings describe content +- Not just for styling + +**Common issues:** +- Multiple H1s +- Skip levels (H1 → H3) +- Headings used for styling only +- No H1 on page + +### Content Optimization + +**Primary Page Content** +- Keyword in first 100 words +- Related keywords naturally used +- Sufficient depth/length for topic +- Answers search intent +- Better than competitors + +**Thin Content Issues** +- Pages with little unique content +- Tag/category pages with no value +- Doorway pages +- Duplicate or near-duplicate content + +### Image Optimization + +**Check for:** +- Descriptive file names +- Alt text on all images +- Alt text describes image +- Compressed file sizes +- Modern formats (WebP) +- Lazy loading implemented +- Responsive images + +### Internal Linking + +**Check for:** +- Important pages well-linked +- Descriptive anchor text +- Logical link relationships +- No broken internal links +- Reasonable link count per page + +**Common issues:** +- Orphan pages (no internal links) +- Over-optimized anchor text +- Important pages buried +- Excessive footer/sidebar links + +### Keyword Targeting + +**Per Page** +- Clear primary keyword target +- Title, H1, URL aligned +- Content satisfies search intent +- Not competing with other pages (cannibalization) + +**Site-Wide** +- Keyword mapping document +- No major gaps in coverage +- No keyword cannibalization +- Logical topical clusters + +--- + +## Content Quality Assessment + +### E-E-A-T Signals + +**Experience** +- First-hand experience demonstrated +- Original insights/data +- Real examples and case studies + +**Expertise** +- Author credentials visible +- Accurate, detailed information +- Properly sourced claims + +**Authoritativeness** +- Recognized in the space +- Cited by others +- Industry credentials + +**Trustworthiness** +- Accurate information +- Transparent about business +- Contact information available +- Privacy policy, terms +- Secure site (HTTPS) + +### Content Depth + +- Comprehensive coverage of topic +- Answers follow-up questions +- Better than top-ranking competitors +- Updated and current + +### User Engagement Signals + +- Time on page +- Bounce rate in context +- Pages per session +- Return visits + +--- + +## Common Issues by Site Type + +### SaaS/Product Sites +- Product pages lack content depth +- Blog not integrated with product pages +- Missing comparison/alternative pages +- Feature pages thin on content +- No glossary/educational content + +### E-commerce +- Thin category pages +- Duplicate product descriptions +- Missing product schema +- Faceted navigation creating duplicates +- Out-of-stock pages mishandled + +### Content/Blog Sites +- Outdated content not refreshed +- Keyword cannibalization +- No topical clustering +- Poor internal linking +- Missing author pages + +### Local Business +- Inconsistent NAP +- Missing local schema +- No Google Business Profile optimization +- Missing location pages +- No local content + +--- + +## Output Format + +### Audit Report Structure + +**Executive Summary** +- Overall health assessment +- Top 3-5 priority issues +- Quick wins identified + +**Technical SEO Findings** +For each issue: +- **Issue**: What's wrong +- **Impact**: SEO impact (High/Medium/Low) +- **Evidence**: How you found it +- **Fix**: Specific recommendation +- **Priority**: 1-5 or High/Medium/Low + +**On-Page SEO Findings** +Same format as above + +**Content Findings** +Same format as above + +**Prioritized Action Plan** +1. Critical fixes (blocking indexation/ranking) +2. High-impact improvements +3. Quick wins (easy, immediate benefit) +4. Long-term recommendations + +--- + +## References + +- [AI Writing Detection](references/ai-writing-detection.md): Common AI writing patterns to avoid (em dashes, overused phrases, filler words) +- [AEO & GEO Patterns](references/aeo-geo-patterns.md): Content patterns optimized for answer engines and AI citation + +--- + +## Tools Referenced + +**Free Tools** +- Google Search Console (essential) +- Google PageSpeed Insights +- Bing Webmaster Tools +- Rich Results Test +- Mobile-Friendly Test +- Schema Validator + +**Paid Tools** (if available) +- Screaming Frog +- Ahrefs / Semrush +- Sitebulb +- ContentKing + +--- + +## Task-Specific Questions + +1. What pages/keywords matter most? +2. Do you have Search Console access? +3. Any recent changes or migrations? +4. Who are your top organic competitors? +5. What's your current organic traffic baseline? + +--- + +## Related Skills + +- **programmatic-seo** — WHEN: user wants to build SEO pages at scale after the audit identifies keyword gaps. WHEN NOT: don't use for diagnosing existing issues; stay in seo-audit mode. +- **ai-seo** — WHEN: user wants to optimize for AI answer engines (SGE, Perplexity, ChatGPT) in addition to traditional search. WHEN NOT: don't use for purely technical crawl/indexation issues. +- **schema-markup** — WHEN: audit reveals missing structured data opportunities (FAQ, HowTo, Product, Review schemas). WHEN NOT: don't use as a standalone fix when core technical SEO is broken. +- **site-architecture** — WHEN: audit uncovers poor internal linking, orphan pages, or crawl depth issues that need a structural redesign. WHEN NOT: don't involve when the audit scope is limited to on-page or content issues. +- **content-strategy** — WHEN: audit reveals thin content, keyword gaps, or lack of topical authority requiring a content plan. WHEN NOT: don't use when the problem is purely technical (robots.txt, redirects, speed). +- **marketing-context** — WHEN: always read first if `.claude/product-marketing-context.md` exists to avoid redundant questions. WHEN NOT: skip if no context file exists and user has provided all necessary product info directly. + +--- + +## Communication + +All audit output follows the **SEO Audit Quality Standard**: +- Lead with the executive summary (3-5 bullets max) +- Findings use the Issue / Impact / Evidence / Fix / Priority format consistently +- Prioritized Action Plan is always the final deliverable section +- Avoid jargon without explanation; write for a technically-aware but non-SEO-specialist reader +- Quick wins are called out explicitly and kept separate from high-effort recommendations +- Never present recommendations without evidence or rationale + +--- + +## Proactive Triggers + +Automatically surface seo-audit recommendations when: + +1. **Traffic drop mentioned** — User says organic traffic dropped or rankings fell; immediately frame an audit scope. +2. **Site migration or redesign** — User mentions a planned or recent URL change, platform switch, or redesign; flag pre/post-migration audit needs. +3. **"Why isn't my page ranking?"** — Any ranking frustration triggers the on-page + intent checklist before external factors. +4. **Content strategy discussion** — When content-strategy skill is active and keyword gaps appear, proactively suggest an SEO audit to validate opportunity. +5. **New site or product launch** — User preparing a launch; proactively recommend a technical SEO pre-launch checklist from the audit framework. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Executive Summary | Markdown bullets | 3-5 top issues + quick wins, suitable for sharing with stakeholders | +| Technical SEO Findings | Structured table | Issue / Impact / Evidence / Fix / Priority per finding | +| On-Page SEO Findings | Structured table | Same format, focused on content and metadata | +| Prioritized Action Plan | Numbered list | Ordered by impact Ɨ effort, grouped into Critical / High / Quick Wins | +| Keyword Cannibalization Map | Table | Pages competing for same keyword with recommended canonical or redirect actions | diff --git a/marketing-skill/seo-audit/scripts/seo_checker.py b/marketing-skill/seo-audit/scripts/seo_checker.py new file mode 100755 index 0000000..675cab7 --- /dev/null +++ b/marketing-skill/seo-audit/scripts/seo_checker.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python3 +""" +seo_checker.py — On-page SEO analyzer +Usage: + python3 seo_checker.py [--file page.html] [--url https://...] [--json] + python3 seo_checker.py # demo mode with embedded sample HTML +""" + +import argparse +import json +import math +import re +import sys +import urllib.request +from html.parser import HTMLParser + + +# --------------------------------------------------------------------------- +# HTML Parser +# --------------------------------------------------------------------------- + +class SEOParser(HTMLParser): + def __init__(self): + super().__init__() + self.title = "" + self._in_title = False + self.meta_description = "" + self.h_tags = [] # list of (level, text) + self._current_h = None + self._current_h_text = [] + self.images = [] # list of {"src": ..., "alt": ...} + self._in_body = False + self.links = [] # list of {"href": ..., "text": ...} + self._current_link_text = [] + self._current_link_href = "" + self._in_link = False + self.body_text_parts = [] + self._in_script = False + self._in_style = False + self.viewport_meta = False + + def handle_starttag(self, tag, attrs): + attrs_dict = dict(attrs) + tag = tag.lower() + + if tag == "title": + self._in_title = True + elif tag == "meta": + name = attrs_dict.get("name", "").lower() + prop = attrs_dict.get("property", "").lower() + if name == "description": + self.meta_description = attrs_dict.get("content", "") + if name == "viewport": + self.viewport_meta = True + if prop == "og:description" and not self.meta_description: + self.meta_description = attrs_dict.get("content", "") + elif tag in ("h1", "h2", "h3", "h4", "h5", "h6"): + self._current_h = int(tag[1]) + self._current_h_text = [] + elif tag == "img": + self.images.append({ + "src": attrs_dict.get("src", ""), + "alt": attrs_dict.get("alt", None), + }) + elif tag == "a": + self._in_link = True + self._current_link_href = attrs_dict.get("href", "") + self._current_link_text = [] + elif tag == "body": + self._in_body = True + elif tag == "script": + self._in_script = True + elif tag == "style": + self._in_style = True + + def handle_endtag(self, tag): + tag = tag.lower() + if tag == "title": + self._in_title = False + elif tag in ("h1", "h2", "h3", "h4", "h5", "h6"): + if self._current_h is not None: + self.h_tags.append((self._current_h, " ".join(self._current_h_text).strip())) + self._current_h = None + self._current_h_text = [] + elif tag == "a": + if self._in_link: + self.links.append({ + "href": self._current_link_href, + "text": " ".join(self._current_link_text).strip(), + }) + self._in_link = False + self._current_link_text = [] + self._current_link_href = "" + elif tag == "script": + self._in_script = False + elif tag == "style": + self._in_style = False + + def handle_data(self, data): + if self._in_title: + self.title += data + if self._current_h is not None: + self._current_h_text.append(data) + if self._in_link: + self._current_link_text.append(data) + if self._in_body and not self._in_script and not self._in_style: + self.body_text_parts.append(data) + + +# --------------------------------------------------------------------------- +# Analysis helpers +# --------------------------------------------------------------------------- + +def _is_external(href, base_domain=""): + if not href: + return False + return href.startswith("http://") or href.startswith("https://") + + +def analyze_html(html: str, base_domain: str = "") -> dict: + parser = SEOParser() + parser.feed(html) + + results = {} + + # --- Title --- + title = parser.title.strip() + title_len = len(title) + title_ok = 50 <= title_len <= 60 + results["title"] = { + "value": title, + "length": title_len, + "optimal_range": "50-60 chars", + "pass": title_ok, + "score": 100 if title_ok else (50 if title else 0), + "note": "Good length" if title_ok else ( + f"Too {'short' if title_len < 50 else 'long'} ({title_len} chars)" if title else "Missing title tag" + ), + } + + # --- Meta description --- + desc = parser.meta_description.strip() + desc_len = len(desc) + desc_ok = 150 <= desc_len <= 160 + results["meta_description"] = { + "value": desc[:80] + ("..." if len(desc) > 80 else ""), + "length": desc_len, + "optimal_range": "150-160 chars", + "pass": desc_ok, + "score": 100 if desc_ok else (50 if 100 <= desc_len < 150 or 160 < desc_len <= 200 else (30 if desc else 0)), + "note": "Good length" if desc_ok else ( + f"Too {'short' if desc_len < 150 else 'long'} ({desc_len} chars)" if desc else "Missing meta description" + ), + } + + # --- H1 --- + h1s = [t for lvl, t in parser.h_tags if lvl == 1] + h1_count = len(h1s) + h1_ok = h1_count == 1 + results["h1"] = { + "count": h1_count, + "values": h1s, + "pass": h1_ok, + "score": 100 if h1_ok else (50 if h1_count > 1 else 0), + "note": "Exactly one H1 āœ“" if h1_ok else ( + f"Multiple H1s ({h1_count})" if h1_count > 1 else "No H1 found" + ), + } + + # --- Heading hierarchy --- + heading_issues = [] + prev_level = 0 + for lvl, _ in parser.h_tags: + if prev_level and lvl > prev_level + 1: + heading_issues.append(f"H{prev_level} → H{lvl} skips a level") + prev_level = lvl + hierarchy_ok = len(heading_issues) == 0 + results["heading_hierarchy"] = { + "headings": [(f"H{l}", t[:60]) for l, t in parser.h_tags], + "issues": heading_issues, + "pass": hierarchy_ok, + "score": max(0, 100 - len(heading_issues) * 25), + "note": "Hierarchy OK" if hierarchy_ok else f"{len(heading_issues)} level-skip issue(s)", + } + + # --- Image alt text --- + total_imgs = len(parser.images) + imgs_with_alt = sum(1 for img in parser.images if img["alt"] is not None and img["alt"].strip()) + alt_pct = (imgs_with_alt / total_imgs * 100) if total_imgs else 100 + alt_ok = alt_pct == 100 + results["image_alt_text"] = { + "total_images": total_imgs, + "with_alt": imgs_with_alt, + "coverage_pct": round(alt_pct, 1), + "pass": alt_ok, + "score": round(alt_pct), + "note": "All images have alt text" if alt_ok else f"{total_imgs - imgs_with_alt} image(s) missing alt", + } + + # --- Link ratio --- + total_links = len(parser.links) + ext_links = sum(1 for l in parser.links if _is_external(l["href"], base_domain)) + int_links = total_links - ext_links + ratio = (int_links / total_links) if total_links else 0 + ratio_ok = ratio >= 0.5 or total_links == 0 + results["link_ratio"] = { + "total_links": total_links, + "internal": int_links, + "external": ext_links, + "internal_pct": round(ratio * 100, 1), + "pass": ratio_ok, + "score": 100 if ratio_ok else round(ratio * 100), + "note": "Good internal/external balance" if ratio_ok else "More external than internal links", + } + + # --- Word count --- + body_text = " ".join(parser.body_text_parts) + words = re.findall(r"\b\w+\b", body_text) + word_count = len(words) + wc_ok = word_count >= 300 + results["word_count"] = { + "count": word_count, + "minimum": 300, + "pass": wc_ok, + "score": min(100, round(word_count / 300 * 100)) if not wc_ok else 100, + "note": f"{word_count} words (good)" if wc_ok else f"Only {word_count} words — need 300+", + } + + # --- Viewport meta --- + results["viewport_meta"] = { + "present": parser.viewport_meta, + "pass": parser.viewport_meta, + "score": 100 if parser.viewport_meta else 0, + "note": "Mobile viewport tag present" if parser.viewport_meta else "Missing viewport meta tag", + } + + return results + + +def compute_overall_score(results: dict) -> int: + weights = { + "title": 20, + "meta_description": 15, + "h1": 15, + "heading_hierarchy": 10, + "image_alt_text": 10, + "link_ratio": 10, + "word_count": 15, + "viewport_meta": 5, + } + total_w = sum(weights.values()) + score = sum(results[k]["score"] * w for k, w in weights.items() if k in results) + return round(score / total_w) + + +# --------------------------------------------------------------------------- +# Demo HTML +# --------------------------------------------------------------------------- + +DEMO_HTML = """ + + + + + 10 Ways to Boost Your Marketing ROI in 2024 + + + +

10 Ways to Boost Your Marketing ROI in 2024

+

Marketing budgets are tight. Every dollar counts. Here is how to make yours work harder.

+

1. Audit Your Current Spend

+

Before adding channels, understand where money goes. Most companies waste 30% of budget on low-ROI tactics.

+ Marketing spend audit chart showing channel breakdown +

2. Double Down on SEO

+

Organic traffic compounds. Paid stops the moment you stop spending. Invest in content that ranks.

+ SEO traffic growth over 12 months +

On-Page Optimization

+

Start with title tags, meta descriptions, and heading structure before anything else.

+

3. Improve Email Open Rates

+

Subject lines determine 80% of open rates. Test at least three variants per campaign.

+ Email templates library + Mailchimp +

4. Use Retargeting Wisely

+

Retargeting works best with frequency caps. Show the same ad more than 7 times and you hurt brand perception.

+

5. Build Landing Pages That Convert

+

A single focused landing page beats a homepage for paid traffic every time. Remove navigation. Add a clear CTA.

+ Landing page guide + CRO checklist + Unbounce +

With these strategies you should see measurable improvement within 90 days. Start with the audit — it reveals the quickest wins.

+ +""" + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="On-page SEO checker — scores an HTML page 0-100." + ) + parser.add_argument("--file", help="Path to HTML file") + parser.add_argument("--url", help="URL to fetch and analyze") + parser.add_argument("--domain", default="", help="Base domain for internal link detection") + parser.add_argument("--json", action="store_true", help="Output as JSON") + args = parser.parse_args() + + if args.file: + with open(args.file, "r", encoding="utf-8", errors="replace") as f: + html = f.read() + elif args.url: + with urllib.request.urlopen(args.url, timeout=10) as resp: + html = resp.read().decode("utf-8", errors="replace") + else: + html = DEMO_HTML + if not args.json: + print("No input provided — running in demo mode.\n") + + results = analyze_html(html, base_domain=args.domain) + overall = compute_overall_score(results) + + if args.json: + output = {"overall_score": overall, "checks": results} + print(json.dumps(output, indent=2)) + return + + # Human-readable output + ICONS = {True: "āœ…", False: "āŒ"} + print("=" * 60) + print(f" SEO AUDIT RESULTS Overall Score: {overall}/100") + print("=" * 60) + + checks = [ + ("Title Tag", "title"), + ("Meta Description", "meta_description"), + ("H1 Tag", "h1"), + ("Heading Hierarchy", "heading_hierarchy"), + ("Image Alt Text", "image_alt_text"), + ("Link Ratio", "link_ratio"), + ("Word Count", "word_count"), + ("Viewport Meta", "viewport_meta"), + ] + + for label, key in checks: + r = results[key] + icon = ICONS[r["pass"]] + score = r["score"] + note = r["note"] + print(f" {icon} {label:<22} [{score:>3}/100] {note}") + + print("=" * 60) + + # Grade + grade = "A" if overall >= 90 else "B" if overall >= 75 else "C" if overall >= 60 else "D" if overall >= 40 else "F" + print(f" Grade: {grade} Score: {overall}/100") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/signup-flow-cro/SKILL.md b/marketing-skill/signup-flow-cro/SKILL.md new file mode 100644 index 0000000..c47400f --- /dev/null +++ b/marketing-skill/signup-flow-cro/SKILL.md @@ -0,0 +1,401 @@ +--- +name: signup-flow-cro +description: When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions "signup conversions," "registration friction," "signup form optimization," "free trial signup," "reduce signup dropoff," or "account creation flow." For post-signup onboarding, see onboarding-cro. For lead capture forms (not account creation), see form-cro. +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Signup Flow CRO + +You are an expert in optimizing signup and registration flows. Your goal is to reduce friction, increase completion rates, and set users up for successful activation. + +## Initial Assessment + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Before providing recommendations, understand: + +1. **Flow Type** + - Free trial signup + - Freemium account creation + - Paid account creation + - Waitlist/early access signup + - B2B vs B2C + +2. **Current State** + - How many steps/screens? + - What fields are required? + - What's the current completion rate? + - Where do users drop off? + +3. **Business Constraints** + - What data is genuinely needed at signup? + - Are there compliance requirements? + - What happens immediately after signup? + +--- + +## Core Principles + +### 1. Minimize Required Fields +Every field reduces conversion. For each field, ask: +- Do we absolutely need this before they can use the product? +- Can we collect this later through progressive profiling? +- Can we infer this from other data? + +**Typical field priority:** +- Essential: Email (or phone), Password +- Often needed: Name +- Usually deferrable: Company, Role, Team size, Phone, Address + +### 2. Show Value Before Asking for Commitment +- What can you show/give before requiring signup? +- Can they experience the product before creating an account? +- Reverse the order: value first, signup second + +### 3. Reduce Perceived Effort +- Show progress if multi-step +- Group related fields +- Use smart defaults +- Pre-fill when possible + +### 4. Remove Uncertainty +- Clear expectations ("Takes 30 seconds") +- Show what happens after signup +- No surprises (hidden requirements, unexpected steps) + +--- + +## Field-by-Field Optimization + +### Email Field +- Single field (no email confirmation field) +- Inline validation for format +- Check for common typos (gmial.com → gmail.com) +- Clear error messages + +### Password Field +- Show password toggle (eye icon) +- Show requirements upfront, not after failure +- Consider passphrase hints for strength +- Update requirement indicators in real-time + +**Better password UX:** +- Allow paste (don't disable) +- Show strength meter instead of rigid rules +- Consider passwordless options + +### Name Field +- Single "Full name" field vs. First/Last split (test this) +- Only require if immediately used (personalization) +- Consider making optional + +### Social Auth Options +- Place prominently (often higher conversion than email) +- Show most relevant options for your audience + - B2C: Google, Apple, Facebook + - B2B: Google, Microsoft, SSO +- Clear visual separation from email signup +- Consider "Sign up with Google" as primary + +### Phone Number +- Defer unless essential (SMS verification, calling leads) +- If required, explain why +- Use proper input type with country code handling +- Format as they type + +### Company/Organization +- Defer if possible +- Auto-suggest as they type +- Infer from email domain when possible + +### Use Case / Role Questions +- Defer to onboarding if possible +- If needed at signup, keep to one question +- Use progressive disclosure (don't show all options at once) + +--- + +## Single-Step vs. Multi-Step + +### Single-Step Works When: +- 3 or fewer fields +- Simple B2C products +- High-intent visitors (from ads, waitlist) + +### Multi-Step Works When: +- More than 3-4 fields needed +- Complex B2B products needing segmentation +- You need to collect different types of info + +### Multi-Step Best Practices +- Show progress indicator +- Lead with easy questions (name, email) +- Put harder questions later (after psychological commitment) +- Each step should feel completable in seconds +- Allow back navigation +- Save progress (don't lose data on refresh) + +**Progressive commitment pattern:** +1. Email only (lowest barrier) +2. Password + name +3. Customization questions (optional) + +--- + +## Trust and Friction Reduction + +### At the Form Level +- "No credit card required" (if true) +- "Free forever" or "14-day free trial" +- Privacy note: "We'll never share your email" +- Security badges if relevant +- Testimonial near signup form + +### Error Handling +- Inline validation (not just on submit) +- Specific error messages ("Email already registered" + recovery path) +- Don't clear the form on error +- Focus on the problem field + +### Microcopy +- Placeholder text: Use for examples, not labels +- Labels: Always visible (not just placeholders) +- Help text: Only when needed, placed close to field + +--- + +## Mobile Signup Optimization + +- Larger touch targets (44px+ height) +- Appropriate keyboard types (email, tel, etc.) +- Autofill support +- Reduce typing (social auth, pre-fill) +- Single column layout +- Sticky CTA button +- Test with actual devices + +--- + +## Post-Submit Experience + +### Success State +- Clear confirmation +- Immediate next step +- If email verification required: + - Explain what to do + - Easy resend option + - Check spam reminder + - Option to change email if wrong + +### Verification Flows +- Consider delaying verification until necessary +- Magic link as alternative to password +- Let users explore while awaiting verification +- Clear re-engagement if verification stalls + +--- + +## Measurement + +### Key Metrics +- Form start rate (landed → started filling) +- Form completion rate (started → submitted) +- Field-level drop-off (which fields lose people) +- Time to complete +- Error rate by field +- Mobile vs. desktop completion + +### What to Track +- Each field interaction (focus, blur, error) +- Step progression in multi-step +- Social auth vs. email signup ratio +- Time between steps + +--- + +## Output Format + +### Audit Findings +For each issue found: +- **Issue**: What's wrong +- **Impact**: Why it matters (with estimated impact if possible) +- **Fix**: Specific recommendation +- **Priority**: High/Medium/Low + +### Recommended Changes +Organized by: +1. Quick wins (same-day fixes) +2. High-impact changes (week-level effort) +3. Test hypotheses (things to A/B test) + +### Form Redesign (if requested) +- Recommended field set with rationale +- Field order +- Copy for labels, placeholders, buttons, errors +- Visual layout suggestions + +--- + +## Common Signup Flow Patterns + +### B2B SaaS Trial +1. Email + Password (or Google auth) +2. Name + Company (optional: role) +3. → Onboarding flow + +### B2C App +1. Google/Apple auth OR Email +2. → Product experience +3. Profile completion later + +### Waitlist/Early Access +1. Email only +2. Optional: Role/use case question +3. → Waitlist confirmation + +### E-commerce Account +1. Guest checkout as default +2. Account creation optional post-purchase +3. OR Social auth with single click + +--- + +## Experiment Ideas + +### Form Design Experiments + +**Layout & Structure** +- Single-step vs. multi-step signup flow +- Multi-step with progress bar vs. without +- 1-column vs. 2-column field layout +- Form embedded on page vs. separate signup page +- Horizontal vs. vertical field alignment + +**Field Optimization** +- Reduce to minimum fields (email + password only) +- Add or remove phone number field +- Single "Name" field vs. "First/Last" split +- Add or remove company/organization field +- Test required vs. optional field balance + +**Authentication Options** +- Add SSO options (Google, Microsoft, GitHub, LinkedIn) +- SSO prominent vs. email form prominent +- Test which SSO options resonate (varies by audience) +- SSO-only vs. SSO + email option + +**Visual Design** +- Test button colors and sizes for CTA prominence +- Plain background vs. product-related visuals +- Test form container styling (card vs. minimal) +- Mobile-optimized layout testing + +--- + +### Copy & Messaging Experiments + +**Headlines & CTAs** +- Test headline variations above signup form +- CTA button text: "Create Account" vs. "Start Free Trial" vs. "Get Started" +- Add clarity around trial length in CTA +- Test value proposition emphasis in form header + +**Microcopy** +- Field labels: minimal vs. descriptive +- Placeholder text optimization +- Error message clarity and tone +- Password requirement display (upfront vs. on error) + +**Trust Elements** +- Add social proof next to signup form +- Test trust badges near form (security, compliance) +- Add "No credit card required" messaging +- Include privacy assurance copy + +--- + +### Trial & Commitment Experiments + +**Free Trial Variations** +- Credit card required vs. not required for trial +- Test trial length impact (7 vs. 14 vs. 30 days) +- Freemium vs. free trial model +- Trial with limited features vs. full access + +**Friction Points** +- Email verification required vs. delayed vs. removed +- Test CAPTCHA impact on completion +- Terms acceptance checkbox vs. implicit acceptance +- Phone verification for high-value accounts + +--- + +### Post-Submit Experiments + +- Clear next steps messaging after signup +- Instant product access vs. email confirmation first +- Personalized welcome message based on signup data +- Auto-login after signup vs. require login + +--- + +## Task-Specific Questions + +1. What's your current signup completion rate? +2. Do you have field-level analytics on drop-off? +3. What data is absolutely required before they can use the product? +4. Are there compliance or verification requirements? +5. What happens immediately after signup? + +--- + +## Related Skills + +- **onboarding-cro** — WHEN: the signup flow itself completes well but users aren't activating or reaching their "aha moment" after account creation. WHEN NOT: don't jump to onboarding-cro when users are dropping off during the signup form itself. +- **form-cro** — WHEN: the form being optimized is NOT account creation — lead capture, contact, demo request, or survey forms need form-cro instead. WHEN NOT: don't use form-cro for registration/account creation flows; signup-flow-cro has the right framework for authentication patterns (SSO, magic link, email+password). +- **page-cro** — WHEN: the landing page or marketing page leading to the signup is the bottleneck — poor headline, weak value prop, or message mismatch. WHEN NOT: don't invoke page-cro when users are reaching the signup form but dropping inside it. +- **ab-test-setup** — WHEN: hypotheses from the signup audit are ready to test (SSO vs. email, single-step vs. multi-step, credit card required vs. not). WHEN NOT: don't run A/B tests on the signup flow before instrumenting field-level drop-off analytics. +- **paywall-upgrade-cro** — WHEN: the signup flow is freemium and the real challenge is converting free users to paid, not getting them to sign up. WHEN NOT: don't conflate trial-to-paid conversion with signup-flow optimization. +- **marketing-context** — WHEN: check `.claude/product-marketing-context.md` for B2B vs. B2C context, compliance requirements, and qualification data needs before designing the field set. WHEN NOT: skip if user has provided explicit product and compliance context in the conversation. + +--- + +## Communication + +All signup flow CRO output follows this quality standard: +- Recommendations are always organized as **Quick Wins → High-Impact → Test Hypotheses** — never a flat list +- Every field removal recommendation is justified against the "do we need this before they can use the product?" test +- SSO options are always considered and recommended when relevant — don't default to email-only flows +- Post-submit experience (verification, success state, next steps) is always addressed — it's part of the flow +- Mobile optimization is treated as a distinct section, not an afterthought +- Experiment ideas distinguish between "fix this" (obvious) and "test this" (uncertain) — never recommend testing obvious improvements + +--- + +## Proactive Triggers + +Automatically surface signup-flow-cro when: + +1. **"Users sign up but don't activate"** — Low activation rate often traces back to signup friction or a broken post-submit experience; proactively audit the full signup-to-activation path. +2. **"Our trial conversion is low"** — When the trial-to-paid rate is poor, check whether the signup flow is setting wrong expectations or collecting the wrong users. +3. **Free trial or freemium product being built** — When product or engineering work on a new trial flow is detected, proactively offer signup-flow-cro review before launch. +4. **"Should we require a credit card?"** — This question always triggers the full signup friction analysis and trial commitment experiment framework. +5. **High mobile drop-off on signup** — When analytics or page-cro reveals a mobile gap specifically on the signup page, immediately surface the mobile signup optimization checklist. + +--- + +## Output Artifacts + +| Artifact | Format | Description | +|----------|--------|-------------| +| Signup Flow Audit | Issue/Impact/Fix/Priority table | Per-step and per-field analysis with severity ratings | +| Recommended Field Set | Justified list | Required vs. deferrable fields with rationale, organized by signup step | +| Flow Redesign Spec | Step-by-step outline | Recommended multi-step or single-step flow with copy for each screen | +| SSO & Auth Options Recommendation | Decision table | Which auth methods to offer, placement, and priority for the target audience | +| A/B Test Hypotheses | Table | Hypothesis Ɨ variant description Ɨ success metric Ɨ priority for top 3-5 tests | diff --git a/marketing-skill/signup-flow-cro/scripts/funnel_drop_analyzer.py b/marketing-skill/signup-flow-cro/scripts/funnel_drop_analyzer.py new file mode 100644 index 0000000..4ffc835 --- /dev/null +++ b/marketing-skill/signup-flow-cro/scripts/funnel_drop_analyzer.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python3 +""" +funnel_drop_analyzer.py — Signup Funnel Drop-Off Analyzer +100% stdlib, no pip installs required. + +Usage: + python3 funnel_drop_analyzer.py # demo mode + python3 funnel_drop_analyzer.py --steps steps.json + python3 funnel_drop_analyzer.py --steps steps.json --json + echo '[{"step":"Visit","count":10000}]' | python3 funnel_drop_analyzer.py --stdin + +steps.json format: + [ + {"step": "Landing Page Visit", "count": 10000}, + {"step": "Clicked Sign Up", "count": 4200}, + {"step": "Filled Form", "count": 2800}, + {"step": "Email Verified", "count": 1900}, + {"step": "Onboarding Done", "count": 1100} + ] +""" + +import argparse +import json +import math +import sys + + +# --------------------------------------------------------------------------- +# Recommendation engine +# --------------------------------------------------------------------------- + +RECOMMENDATIONS = { + "high_drop": { + "threshold": 0.50, # >50% drop + "landing_page": [ + "Value proposition may be unclear — run a 5-second test.", + "Add social proof (testimonials, logos, user count) above the fold.", + "Ensure CTA button is prominent and benefit-focused ('Start Free' not 'Submit').", + ], + "clicked_sign_up": [ + "CTA label or placement may not resonate — A/B test button copy and colour.", + "Users may not trust the product — add trust badges and reviews near CTA.", + "Consider a sticky header CTA for long landing pages.", + ], + "filled_form": [ + "Form has too many fields — reduce to email + password minimum.", + "Try progressive disclosure: collect extra info post-signup.", + "Add inline validation so errors appear in real-time, not on submit.", + "Show a progress indicator if multi-step.", + ], + "email_verified": [ + "Verification email may land in spam — check SPF/DKIM/DMARC.", + "Send a plain-text follow-up 30 min after signup nudging verification.", + "Consider SMS or magic-link alternatives to email verification.", + "Reduce time-to-value: show a useful screen before requiring verification.", + ], + "default": [ + "Significant drop detected — instrument with session recordings (Hotjar/FullStory).", + "Run exit surveys at this step to capture qualitative reasons.", + "Check for UI bugs or broken flows on mobile.", + ], + }, + "medium_drop": { + "threshold": 0.25, # 25–50% drop + "default": [ + "Moderate friction — review copy and UX at this step.", + "Ensure mobile experience is frictionless (test on real devices).", + "Add micro-copy explaining why information is requested.", + ], + }, + "healthy": { + "default": [ + "Step conversion is healthy — focus optimisation effort elsewhere.", + ], + }, +} + + +def classify_step_name(name: str) -> str: + """Map step name to a known category for targeted recommendations.""" + n = name.lower() + if any(k in n for k in ["land", "visit", "page", "home"]): + return "landing_page" + if any(k in n for k in ["cta", "click", "signup", "sign up", "register", "start"]): + return "clicked_sign_up" + if any(k in n for k in ["form", "fill", "detail", "info", "enter"]): + return "filled_form" + if any(k in n for k in ["email", "verif", "confirm", "activate"]): + return "email_verified" + return "default" + + +def get_recommendation(step_name: str, drop_rate: float) -> list: + if drop_rate > RECOMMENDATIONS["high_drop"]["threshold"]: + bucket = RECOMMENDATIONS["high_drop"] + cat = classify_step_name(step_name) + return bucket.get(cat, bucket["default"]) + elif drop_rate > RECOMMENDATIONS["medium_drop"]["threshold"]: + return RECOMMENDATIONS["medium_drop"]["default"] + else: + return RECOMMENDATIONS["healthy"]["default"] + + +# --------------------------------------------------------------------------- +# Core analysis +# --------------------------------------------------------------------------- + +def analyze_funnel(steps: list) -> dict: + """ + Analyse a funnel step list and return full metrics + recommendations. + + Each step: {"step": , "count": } + """ + if not steps: + raise ValueError("steps list is empty") + if len(steps) < 2: + raise ValueError("Need at least 2 steps to analyse a funnel") + + top_count = steps[0]["count"] + if top_count <= 0: + raise ValueError("Top-of-funnel count must be > 0") + + step_metrics = [] + worst_step = None + worst_drop_rate = -1.0 + + for i, s in enumerate(steps): + name = s["step"] + count = s["count"] + + cumulative_rate = count / top_count + + if i == 0: + step_to_step_rate = 1.0 + drop_count = 0 + drop_rate = 0.0 + recommendations = ["Top of funnel — all visitors enter here."] + else: + prev_count = steps[i - 1]["count"] + step_to_step_rate = count / prev_count if prev_count > 0 else 0.0 + drop_count = prev_count - count + drop_rate = 1 - step_to_step_rate + recommendations = get_recommendation(name, drop_rate) + + if drop_rate > worst_drop_rate: + worst_drop_rate = drop_rate + worst_step = name + + step_metrics.append({ + "step": name, + "count": count, + "step_conversion_pct": round(step_to_step_rate * 100, 2), + "step_drop_pct": round(drop_rate * 100, 2), + "drop_count": drop_count, + "cumulative_conversion_pct": round(cumulative_rate * 100, 2), + "recommendations": recommendations, + }) + + # Overall funnel health score (0-100) + overall_conv = steps[-1]["count"] / top_count + score = _funnel_score(step_metrics, overall_conv) + + return { + "summary": { + "total_steps": len(steps), + "top_of_funnel_count": top_count, + "bottom_of_funnel_count": steps[-1]["count"], + "overall_conversion_pct": round(overall_conv * 100, 2), + "worst_performing_step": worst_step, + "worst_step_drop_pct": round(worst_drop_rate * 100, 2), + "funnel_health_score": score, + "funnel_health_label": _score_label(score), + }, + "steps": step_metrics, + "top_priority": _top_priority(step_metrics), + } + + +def _funnel_score(step_metrics: list, overall_conv: float) -> int: + """ + Score = 100 * overall_conversion adjusted for worst-step severity. + - Base: log-scale overall conversion (capped at a 10% target = 100 pts) + - Penalty: each step with >60% drop deducts points + """ + target_conv = 0.10 # 10% overall = score 100 + base = min(100, math.log1p(overall_conv) / math.log1p(target_conv) * 100) + + penalty = 0 + for m in step_metrics[1:]: + if m["step_drop_pct"] > 60: + penalty += 10 + elif m["step_drop_pct"] > 40: + penalty += 5 + + score = max(0, round(base - penalty)) + return score + + +def _score_label(s: int) -> str: + if s >= 80: return "Excellent" + if s >= 60: return "Good" + if s >= 40: return "Fair" + if s >= 20: return "Poor" + return "Critical" + + +def _top_priority(step_metrics: list) -> dict: + """Return the single highest-impact step to fix first.""" + # Pick step with largest absolute drop count (not just rate) + candidates = step_metrics[1:] + if not candidates: + return {} + top = max(candidates, key=lambda m: m["drop_count"]) + return { + "step": top["step"], + "drop_count": top["drop_count"], + "drop_pct": top["step_drop_pct"], + "why": "Largest absolute visitor loss — highest revenue impact.", + "quick_wins": top["recommendations"], + } + + +# --------------------------------------------------------------------------- +# Pretty-print +# --------------------------------------------------------------------------- + +def pretty_print(result: dict) -> None: + s = result["summary"] + tp = result["top_priority"] + + print("\n" + "=" * 65) + print(" SIGNUP FUNNEL DROP-OFF ANALYZER") + print("=" * 65) + + print(f"\nšŸ“Š FUNNEL OVERVIEW") + print(f" Top of funnel : {s['top_of_funnel_count']:,} visitors") + print(f" Bottom of funnel : {s['bottom_of_funnel_count']:,} converted") + print(f" Overall conversion : {s['overall_conversion_pct']}%") + print(f" Funnel health : {s['funnel_health_score']}/100 ({s['funnel_health_label']})") + print(f" Worst step : {s['worst_performing_step']} " + f"({s['worst_step_drop_pct']}% drop)") + + print(f"\n{'Step':<28} {'Count':>8} {'Step Conv':>10} {'Step Drop':>10} {'Cumul Conv':>10}") + print("─" * 75) + for m in result["steps"]: + bar = "ā–ˆ" * int(m["cumulative_conversion_pct"] / 5) + print(f" {m['step']:<26} {m['count']:>8,} " + f"{m['step_conversion_pct']:>9.1f}% " + f"{m['step_drop_pct']:>9.1f}% " + f"{m['cumulative_conversion_pct']:>9.1f}% {bar}") + + print(f"\n🚨 TOP PRIORITY FIX: {tp.get('step', 'N/A')}") + print(f" Lost visitors : {tp.get('drop_count', 0):,} ({tp.get('drop_pct', 0)}% drop)") + print(f" Why fix first : {tp.get('why', '')}") + print(" Quick wins:") + for qw in tp.get("quick_wins", []): + print(f" • {qw}") + + print(f"\nšŸ’” STEP-BY-STEP RECOMMENDATIONS") + for m in result["steps"][1:]: + if m["step_drop_pct"] > 10: + print(f"\n [{m['step']}] ↓{m['step_drop_pct']}% drop") + for r in m["recommendations"]: + print(f" • {r}") + + print() + + +# --------------------------------------------------------------------------- +# CLI +# --------------------------------------------------------------------------- + +DEMO_STEPS = [ + {"step": "Landing Page Visit", "count": 12000}, + {"step": "Clicked Sign Up CTA", "count": 4560}, + {"step": "Filled Registration", "count": 2800}, + {"step": "Email Verified", "count": 1540}, + {"step": "Onboarding Completed", "count": 880}, + {"step": "First Core Action", "count": 420}, +] + + +def parse_args(): + parser = argparse.ArgumentParser( + description="Analyse signup funnel drop-off by step (stdlib only).", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--steps", type=str, default=None, + help="Path to JSON file with funnel steps") + parser.add_argument("--stdin", action="store_true", + help="Read steps JSON from stdin") + parser.add_argument("--json", action="store_true", + help="Output results as JSON") + return parser.parse_args() + + +def main(): + args = parse_args() + steps = None + + if args.stdin: + steps = json.load(sys.stdin) + elif args.steps: + with open(args.steps) as f: + steps = json.load(f) + else: + print("šŸ”¬ DEMO MODE — using sample SaaS signup funnel\n") + steps = DEMO_STEPS + + result = analyze_funnel(steps) + + if args.json: + print(json.dumps(result, indent=2)) + else: + pretty_print(result) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/site-architecture/SKILL.md b/marketing-skill/site-architecture/SKILL.md new file mode 100644 index 0000000..9404de1 --- /dev/null +++ b/marketing-skill/site-architecture/SKILL.md @@ -0,0 +1,289 @@ +--- +name: site-architecture +description: "When the user wants to audit, redesign, or plan their website's structure, URL hierarchy, navigation design, or internal linking strategy. Use when the user mentions 'site architecture,' 'URL structure,' 'internal links,' 'site navigation,' 'breadcrumbs,' 'topic clusters,' 'hub pages,' 'orphan pages,' 'silo structure,' 'information architecture,' or 'website reorganization.' Also use when someone has SEO problems and the root cause is structural (not content or schema). NOT for content strategy decisions about what to write (use content-strategy) or for schema markup (use schema-markup)." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Site Architecture & Internal Linking + +You are an expert in website information architecture and technical SEO structure. Your goal is to design website architecture that makes it easy for users to navigate, easy for search engines to crawl, and builds topical authority through intelligent internal linking. + +## Before Starting + +**Check for context first:** +If `marketing-context.md` exists, read it before asking questions. + +Gather this context: + +### 1. Current State +- Do they have an existing site? (URL, CMS, sitemap.xml available?) +- How many pages exist? Rough estimate by section. +- What are the top-performing pages (if they know)? +- Any known problems: orphan pages, duplicate content, poor rankings? + +### 2. Goals +- Primary business goal (lead gen, e-commerce, content authority, local search) +- Target audience and their mental model of navigation +- Specific SEO targets — topics or keyword clusters they want to rank for + +### 3. Constraints +- CMS capabilities (can they change URLs? Does it auto-generate certain structures?) +- Redirect capacity (if restructuring, can they manage bulk 301s?) +- Development resources (minor tweaks vs full migration) + +--- + +## How This Skill Works + +### Mode 1: Audit Current Architecture +When a site exists and they need a structural assessment. + +1. Run `scripts/sitemap_analyzer.py` on their sitemap.xml (or paste sitemap content) +2. Review: depth distribution, URL patterns, potential orphans, duplicate paths +3. Evaluate navigation by reviewing the site manually or from their description +4. Identify the top structural problems by SEO impact +5. Deliver a prioritized audit with quick wins and structural recommendations + +### Mode 2: Plan New Structure +When building a new site or doing a full redesign/restructure. + +1. Map business goals to site sections +2. Design URL hierarchy (flat vs layered by content type) +3. Define content silos for topical authority +4. Plan navigation zones: primary nav, breadcrumbs, footer nav, contextual +5. Deliver site map diagram (text-based tree) + URL structure spec + +### Mode 3: Internal Linking Strategy +When the structure is fine but they need to improve link equity flow and topical signals. + +1. Identify hub pages (the pillar content that should rank highest) +2. Map spoke pages (supporting content that links to hubs) +3. Find orphan pages (indexed pages with no inbound internal links) +4. Identify anchor text patterns and over-optimized phrases +5. Deliver an internal linking plan: which pages link to which, with anchor text guidance + +--- + +## URL Structure Principles + +### The Core Rule: URLs are for Humans First + +A URL should tell a user exactly where they are before they click. It also tells search engines about content hierarchy. Get this right once — URL changes later require redirects and lose equity. + +### Flat vs Layered: Pick the Right Depth + +| Depth | Example | Use When | +|-------|---------|----------| +| Flat (1 level) | `/blog/cold-email-tips` | Blog posts, articles, standalone pages | +| Two levels | `/blog/email-marketing/cold-email-tips` | When category is a ranking page itself | +| Three levels | `/solutions/marketing/email-automation` | Product families, nested services | +| 4+ levels | `/a/b/c/d/page` | āŒ Avoid — dilutes crawl equity, confusing | + +**Rule of thumb:** If the category URL (`/blog/email-marketing/`) is not a real page you want to rank, don't create the directory. Flat is usually better for SEO. + +### URL Construction Rules + +| Do | Don't | +|----|-------| +| `/how-to-write-cold-emails` | `/how_to_write_cold_emails` (underscores) | +| `/pricing` | `/pricing-page` (redundant suffixes) | +| `/blog/seo-tips-2024` | `/blog/article?id=4827` (dynamic, non-descriptive) | +| `/services/web-design` | `/services/web-design/` (trailing slash — pick one and be consistent) | +| `/about` | `/about-us-company-info` (keyword stuffing the URL) | +| Short, human-readable | Long, generated, token-filled | + +### Keywords in URLs + +Yes — include the primary keyword. No — don't stuff 4 keywords in. + +`/guides/technical-seo-audit` āœ… +`/guides/technical-seo-audit-checklist-how-to-complete-step-by-step` āŒ + +The keyword in the URL is a minor signal, not a major one. Don't sacrifice readability for it. + +### Reference docs +See `references/url-design-guide.md` for patterns by site type (blog, SaaS, e-commerce, local). + +--- + +## Navigation Design + +Navigation serves two masters: user experience and link equity flow. Most sites optimize for neither. + +### Navigation Zones + +| Zone | Purpose | SEO Role | +|------|---------|----------| +| Primary nav | Core site sections, 5-8 items max | Passes equity to top-level pages | +| Secondary nav | Sub-sections within a section | Passes equity within a silo | +| Breadcrumbs | Current location in hierarchy | Equity from deep pages upward | +| Footer nav | Secondary utility links, key service pages | Sitewide links — use carefully | +| Contextual nav | In-content links, related posts, "next step" links | Most powerful equity signal | +| Sidebar | Related content, category listing | Medium equity if above fold | + +### Primary Navigation Rules + +- 5-8 items maximum. Cognitive load increases with every item. +- Each nav item should link to a page you want to rank. +- Never use nav labels like "Resources" with no landing page — it should be a real, rankable resources page. +- Dropdown menus are fine but crawlers may not engage them deeply — critical pages need a clickable parent link. + +### Breadcrumbs + +Add breadcrumbs to every non-homepage page. They do three things: +1. Show users where they are +2. Create site-wide upward internal links to category/hub pages +3. Enable BreadcrumbList schema for rich results in Google + +Format: `Home > Category > Subcategory > Current Page` + +Every breadcrumb segment should be a real, crawlable link — not just styled text. + +--- + +## Silo Structure & Topical Authority + +A silo is a self-contained cluster of content about one topic, where all pages link to each other and to a central hub page. Google uses this to determine topical authority. + +### Hub-and-Spoke Model + +``` +HUB: /seo/ ← Pillar page, broad topic + SPOKE: /seo/technical-seo/ ← Sub-topic + SPOKE: /seo/on-page-seo/ ← Sub-topic + SPOKE: /seo/link-building/ ← Sub-topic + SPOKE: /seo/keyword-research/ ← Sub-topic + └─ DEEP: /seo/keyword-research/long-tail-keywords/ ← Specific guide +``` + +**Linking rules within a silo:** +- Hub links to all spokes +- Each spoke links back to hub +- Spokes can link to adjacent spokes (contextually relevant) +- Deep pages link up to their spoke + the hub +- Cross-silo links are fine when genuinely relevant — just don't build a link for its own sake + +### Building Topic Clusters + +1. Identify your core topics (usually 3-7 for a focused site) +2. For each topic: one pillar page (the hub) that covers it broadly +3. Create spoke content for each major sub-question within the topic +4. Every spoke links to the pillar with relevant anchor text +5. The pillar links down to all spokes +6. Build the cluster before you build the links — if you don't have the content, the links don't help + +--- + +## Internal Linking Strategy + +Internal links are the most underused SEO lever. They're fully under your control, free, and directly affect which pages rank. + +### Link Equity Principles + +- Google crawls your site from the homepage outward +- Pages closer to the homepage (fewer clicks away) get more equity +- A page with no internal links is an orphan — Google won't prioritize it +- Anchor text matters: generic ("click here") signals nothing; descriptive ("cold email templates") signals topic relevance + +### Anchor Text Rules + +| Type | Example | Use | +|------|---------|-----| +| Exact match | "cold email templates" | Use sparingly — 1-2x per page, looks natural | +| Partial match | "writing effective cold emails" | Primary approach — most internal links | +| Branded | "our email guide" | Fine, not the most powerful | +| Generic | "click here", "learn more" | Avoid — wastes the signal | +| Naked URL | `https://example.com/guide` | Never use for internal links | + +### Finding and Fixing Orphan Pages + +An orphan page is indexed but has no inbound internal links. It's invisible to the site's link graph. + +How to find them: +1. Export all indexed URLs (from GSC, Screaming Frog, or `sitemap_analyzer.py`) +2. Export all internal links on the site +3. Pages that appear in set A but not set B are orphans +4. Or: run `scripts/sitemap_analyzer.py` which flags potential orphan candidates + +How to fix them: +- Add contextual links from relevant existing pages +- Add them to relevant hub pages +- If they truly have no home, consider whether they should exist at all + +### The Linking Priority Stack + +Not all internal links are equal. From most to least powerful: + +1. **In-content links** — within the body copy of a relevant page. Most natural, most powerful. +2. **Hub page links** — the pillar page linking to all its spokes. High equity because pillar pages are linked from everywhere. +3. **Navigation links** — sitewide, consistent, but diluted by their ubiquity. +4. **Footer links** — sitewide, but Google gives them less weight than in-content. +5. **Sidebar links** — OK but often not in the main content flow. + +See `references/internal-linking-playbook.md` for patterns and scripts. + +--- + +## Common Architecture Mistakes + +| Mistake | Why It Hurts | Fix | +|---------|-------------|-----| +| Orphan pages | No equity flows in, Google deprioritizes | Add contextual internal links from related content | +| URL changes without redirects | Inbound links become broken, equity lost | Always 301 redirect old URLs to new ones | +| Duplicate paths | `/blog/seo` and `/resources/seo` covering same topic | Consolidate with canonical or merge content | +| Deep nesting (4+ levels) | Crawl equity diluted, users confused | Flatten structure, remove unnecessary directories | +| Sitewide footer links to every post | Footer equity is diluted across 500 links | Footer should link to high-value pages only | +| Navigation that doesn't match user intent | Users leave, rankings drop | Run card-sort tests — let users show you their mental model | +| Homepage linking nowhere | Home is highest-equity page — use it | Link from home to key hub pages | +| Category pages with no content | Thin pages rank poorly | Add content to all hub/category pages | +| Dynamic URLs with parameters | `?sort=&filter=` creates duplicate content | Canonicalize or block with robots.txt | + +--- + +## Proactive Triggers + +Surface these without being asked: + +- **Pages more than 3 clicks from homepage** → flag as crawl equity risk. Any page a user has to click 4+ times to reach needs a structural shortcut. +- **Category/hub page has thin or no content** → hub pages without real content don't rank. Flag and recommend adding a proper pillar page. +- **Internal links using generic anchor text ("click here", "read more")** → wasted signal. Offer to rewrite anchor text patterns. +- **No breadcrumbs on deep pages** → missing upward equity links and BreadcrumbList schema opportunity. +- **Sitemap includes noindex pages** → sitemap should only contain pages you want indexed. Flag and offer to filter. +- **Primary nav links to utility pages (contact, privacy)** → pushing equity to low-value pages. Nav should prioritize money/content pages. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| Architecture audit | Structural scorecard: depth distribution, orphan count, URL pattern issues, navigation gaps + prioritized fix list | +| New site structure | Text-based site tree (hierarchy diagram) + URL spec table with notes per section | +| Internal linking plan | Hub-and-spoke map per topic cluster + anchor text guidelines + orphan fix list | +| URL redesign | Before/after URL table + 301 redirect mapping + implementation checklist | +| Silo strategy | Topic cluster map per business goal + content gap analysis + pillar page brief | + +--- + +## Communication + +All output follows the structured communication standard: +- **Bottom line first** — answer before explanation +- **What + Why + How** — every finding has all three +- **Actions have owners and deadlines** — no "we should consider" +- **Confidence tagging** — 🟢 verified / 🟔 medium / šŸ”“ assumed + +--- + +## Related Skills + +- **seo-audit**: For comprehensive SEO audit covering technical, on-page, and off-page. Use seo-audit when architecture is one of several problem areas. NOT for deep structural redesign — use site-architecture. +- **schema-markup**: For structured data implementation. Use after site-architecture when you want to add BreadcrumbList and other schema to your finalized structure. +- **content-strategy**: For deciding what content to create. Use content-strategy to plan the content, then site-architecture to determine where it lives and how it links. +- **programmatic-seo**: When you need to generate hundreds or thousands of pages systematically. Site-architecture provides the URL and structural patterns that programmatic-seo scales. +- **seo-audit**: For identifying technical issues. NOT for architecture redesign planning — use site-architecture for that. diff --git a/marketing-skill/site-architecture/references/internal-linking-playbook.md b/marketing-skill/site-architecture/references/internal-linking-playbook.md new file mode 100644 index 0000000..5788ee8 --- /dev/null +++ b/marketing-skill/site-architecture/references/internal-linking-playbook.md @@ -0,0 +1,216 @@ +# Internal Linking Playbook + +Patterns for building an internal link structure that distributes equity intelligently and reinforces topical authority. + +--- + +## The Three Goals of Internal Linking + +1. **Crawlability** — every page should be reachable from the homepage in 3 clicks or fewer +2. **Equity flow** — link equity flows from authoritative pages to pages you want to rank +3. **Topical signals** — anchor text and link context tell Google what a page is about + +Most sites get none of these right. The ones that do compound their SEO advantage over time. + +--- + +## Linking Architecture Patterns + +### Pattern 1: Hub-and-Spoke (Topic Cluster) + +Best for: Content sites, blogs, SaaS feature/solution pages. + +``` +Hub (Pillar) Page +ā”œā”€ā”€ Spoke 1 (Sub-topic) +│ └── Deep 1a (Specific guide within sub-topic) +│ └── Deep 1b +ā”œā”€ā”€ Spoke 2 (Sub-topic) +│ └── Deep 2a +└── Spoke 3 (Sub-topic) +``` + +**Link rules:** +- Hub → all spokes (contextual, in-body links) +- Each spoke → hub (with anchor text matching hub's target keyword) +- Each spoke → adjacent spokes (only when genuinely relevant) +- Deep pages → parent spoke + hub + +**What makes this work:** The hub becomes the authority page because it receives links from everything in the cluster. Google sees a well-linked hub as the definitive resource on the topic. + +--- + +### Pattern 2: Linear (Sequential Content) + +Best for: Course content, multi-part guides, documentation, step-by-step processes. + +``` +Introduction → Part 1 → Part 2 → Part 3 → Summary/CTA +``` + +**Link rules:** +- Each page links forward (next) and back (previous) +- An index page links to all parts +- Summary page links back to each key section + +**What makes this work:** Clear navigation for users, clear sequence for crawlers. + +--- + +### Pattern 3: Conversion Funnel Linking + +Best for: SaaS sites, lead gen sites — moving users from content to conversion. + +``` +Blog Post (awareness) → Feature Page (consideration) → Pricing Page (decision) +Blog Post (awareness) → Case Study (social proof) → Free Trial / Demo CTA +``` + +**Link rules:** +- Every blog post should have at least one contextual link to a product/feature page +- Case studies link to the relevant feature/solution and to pricing +- Feature pages link to relevant case studies and to pricing +- Pricing page links to FAQ and to demo/trial + +**What makes this work:** Equity flows from content (high link volume) to money pages (low link volume). Most SaaS sites have this backwards — money pages get links from the nav only. + +--- + +### Pattern 4: Star / Authority Distribution + +Best for: Homepage and top-level hub pages that have lots of external links. + +``` +Homepage (authority source) +ā”œā”€ā”€ Service Page A (direct link from homepage) +ā”œā”€ā”€ Feature Page B (direct link from homepage) +ā”œā”€ā”€ Blog Category Hub (direct link from homepage) +└── Case Studies Hub (direct link from homepage) +``` + +**Link rules:** +- Homepage links only to the most important pages +- Not to every blog post — to the category hubs +- Each hub then distributes equity downward + +**What makes this work:** Homepage equity isn't diluted across 200 blog links. It concentrates on 5-8 priority pages, which then funnel it to their children. + +--- + +## Anchor Text Strategy + +### The Right Mix + +| Type | Target % of Internal Links | Example | +|------|--------------------------|---------| +| Descriptive partial match | 50-60% | "cold email writing guide" | +| Exact match keyword | 10-15% | "cold email templates" | +| Page title / branded | 20-25% | "our guide to cold outreach" | +| Generic | <5% | "learn more" | +| Naked URL | 0% | Never | + +### Writing Good Anchor Text + +**Good:** Uses the target keyword naturally in a sentence. +> "For tactical patterns, see our [cold email frameworks](link)." + +**Bad:** Forces exact match where it sounds unnatural. +> "Click here to read our cold email templates cold email cold outreach guide." + +**Bad:** Generic — signals nothing. +> "For more information, [click here](link)." + +### Anchor Text Diversification + +Don't link to the same page with the same anchor every time. Vary it. If you have 15 internal links to your "cold email templates" page: +- 8 using variations: "email outreach templates," "cold outreach scripts," "first-email frameworks" +- 4 using exact: "cold email templates" +- 3 using title/branded: "our template library" + +This looks natural and covers a wider keyword base. + +--- + +## Finding Linking Opportunities + +### Method 1: Keyword Overlap Search (Manual) + +When you publish new content, search your site for pages that mention the topic but don't link to the new page. + +``` +site:yourdomain.com "cold email" +``` + +Any page that mentions "cold email" and doesn't already link to your cold email guide is a candidate for adding a contextual link. + +### Method 2: Screaming Frog Crawl + +Crawl your site with Screaming Frog → Bulk Export → Internal links. Then filter: +- Pages with 0 inbound internal links = orphans (fix immediately) +- Pages with 1-2 inbound internal links = at-risk (add more) +- Pages with high outbound links but low inbound = over-givers (these should be receiving, not just giving) + +### Method 3: Content Gap Linking + +When you audit your content clusters, look for spokes that aren't linked from the hub. The hub should explicitly link to every key spoke page. If it doesn't, the cluster is broken. + +--- + +## Orphan Page Recovery + +An orphan page has no internal links pointing to it. It's effectively invisible to Google's link graph. + +**Step 1: Find your orphans** +- Run `scripts/sitemap_analyzer.py` to get all indexed URLs +- Cross-reference with your internal link graph (from Screaming Frog or GSC) +- Pages in sitemap but not in internal link graph = candidates + +**Step 2: Classify them** + +| Type | Action | +|------|--------| +| Valuable content, no home | Find existing relevant pages to add contextual links from; add to relevant hub | +| Landing pages (PPC, events) | These are intentionally unlinked — check if they're accidentally indexed | +| Duplicate / thin content | Consolidate with canonical or noindex | +| Old content no longer relevant | Consider 301 redirect to updated version or 410 | + +**Step 3: Fix in priority order** +1. Orphans with inbound external links first (equity is flowing in but going nowhere) +2. Orphans with good content and search potential +3. Orphans with thin content (fix content first, then link) + +--- + +## Internal Link Audit Checklist + +Run this quarterly: + +- [ ] Every key page is reachable in ≤3 clicks from homepage +- [ ] Pillar/hub pages have links from all their spokes +- [ ] All spoke pages link back to their hub +- [ ] No orphan pages (pages with zero internal inbound links) +- [ ] Homepage links to 5-8 priority sections only +- [ ] Footer links limited to high-value pages (10-15 max) +- [ ] New content published in the last 30 days has at least 3 contextual inbound internal links +- [ ] No broken internal links (404s from internal sources) +- [ ] Anchor text is descriptive, not generic +- [ ] Pages with highest external backlinks are linking to money/conversion pages + +--- + +## Common Patterns That Fail + +### The Footer Dump +Putting 80 links in the footer because "they should be accessible." Google gives footer links minimal weight and won't thank you for linking to every blog post from there. Footer = navigation to key sections + legal. That's it. + +### The "Related Posts" Widget Approach Only +Auto-generated related posts widgets are fine as supplemental linking, but they don't replace intentional contextual linking. The widget links to "related" content by tag or category — not necessarily to what you actually want to rank. Do the manual work. + +### The Nav-Only Money Pages +Feature pages and pricing pages that only appear in the navigation get equity from nav links only. Powerful nav links are sitewide — but adding 5-10 contextual blog links to your pricing page is a significant equity boost. Write one blog post that organically links to pricing. That's real. + +### Linking to Pages You Want to Rank for the Wrong Topic +If your /blog/seo-guide has 30 internal links to it but all the anchor text says "our guide" and "learn more," you're not sending a topical signal. The link equity flows in, but Google doesn't know what topic to attribute. Fix anchor text. + +### Never Touching Old Posts +Old blog posts accumulate internal links over time because new posts link to them. But they rarely link out to newer, better content. When you publish new content, go back and update old posts to add contextual links to the new piece. This is one of the highest-ROI activities in content SEO. diff --git a/marketing-skill/site-architecture/references/url-design-guide.md b/marketing-skill/site-architecture/references/url-design-guide.md new file mode 100644 index 0000000..7bf90c1 --- /dev/null +++ b/marketing-skill/site-architecture/references/url-design-guide.md @@ -0,0 +1,220 @@ +# URL Design Guide + +URL structure by site type — with examples of what good and bad looks like in practice. + +--- + +## Universal URL Rules + +Before the site-specific patterns, these apply everywhere: + +1. **Lowercase always** — `/Blog/SEO-Tips` and `/blog/seo-tips` are different URLs. Always lowercase. +2. **Hyphens, not underscores** — Google treats hyphens as word separators. Underscores join words. `/seo-tips` not `/seo_tips`. +3. **No special characters** — No `%`, `&`, `#`, `?` in the path itself. +4. **No trailing slash inconsistency** — Pick a convention (`/page` or `/page/`) and enforce it sitewide with redirects. +5. **No dates in URLs unless required** — `/blog/2024/03/seo-tips` ages poorly. `/blog/seo-tips` is evergreen. +6. **Stop words are usually fine** — `/how-to-write-cold-emails` is readable and fine. Don't obsessively remove "how", "to", "a", "the" unless the URL is very long. +7. **Keep them short** — Under 75 characters is a good target. Shorter is usually better. + +--- + +## SaaS / B2B Software + +### Recommended Structure + +``` +/ (homepage) +/features +/features/[feature-name] e.g. /features/email-automation +/pricing +/solutions/[use-case] e.g. /solutions/sales-teams +/solutions/[industry] e.g. /solutions/healthcare +/integrations +/integrations/[tool-name] e.g. /integrations/salesforce +/blog +/blog/[post-slug] e.g. /blog/cold-email-templates +/customers +/customers/[customer-name] e.g. /customers/acme-corp +/about +/changelog +/docs (or subdomain: docs.example.com) +/docs/[topic]/[subtopic] +``` + +### What Works and What Doesn't + +| āœ… Do | āŒ Don't | +|-------|----------| +| `/pricing` | `/pricing-plans` (redundant) | +| `/features/email-automation` | `/product/features/email-automation/detail` (too deep) | +| `/blog/cold-email-guide` | `/blog/articles/cold-email/complete-guide-to-cold-email` (too long) | +| `/solutions/sales-teams` | `/solutions-for-sales-teams` (ugly) | +| `/integrations/hubspot` | `/connect-with/hubspot-integration` | + +### SaaS-Specific Notes + +- `/features/` pages should actually be rankable landing pages, not just nav items. +- `/solutions/` by use case captures bottom-funnel searches ("sales team email tool"). +- `/integrations/[tool]` pages are high-intent SEO goldmines — build a real page for each. +- Blog posts should live at `/blog/[slug]` — not `/resources/`, not `/learn/`, not `/content/`. Pick one. +- Changelog belongs at `/changelog` — some companies put it at `/releases` or `/updates`. Fine, just pick one. + +--- + +## Blog / Content Site + +### Recommended Structure + +``` +/ (homepage) +/[category] e.g. /seo, /email-marketing, /content +/[category]/[post-slug] e.g. /seo/technical-seo-audit-checklist +/guides (optional hub for long-form guides) +/guides/[guide-slug] e.g. /guides/cold-email-complete-guide +/tools (optional if you have free tools) +/tools/[tool-name] +/author/[author-slug] +/tag/[tag-name] (often better to noindex tags) +``` + +### What Works and What Doesn't + +| āœ… Do | āŒ Don't | +|-------|----------| +| `/seo/keyword-research-guide` | `/seo/keyword-research/a-complete-guide-to-keyword-research-for-beginners-in-2024` | +| `/guides/cold-email` | `/blog/2024/03/15/cold-email-guide` | +| `/author/reza-rezvani` | `/author?id=42` | +| Flat category → post structure | 4-level nesting | + +### Blog-Specific Notes + +- Date-based URLs (`/2024/03/15/slug`) age poorly and look stale. Avoid. +- Tag pages create duplicate/thin content at scale. Either noindex them or give them real content. +- If you have <500 posts, flat `/post-slug` is fine. If you have >500, category buckets help organization. +- Author pages are worth building as real pages — they help E-E-A-T signals. + +--- + +## E-Commerce + +### Recommended Structure + +``` +/ (homepage) +/collections (or /shop, /catalog) +/collections/[category] e.g. /collections/mens-shoes +/collections/[category]/[subcategory] e.g. /collections/mens-shoes/running +/products/[product-slug] e.g. /products/air-max-270-black +/brands/[brand-name] +/sale +/new-arrivals +/blog +/blog/[post-slug] +``` + +### What Works and What Doesn't + +| āœ… Do | āŒ Don't | +|-------|----------| +| `/products/air-max-270-black` | `/products?id=89472&color=black&size=10` | +| `/collections/mens-shoes` | `/products/shoes/men/athletic/running/all-styles` | +| Canonical on variant pages | Let `?color=red&size=10` create duplicate URLs | + +### E-Commerce-Specific Notes + +- Product variant pages (size, color) are the biggest duplicate content risk in e-commerce. Use canonical tags pointing to the base product URL, or use URL parameters and configure them in GSC. +- Filter and sort pages (`?sort=price-asc&brand=nike`) should either be canonicalized or blocked. +- Collection/category pages need real content to rank — not just a product grid. +- Discontinued products: don't just delete them. 301 to closest alternative or return 410 with a helpful message. + +--- + +## Local Business / Service Area + +### Recommended Structure (Single Location) + +``` +/ (homepage) +/services +/services/[service-name] e.g. /services/plumbing-repair +/about +/contact +/blog +/blog/[post-slug] +/areas-served (optional hub for service area pages) +/areas-served/[city-name] e.g. /areas-served/brooklyn +``` + +### Recommended Structure (Multi-Location) + +``` +/ (homepage) +/locations +/locations/[city] e.g. /locations/new-york +/locations/[city]/[service] e.g. /locations/new-york/plumbing +/services/[service-name] (generic service pages) +``` + +### Local-Specific Notes + +- City/location pages must have unique, locally relevant content — not just "Find our [service] in [city]" copy-pasted 47 times. +- `/areas-served/brooklyn` should have real information about serving Brooklyn, not a thin page. +- Multi-location sites: `/locations/[city]` works better than subdomain per city for smaller operations. Subdomains make sense for truly independent franchises. + +--- + +## URL Redirect Mapping (When Restructuring) + +If you're changing URLs, you need a 301 redirect map. Every old URL → new URL. No exceptions. + +**Redirect mapping process:** +1. Export all indexed URLs from Google Search Console (Crawl → Coverage → All) +2. Export all inbound links to your site (use Ahrefs, Semrush, or GSC) +3. Map old → new for every URL that has inbound links or search traffic +4. Implement 301 redirects server-side (not JS redirects, not meta refresh) +5. Monitor in GSC for 404 errors after migration +6. Update internal links — don't just redirect, fix the source links + +**Priority redirect tiers:** +- **Tier 1:** Pages with significant inbound external links — redirect these first +- **Tier 2:** Pages with significant organic traffic — redirect to preserve equity +- **Tier 3:** Pages with neither — still redirect, but lower urgency + +**Never:** +- Chain redirects more than 1 hop (`/old` → `/temp` → `/new` wastes equity) +- 302 redirect something that's a permanent move (use 301) +- Leave old URLs live as duplicates without canonicals + +--- + +## Canonicalization + +When the same content is accessible at multiple URLs, tell Google which one is canonical. + +```html + +``` + +Common scenarios requiring canonicals: +- `http://` vs `https://` — canonical should always be `https://` +- `www` vs non-www — pick one, canonical + 301 the other +- Trailing slash vs no trailing slash — `/page` and `/page/` are different URLs to Google +- Filtered/sorted product pages — canonical to base product/collection URL +- Paginated pages — canonical the first page (or use `rel=next`/`rel=prev`) +- Printer-friendly versions — canonical to main page +- Syndicated content — canonical to original source + +--- + +## HTTP Status Code Reference + +| Code | Meaning | Use | +|------|---------|-----| +| 200 | OK | Normal page | +| 301 | Moved Permanently | URL changed permanently — passes equity | +| 302 | Found (Temporary) | Temporary redirect — does NOT pass equity | +| 404 | Not Found | Page doesn't exist — configure a helpful 404 page | +| 410 | Gone | Page intentionally removed — Google deindexes faster than 404 | +| 503 | Service Unavailable | Maintenance mode — tell Google to come back later | + +Use 301, not 302, for all permanent URL changes. diff --git a/marketing-skill/site-architecture/scripts/sitemap_analyzer.py b/marketing-skill/site-architecture/scripts/sitemap_analyzer.py new file mode 100644 index 0000000..6b30c1f --- /dev/null +++ b/marketing-skill/site-architecture/scripts/sitemap_analyzer.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python3 +""" +sitemap_analyzer.py — Analyzes sitemap.xml files for structure, depth, and potential issues. + +Usage: + python3 sitemap_analyzer.py [sitemap.xml] + python3 sitemap_analyzer.py https://example.com/sitemap.xml (fetches via urllib) + cat sitemap.xml | python3 sitemap_analyzer.py + +If no file is provided, runs on embedded sample sitemap for demonstration. + +Output: Structural analysis with depth distribution, URL patterns, orphan candidates, + duplicate path detection, and JSON summary. +Stdlib only — no external dependencies. +""" + +import json +import sys +import re +import select +import urllib.request +import urllib.error +from collections import Counter, defaultdict +from urllib.parse import urlparse +import xml.etree.ElementTree as ET + + +# ─── Namespaces used in sitemaps ───────────────────────────────────────────── + +SITEMAP_NAMESPACES = { + "sm": "http://www.sitemaps.org/schemas/sitemap/0.9", + "image": "http://www.google.com/schemas/sitemap-image/1.1", + "video": "http://www.google.com/schemas/sitemap-video/1.1", + "news": "http://www.google.com/schemas/sitemap-news/0.9", + "xhtml": "http://www.w3.org/1999/xhtml", +} + +# ─── Sample sitemap (embedded) ──────────────────────────────────────────────── + +SAMPLE_SITEMAP = """ + + + + + https://example.com/ + daily + 1.0 + + + + https://example.com/pricing + https://example.com/about + https://example.com/contact + https://example.com/blog + + + https://example.com/features + https://example.com/features/email-automation + https://example.com/features/crm-integration + https://example.com/features/analytics + + + https://example.com/solutions/sales-teams + https://example.com/solutions/marketing-teams + + + https://example.com/blog/cold-email-guide + https://example.com/blog/email-open-rates + https://example.com/blog/crm-comparison + https://example.com/blog/sales-process-optimization + + + https://example.com/resources/guides/email/cold-outreach/advanced/templates + https://example.com/resources/guides/email/cold-outreach/advanced/scripts + + + https://example.com/blog/email-tips + https://example.com/resources/email-tips + + + https://example.com/search?q=cold+email&sort=recent + + + https://example.com/customers/acme-corp + https://example.com/customers/globex + + + https://example.com/privacy + https://example.com/terms + + +""" + + +# ─── URL Analysis ───────────────────────────────────────────────────────────── + +def get_depth(path: str) -> int: + """Return depth of a URL path. / = 0, /blog = 1, /blog/post = 2, etc.""" + parts = [p for p in path.strip("/").split("/") if p] + return len(parts) + + +def get_path_pattern(path: str) -> str: + """Replace variable segments with {slug} for pattern detection.""" + parts = path.strip("/").split("/") + normalized = [] + for p in parts: + if p: + # Keep static segments (likely structure), replace dynamic-looking ones + if re.match(r'^[a-z][-a-z]+$', p) and len(p) < 30: + normalized.append(p) + else: + normalized.append("{slug}") + return "/" + "/".join(normalized) if normalized else "/" + + +def has_query_params(url: str) -> bool: + return "?" in url + + +def looks_like_dynamic_url(url: str) -> bool: + parsed = urlparse(url) + return bool(parsed.query) + + +def detect_path_siblings(urls: list) -> list: + """Find URLs with same slug in different parent directories (potential duplicates).""" + slug_to_paths = defaultdict(list) + for url in urls: + path = urlparse(url).path.strip("/") + slug = path.split("/")[-1] if path else "" + if slug: + slug_to_paths[slug].append(url) + + duplicates = [] + for slug, paths in slug_to_paths.items(): + if len(paths) > 1: + # Only flag if they're in different directories + parents = set("/".join(urlparse(p).path.strip("/").split("/")[:-1]) for p in paths) + if len(parents) > 1: + duplicates.append({"slug": slug, "urls": paths}) + return duplicates + + +# ─── Sitemap Parser ────────────────────────────────────────────────────────── + +def parse_sitemap(content: str) -> list: + """Parse sitemap XML and return list of URL dicts.""" + urls = [] + + # Strip namespace declarations for simpler parsing + content_clean = re.sub(r'xmlns[^=]*="[^"]*"', '', content) + + try: + root = ET.fromstring(content_clean) + except ET.ParseError as e: + print(f"āŒ XML parse error: {e}", file=sys.stderr) + return [] + + # Handle sitemap index (points to other sitemaps) + if root.tag.endswith("sitemapindex") or root.tag == "sitemapindex": + print("ā„¹ļø This is a sitemap index file — it points to child sitemaps.") + print(" Child sitemaps:") + for sitemap in root.findall(".//{http://www.sitemaps.org/schemas/sitemap/0.9}loc") or root.findall(".//loc"): + print(f" - {sitemap.text}") + print(" Run this tool on each child sitemap for full analysis.") + return [] + + # Regular urlset + for url_el in root.findall(".//{http://www.sitemaps.org/schemas/sitemap/0.9}url") or root.findall(".//url"): + loc_el = url_el.find("{http://www.sitemaps.org/schemas/sitemap/0.9}loc") or url_el.find("loc") + lastmod_el = url_el.find("{http://www.sitemaps.org/schemas/sitemap/0.9}lastmod") or url_el.find("lastmod") + priority_el = url_el.find("{http://www.sitemaps.org/schemas/sitemap/0.9}priority") or url_el.find("priority") + + if loc_el is not None and loc_el.text: + urls.append({ + "url": loc_el.text.strip(), + "lastmod": lastmod_el.text.strip() if lastmod_el is not None and lastmod_el.text else None, + "priority": float(priority_el.text.strip()) if priority_el is not None and priority_el.text else None, + }) + + return urls + + +# ─── Analysis Engine ───────────────────────────────────────────────────────── + +def analyze_urls(urls: list) -> dict: + raw_urls = [u["url"] for u in urls] + paths = [urlparse(u).path for u in raw_urls] + + depths = [get_depth(p) for p in paths] + depth_counter = Counter(depths) + + dynamic_urls = [u for u in raw_urls if looks_like_dynamic_url(u)] + + patterns = Counter(get_path_pattern(urlparse(u).path) for u in raw_urls) + top_patterns = patterns.most_common(10) + + duplicate_slugs = detect_path_siblings(raw_urls) + + deep_urls = [(u, get_depth(urlparse(u).path)) for u in raw_urls if get_depth(urlparse(u).path) >= 4] + + # Extract top-level directories + top_dirs = Counter() + for p in paths: + parts = p.strip("/").split("/") + if parts and parts[0]: + top_dirs[parts[0]] += 1 + + return { + "total_urls": len(urls), + "depth_distribution": dict(sorted(depth_counter.items())), + "top_directories": dict(top_dirs.most_common(15)), + "dynamic_urls": dynamic_urls, + "deep_pages": deep_urls, + "duplicate_slug_candidates": duplicate_slugs, + "top_url_patterns": [{"pattern": p, "count": c} for p, c in top_patterns], + } + + +# ─── Report Printer ────────────────────────────────────────────────────────── + +def grade_depth_distribution(dist: dict) -> str: + deep = sum(v for k, v in dist.items() if k >= 4) + total = sum(dist.values()) + if total == 0: + return "N/A" + pct = deep / total * 100 + if pct < 5: + return "🟢 Excellent" + if pct < 15: + return "🟔 Acceptable" + return "šŸ”“ Too many deep pages" + + +def print_report(analysis: dict) -> None: + print("\n" + "═" * 62) + print(" SITEMAP STRUCTURE ANALYSIS") + print("═" * 62) + print(f"\n Total URLs: {analysis['total_urls']}") + + print("\n── Depth Distribution ──") + dist = analysis["depth_distribution"] + total = analysis["total_urls"] + for depth, count in sorted(dist.items()): + pct = count / total * 100 if total else 0 + bar = "ā–ˆ" * int(pct / 2) + label = "homepage" if depth == 0 else f"{' ' * min(depth, 3)}/{'…/' * (depth - 1)}page" + print(f" Depth {depth}: {count:4d} pages ({pct:5.1f}%) {bar} {label}") + + print(f"\n Rating: {grade_depth_distribution(dist)}") + deep_pct = sum(v for k, v in dist.items() if k >= 4) / total * 100 if total else 0 + if deep_pct >= 5: + print(" āš ļø More than 5% of pages are 4+ levels deep.") + print(" Consider flattening structure or adding shortcut links.") + + print("\n── Top-Level Directories ──") + for d, count in analysis["top_directories"].items(): + pct = count / total * 100 if total else 0 + print(f" /{d:<30s} {count:4d} URLs ({pct:.1f}%)") + + print("\n── URL Pattern Analysis ──") + for p in analysis["top_url_patterns"]: + print(f" {p['pattern']:<45s} {p['count']:4d} URLs") + + if analysis["dynamic_urls"]: + print(f"\n── Dynamic URLs Detected ({len(analysis['dynamic_urls'])}) ──") + print(" āš ļø URLs with query parameters should usually be excluded from sitemap.") + print(" Use canonical tags or robots.txt to prevent duplicate content indexing.") + for u in analysis["dynamic_urls"][:5]: + print(f" {u}") + if len(analysis["dynamic_urls"]) > 5: + print(f" ... and {len(analysis['dynamic_urls']) - 5} more") + + if analysis["deep_pages"]: + print(f"\n── Deep Pages (4+ Levels) ({len(analysis['deep_pages'])}) ──") + print(" āš ļø Pages this deep may have weak crawl equity. Add internal shortcuts.") + for url, depth in analysis["deep_pages"][:5]: + print(f" Depth {depth}: {url}") + if len(analysis["deep_pages"]) > 5: + print(f" ... and {len(analysis['deep_pages']) - 5} more") + + if analysis["duplicate_slug_candidates"]: + print(f"\n── Potential Duplicate Path Issues ({len(analysis['duplicate_slug_candidates'])}) ──") + print(" āš ļø Same slug appears in multiple directories — possible duplicate content.") + for item in analysis["duplicate_slug_candidates"][:5]: + print(f" Slug: '{item['slug']}'") + for u in item["urls"]: + print(f" - {u}") + if len(analysis["duplicate_slug_candidates"]) > 5: + print(f" ... and {len(analysis['duplicate_slug_candidates']) - 5} more") + + print("\n── Recommendations ──") + has_issues = False + if analysis["dynamic_urls"]: + print(" 1. Remove dynamic URLs (with ?) from sitemap.") + has_issues = True + if analysis["deep_pages"]: + print(f" {'2' if has_issues else '1'}. Flatten deep URL structures or add internal shortcut links.") + has_issues = True + if analysis["duplicate_slug_candidates"]: + print(f" {'3' if has_issues else '1'}. Review duplicate slug paths — consolidate or add canonical tags.") + has_issues = True + if not has_issues: + print(" āœ… No major structural issues detected in this sitemap.") + + print("\n" + "═" * 62) + + +# ─── Main ───────────────────────────────────────────────────────────────────── + +def load_content(source: str) -> str: + """Load sitemap from file path, URL, or stdin.""" + if source.startswith("http://") or source.startswith("https://"): + try: + with urllib.request.urlopen(source, timeout=10) as resp: + return resp.read().decode("utf-8") + except urllib.error.URLError as e: + print(f"Error fetching URL: {e}", file=sys.stderr) + sys.exit(1) + else: + try: + with open(source, "r", encoding="utf-8") as f: + return f.read() + except FileNotFoundError: + print(f"Error: File not found: {source}", file=sys.stderr) + sys.exit(1) + + +def main(): + if len(sys.argv) > 1: + arg = sys.argv[1] + if arg == "-": + content = sys.stdin.read() + else: + content = load_content(arg) + else: + print("No file or URL provided — running on embedded sample sitemap.\n") + content = SAMPLE_SITEMAP + + urls = parse_sitemap(content) + if not urls: + print("No URLs found in sitemap.", file=sys.stderr) + sys.exit(1) + + analysis = analyze_urls(urls) + print_report(analysis) + + # JSON output + print("\n── JSON Summary ──") + summary = { + "total_urls": analysis["total_urls"], + "depth_distribution": analysis["depth_distribution"], + "dynamic_url_count": len(analysis["dynamic_urls"]), + "deep_page_count": len(analysis["deep_pages"]), + "duplicate_slug_count": len(analysis["duplicate_slug_candidates"]), + "top_directories": analysis["top_directories"], + } + print(json.dumps(summary, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/marketing-skill/social-content/SKILL.md b/marketing-skill/social-content/SKILL.md new file mode 100644 index 0000000..d8e23bc --- /dev/null +++ b/marketing-skill/social-content/SKILL.md @@ -0,0 +1,323 @@ +--- +name: social-content +description: "When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform-specific strategies." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Social Content + +You are an expert social media strategist. Your goal is to help create engaging content that builds audience, drives engagement, and supports business goals. + +## Before Creating Content + +**Check for product marketing context first:** +If `.claude/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task. + +Gather this context (ask if not provided): + +### 1. Goals +- What's the primary objective? (Brand awareness, leads, traffic, community) +- What action do you want people to take? +- Are you building personal brand, company brand, or both? + +### 2. Audience +- Who are you trying to reach? +- What platforms are they most active on? +- What content do they engage with? + +### 3. Brand Voice +- What's your tone? (Professional, casual, witty, authoritative) +- Any topics to avoid? +- Any specific terminology or style guidelines? + +### 4. Resources +- How much time can you dedicate to social? +- Do you have existing content to repurpose? +- Can you create video content? + +--- + +## Platform Quick Reference + +| Platform | Best For | Frequency | Key Format | +|----------|----------|-----------|------------| +| LinkedIn | B2B, thought leadership | 3-5x/week | Carousels, stories | +| Twitter/X | Tech, real-time, community | 3-10x/day | Threads, hot takes | +| Instagram | Visual brands, lifestyle | 1-2 posts + Stories daily | Reels, carousels | +| TikTok | Brand awareness, younger audiences | 1-4x/day | Short-form video | +| Facebook | Communities, local businesses | 1-2x/day | Groups, native video | + +**For detailed platform strategies**: See [references/platforms.md](references/platforms.md) + +--- + +## Content Pillars Framework + +Build your content around 3-5 pillars that align with your expertise and audience interests. + +### Example for a SaaS Founder + +| Pillar | % of Content | Topics | +|--------|--------------|--------| +| Industry insights | 30% | Trends, data, predictions | +| Behind-the-scenes | 25% | Building the company, lessons learned | +| Educational | 25% | How-tos, frameworks, tips | +| Personal | 15% | Stories, values, hot takes | +| Promotional | 5% | Product updates, offers | + +### Pillar Development Questions + +For each pillar, ask: +1. What unique perspective do you have? +2. What questions does your audience ask? +3. What content has performed well before? +4. What can you create consistently? +5. What aligns with business goals? + +--- + +## Hook Formulas + +The first line determines whether anyone reads the rest. + +### Curiosity Hooks +- "I was wrong about [common belief]." +- "The real reason [outcome] happens isn't what you think." +- "[Impressive result] — and it only took [surprisingly short time]." + +### Story Hooks +- "Last week, [unexpected thing] happened." +- "I almost [big mistake/failure]." +- "3 years ago, I [past state]. Today, [current state]." + +### Value Hooks +- "How to [desirable outcome] (without [common pain]):" +- "[Number] [things] that [outcome]:" +- "Stop [common mistake]. Do this instead:" + +### Contrarian Hooks +- "Unpopular opinion: [bold statement]" +- "[Common advice] is wrong. Here's why:" +- "I stopped [common practice] and [positive result]." + +**For post templates and more hooks**: See [references/post-templates.md](references/post-templates.md) + +--- + +## Content Repurposing System + +Turn one piece of content into many: + +### Blog Post → Social Content + +| Platform | Format | +|----------|--------| +| LinkedIn | Key insight + link in comments | +| LinkedIn | Carousel of main points | +| Twitter/X | Thread of key takeaways | +| Instagram | Carousel with visuals | +| Instagram | Reel summarizing the post | + +### Repurposing Workflow + +1. **Create pillar content** (blog, video, podcast) +2. **Extract key insights** (3-5 per piece) +3. **Adapt to each platform** (format and tone) +4. **Schedule across the week** (spread distribution) +5. **Update and reshare** (evergreen content can repeat) + +--- + +## Content Calendar Structure + +### Weekly Planning Template + +| Day | LinkedIn | Twitter/X | Instagram | +|-----|----------|-----------|-----------| +| Mon | Industry insight | Thread | Carousel | +| Tue | Behind-scenes | Engagement | Story | +| Wed | Educational | Tips tweet | Reel | +| Thu | Story post | Thread | Educational | +| Fri | Hot take | Engagement | Story | + +### Batching Strategy (2-3 hours weekly) + +1. Review content pillar topics +2. Write 5 LinkedIn posts +3. Write 3 Twitter threads + daily tweets +4. Create Instagram carousel + Reel ideas +5. Schedule everything +6. Leave room for real-time engagement + +--- + +## Engagement Strategy + +### Daily Engagement Routine (30 min) + +1. Respond to all comments on your posts (5 min) +2. Comment on 5-10 posts from target accounts (15 min) +3. Share/repost with added insight (5 min) +4. Send 2-3 DMs to new connections (5 min) + +### Quality Comments + +- Add new insight, not just "Great post!" +- Share a related experience +- Ask a thoughtful follow-up question +- Respectfully disagree with nuance + +### Building Relationships + +- Identify 20-50 accounts in your space +- Consistently engage with their content +- Share their content with credit +- Eventually collaborate (podcasts, co-created content) + +--- + +## Analytics & Optimization + +### Metrics That Matter + +**Awareness:** Impressions, Reach, Follower growth rate + +**Engagement:** Engagement rate, Comments (higher value than likes), Shares/reposts, Saves + +**Conversion:** Link clicks, Profile visits, DMs received, Leads attributed + +### Weekly Review + +- Top 3 performing posts (why did they work?) +- Bottom 3 posts (what can you learn?) +- Follower growth trend +- Engagement rate trend +- Best posting times (from data) + +### Optimization Actions + +**If engagement is low:** +- Test new hooks +- Post at different times +- Try different formats +- Increase engagement with others + +**If reach is declining:** +- Avoid external links in post body +- Increase posting frequency +- Engage more in comments +- Test video/visual content + +--- + +## Content Ideas by Situation + +### When You're Starting Out +- Document your journey +- Share what you're learning +- Curate and comment on industry content +- Engage heavily with established accounts + +### When You're Stuck +- Repurpose old high-performing content +- Ask your audience what they want +- Comment on industry news +- Share a failure or lesson learned + +--- + +## Scheduling Best Practices + +### When to Schedule vs. Post Live + +**Schedule:** Core content posts, Threads, Carousels, Evergreen content + +**Post live:** Real-time commentary, Responses to news/trends, Engagement with others + +### Queue Management + +- Maintain 1-2 weeks of scheduled content +- Review queue weekly for relevance +- Leave gaps for spontaneous posts +- Adjust timing based on performance data + +--- + +## Reverse Engineering Viral Content + +Instead of guessing, analyze what's working for top creators in your niche: + +1. **Find creators** — 10-20 accounts with high engagement +2. **Collect data** — 500+ posts for analysis +3. **Analyze patterns** — Hooks, formats, CTAs that work +4. **Codify playbook** — Document repeatable patterns +5. **Layer your voice** — Apply patterns with authenticity +6. **Convert** — Bridge attention to business results + +**For the complete framework**: See [references/reverse-engineering.md](references/reverse-engineering.md) + +--- + +## Task-Specific Questions + +1. What platform(s) are you focusing on? +2. What's your current posting frequency? +3. Do you have existing content to repurpose? +4. What content has performed well in the past? +5. How much time can you dedicate weekly? +6. Are you building personal brand, company brand, or both? + +--- + +## Proactive Triggers + +Surface these issues WITHOUT being asked when you notice them in context: + +- **User wants to post the same content on every platform** → Flag platform format mismatch immediately; adapt tone, length, and structure per platform before writing. +- **No hook is provided or planned** → Stop and write the hook first; everything else is worthless if the first line doesn't land. +- **Posting frequency is unsustainable** (e.g., 3x/day on 4 platforms) → Flag burnout risk and recommend a focused 1-2 platform strategy with batching. +- **Promotional content exceeds 20% of the calendar** → Warn that reach will decline; rebalance toward educational and story-based pillars. +- **No engagement strategy exists** → Remind that posting without engaging is broadcasting, not building; offer the daily routine template. + +--- + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| A social post | Platform-native post with hook, body, CTA, and hashtag recommendations | +| A content calendar | Weekly or monthly table with topic, platform, format, pillar, and posting day | +| A repurposing plan | Source content mapped to 5-8 derivative social formats across platforms | +| Hook options | 5 hook variants (curiosity, story, value, contrarian, data) for a given topic | +| A LinkedIn thread | Full thread structure: hook tweet, 5-8 body tweets, CTA tweet, with formatting notes | + +--- + +## Communication + +All output follows the structured communication standard: + +- **Bottom line first** — deliver the post or calendar before explaining the strategy choices +- **What + Why + How** — every format or platform decision is explained +- **Platform-native by default** — never deliver generic copy; always adapt to the target platform +- **Confidence tagging** — 🟢 proven format / 🟔 test this / šŸ”“ depends on your audience + +Always include a hook as the first element. Never deliver body copy without it. For calendars, flag which posts are evergreen vs. timely. + +--- + +## Related Skills + +- **marketing-context**: USE as foundation before creating any content — loads brand voice, ICP, and tone guidelines. NOT a substitute for platform-specific adaptation. +- **copywriting**: USE when long-form page or landing page copy is needed. NOT for short-form social posts. +- **content-strategy**: USE when deciding what topics to cover before creating social posts. NOT for writing the posts themselves. +- **copy-editing**: USE to polish social copy drafts, especially for high-stakes campaigns. NOT for casual post creation. +- **marketing-ideas**: USE when brainstorming which social tactics or growth channels to pursue. NOT for writing specific posts. +- **content-production**: USE when operating a high-volume content machine across multiple creators. NOT for one-off post creation. +- **content-humanizer**: USE when AI-drafted posts sound robotic or templated. NOT for strategy or scheduling. +- **launch-strategy**: USE when coordinating social content around a product launch. NOT for evergreen posting schedules. diff --git a/marketing-skill/social-content/references/platforms.md b/marketing-skill/social-content/references/platforms.md new file mode 100644 index 0000000..f725a3d --- /dev/null +++ b/marketing-skill/social-content/references/platforms.md @@ -0,0 +1,163 @@ +# Platform-Specific Strategy Guide + +Detailed strategies for each major social platform. + +## LinkedIn + +**Best for:** B2B, thought leadership, professional networking, recruiting +**Audience:** Professionals, decision-makers, job seekers +**Posting frequency:** 3-5x per week +**Best times:** Tuesday-Thursday, 7-8am, 12pm, 5-6pm + +**What works:** +- Personal stories with business lessons +- Contrarian takes on industry topics +- Behind-the-scenes of building a company +- Data and original insights +- Carousel posts (document format) +- Polls that spark discussion + +**What doesn't:** +- Overly promotional content +- Generic motivational quotes +- Links in the main post (kills reach) +- Corporate speak without personality + +**Format tips:** +- First line is everything (hook before "see more") +- Use line breaks for readability +- 1,200-1,500 characters performs well +- Put links in comments, not post body +- Tag people sparingly and genuinely + +**Algorithm tips:** +- First hour engagement matters most +- Comments > reactions > clicks +- Dwell time (people reading) signals quality +- No external links in post body +- Document posts (carousels) get strong reach +- Polls drive engagement but don't build authority + +--- + +## Twitter/X + +**Best for:** Tech, media, real-time commentary, community building +**Audience:** Tech-savvy, news-oriented, niche communities +**Posting frequency:** 3-10x per day (including replies) +**Best times:** Varies by audience; test and measure + +**What works:** +- Hot takes and opinions +- Threads that teach something +- Behind-the-scenes moments +- Engaging with others' content +- Memes and humor (if on-brand) +- Real-time commentary on events + +**What doesn't:** +- Pure self-promotion +- Threads without a strong hook +- Ignoring replies and mentions +- Scheduling everything (no real-time presence) + +**Format tips:** +- Tweets under 100 characters get more engagement +- Threads: Hook in tweet 1, promise value, deliver +- Quote tweets with added insight beat plain retweets +- Use visuals to stop the scroll + +**Algorithm tips:** +- Replies and quote tweets build authority +- Threads keep people on platform (rewarded) +- Images and video get more reach +- Engagement in first 30 min matters +- Twitter Blue/Premium may boost reach + +--- + +## Instagram + +**Best for:** Visual brands, lifestyle, e-commerce, younger demographics +**Audience:** 18-44, visual-first consumers +**Posting frequency:** 1-2 feed posts per day, 3-10 Stories per day +**Best times:** 11am-1pm, 7-9pm + +**What works:** +- High-quality visuals +- Behind-the-scenes Stories +- Reels (short-form video) +- Carousels with value +- User-generated content +- Interactive Stories (polls, questions) + +**What doesn't:** +- Low-quality images +- Too much text in images +- Ignoring Stories and Reels +- Only promotional content + +**Format tips:** +- Reels get 2x reach of static posts +- First frame of Reels must hook +- Carousels: 10 slides with educational content +- Use all Story features (polls, links, etc.) + +**Algorithm tips:** +- Reels heavily prioritized over static posts +- Saves and shares > likes +- Stories keep you top of feed +- Consistency matters more than perfection +- Use all features (polls, questions, etc.) + +--- + +## TikTok + +**Best for:** Brand awareness, younger audiences, viral potential +**Audience:** 16-34, entertainment-focused +**Posting frequency:** 1-4x per day +**Best times:** 7-9am, 12-3pm, 7-11pm + +**What works:** +- Native, unpolished content +- Trending sounds and formats +- Educational content in entertaining wrapper +- POV and day-in-the-life content +- Responding to comments with videos +- Duets and stitches + +**What doesn't:** +- Overly produced content +- Ignoring trends +- Hard selling +- Repurposed horizontal video + +**Format tips:** +- Hook in first 1-2 seconds +- Keep it under 30 seconds to start +- Vertical only (9:16) +- Use trending sounds +- Post consistently to train algorithm + +--- + +## Facebook + +**Best for:** Communities, local businesses, older demographics, groups +**Audience:** 25-55+, community-oriented +**Posting frequency:** 1-2x per day +**Best times:** 1-4pm weekdays + +**What works:** +- Facebook Groups (community) +- Native video +- Live video +- Local content and events +- Discussion-prompting questions + +**What doesn't:** +- Links to external sites (reach killer) +- Pure promotional content +- Ignoring comments +- Cross-posting from other platforms without adaptation diff --git a/marketing-skill/social-content/references/post-templates.md b/marketing-skill/social-content/references/post-templates.md new file mode 100644 index 0000000..c61280b --- /dev/null +++ b/marketing-skill/social-content/references/post-templates.md @@ -0,0 +1,171 @@ +# Post Format Templates + +Ready-to-use templates for different platforms and content types. + +## LinkedIn Post Templates + +### The Story Post +``` +[Hook: Unexpected outcome or lesson] + +[Set the scene: When/where this happened] + +[The challenge you faced] + +[What you tried / what happened] + +[The turning point] + +[The result] + +[The lesson for readers] + +[Question to prompt engagement] +``` + +### The Contrarian Take +``` +[Unpopular opinion stated boldly] + +Here's why: + +[Reason 1] +[Reason 2] +[Reason 3] + +[What you recommend instead] + +[Invite discussion: "Am I wrong?"] +``` + +### The List Post +``` +[X things I learned about [topic] after [credibility builder]: + +1. [Point] — [Brief explanation] + +2. [Point] — [Brief explanation] + +3. [Point] — [Brief explanation] + +[Wrap-up insight] + +Which resonates most with you? +``` + +### The How-To +``` +How to [achieve outcome] in [timeframe]: + +Step 1: [Action] +↳ [Why this matters] + +Step 2: [Action] +↳ [Key detail] + +Step 3: [Action] +↳ [Common mistake to avoid] + +[Result you can expect] + +[CTA or question] +``` + +--- + +## Twitter/X Thread Templates + +### The Tutorial Thread +``` +Tweet 1: [Hook + promise of value] + +"Here's exactly how to [outcome] (step-by-step):" + +Tweet 2-7: [One step per tweet with details] + +Final tweet: [Summary + CTA] + +"If this was helpful, follow me for more on [topic]" +``` + +### The Story Thread +``` +Tweet 1: [Intriguing hook] + +"[Time] ago, [unexpected thing happened]. Here's the full story:" + +Tweet 2-6: [Story beats, building tension] + +Tweet 7: [Resolution and lesson] + +Final tweet: [Takeaway + engagement ask] +``` + +### The Breakdown Thread +``` +Tweet 1: [Company/person] just [did thing]. + +Here's why it's genius (and what you can learn): + +Tweet 2-6: [Analysis points] + +Tweet 7: [Your key takeaway] + +"[Related insight + follow CTA]" +``` + +--- + +## Instagram Templates + +### The Carousel Hook +``` +[Slide 1: Bold statement or question] +[Slides 2-9: One point per slide, visual + text] +[Slide 10: Summary + CTA] + +Caption: [Expand on the topic, add context, include CTA] +``` + +### The Reel Script +``` +Hook (0-2 sec): [Pattern interrupt or bold claim] +Setup (2-5 sec): [Context for the tip] +Value (5-25 sec): [The actual advice/content] +CTA (25-30 sec): [Follow, comment, share, link] +``` + +--- + +## Hook Formulas + +The first line determines whether anyone reads the rest. + +### Curiosity Hooks +- "I was wrong about [common belief]." +- "The real reason [outcome] happens isn't what you think." +- "[Impressive result] — and it only took [surprisingly short time]." +- "Nobody talks about [insider knowledge]." + +### Story Hooks +- "Last week, [unexpected thing] happened." +- "I almost [big mistake/failure]." +- "3 years ago, I [past state]. Today, [current state]." +- "[Person] told me something I'll never forget." + +### Value Hooks +- "How to [desirable outcome] (without [common pain]):" +- "[Number] [things] that [outcome]:" +- "The simplest way to [outcome]:" +- "Stop [common mistake]. Do this instead:" + +### Contrarian Hooks +- "Unpopular opinion: [bold statement]" +- "[Common advice] is wrong. Here's why:" +- "I stopped [common practice] and [positive result]." +- "Everyone says [X]. The truth is [Y]." + +### Social Proof Hooks +- "We [achieved result] in [timeframe]. Here's the full story:" +- "[Number] people asked me about [topic]. Here's my answer:" +- "[Authority figure] taught me [lesson]." diff --git a/marketing-skill/social-content/references/reverse-engineering.md b/marketing-skill/social-content/references/reverse-engineering.md new file mode 100644 index 0000000..6cb8413 --- /dev/null +++ b/marketing-skill/social-content/references/reverse-engineering.md @@ -0,0 +1,190 @@ +# Reverse Engineering Viral Content + +Instead of guessing what works, systematically analyze top-performing content in your niche and extract proven patterns. + +## The 6-Step Framework + +### 1. NICHE ID — Find Top Creators + +Identify 10-20 creators in your space who consistently get high engagement: + +**Selection criteria:** +- Posting consistently (3+ times/week) +- High engagement rate relative to follower count +- Audience overlap with your target market +- Mix of established and rising creators + +**Where to find them:** +- LinkedIn: Search by industry keywords, check "People also viewed" +- Twitter/X: Check who your target audience follows and engages with +- Use tools like SparkToro, Followerwonk, or manual research +- Look at who gets featured in industry newsletters + +### 2. SCRAPE — Collect Posts at Scale + +Gather 500-1000+ posts from your identified creators for analysis: + +**Tools:** +- **Apify** — LinkedIn scraper, Twitter scraper actors +- **Phantom Buster** — Multi-platform automation +- **Export tools** — Platform-specific export features +- **Manual collection** — For smaller datasets, copy/paste into spreadsheet + +**Data to collect:** +- Post text/content +- Engagement metrics (likes, comments, shares, saves) +- Post format (text-only, carousel, video, image) +- Posting time/day +- Hook/first line +- CTA used +- Topic/theme + +### 3. ANALYZE — Extract What Actually Works + +Sort and analyze the data to find patterns: + +**Quantitative analysis:** +- Rank posts by engagement rate +- Identify top 10% performers +- Look for format patterns (do carousels outperform?) +- Check timing patterns (best days/times) +- Compare topic performance + +**Qualitative analysis:** +- What hooks do top posts use? +- How long are high-performing posts? +- What emotional triggers appear? +- What formats repeat? +- What topics consistently perform? + +**Questions to answer:** +- What's the average length of top posts? +- Which hook types appear most in top 10%? +- What CTAs drive most comments? +- What topics get saved/shared most? + +### 4. PLAYBOOK — Codify Patterns + +Document repeatable patterns you can use: + +**Hook patterns to codify:** +``` +Pattern: "I [unexpected action] and [surprising result]" +Example: "I stopped posting daily and my engagement doubled" +Why it works: Curiosity gap + contrarian + +Pattern: "[Specific number] [things] that [outcome]:" +Example: "7 pricing mistakes that cost me $50K:" +Why it works: Specificity + loss aversion + +Pattern: "[Controversial take]" +Example: "Cold outreach is dead." +Why it works: Pattern interrupt + invites debate +``` + +**Format patterns:** +- Carousel: Hook slide → Problem → Solution steps → CTA +- Thread: Hook → Promise → Deliver → Recap → CTA +- Story post: Hook → Setup → Conflict → Resolution → Lesson + +**CTA patterns:** +- Question: "What would you add?" +- Agreement: "Agree or disagree?" +- Share: "Tag someone who needs this" +- Save: "Save this for later" + +### 5. LAYER VOICE — Apply Direct Response Principles + +Take proven patterns and make them yours with these voice principles: + +**"Smart friend who figured something out"** +- Write like you're texting advice to a friend +- Share discoveries, not lectures +- Use "I found that..." not "You should..." +- Be helpful, not preachy + +**Specific > Vague** +``` +āŒ "I made good revenue" +āœ… "I made $47,329" + +āŒ "It took a while" +āœ… "It took 47 days" + +āŒ "A lot of people" +āœ… "2,847 people" +``` + +**Short. Breathe. Land.** +- One idea per sentence +- Use line breaks liberally +- Let important points stand alone +- Create rhythm: short, short, longer explanation + +``` +āŒ "I spent three years building my business the wrong way before I finally realized that the key to success was focusing on fewer things and doing them exceptionally well." + +āœ… "I built wrong for 3 years. + +Then I figured it out. + +Focus on less. +Do it exceptionally well. + +Everything changed." +``` + +**Write from emotion** +- Start with how you felt, not what you did +- Use emotional words: frustrated, excited, terrified, obsessed +- Show vulnerability when authentic +- Connect the feeling to the lesson + +``` +āŒ "Here's what I learned about pricing" + +āœ… "I was terrified to raise my prices. + +My hands were shaking when I sent the email. + +Here's what happened..." +``` + +### 6. CONVERT — Turn Attention into Action + +Bridge from engagement to business results: + +**Soft conversions:** +- Newsletter signups in bio/comments +- Free resource offers in follow-up comments +- DM triggers ("Comment X and I'll send you...") +- Profile visits → optimized profile with clear CTA + +**Direct conversions:** +- Link in comments (not post body on LinkedIn) +- Contextual product mentions within valuable content +- Case study posts that naturally showcase your work +- "If you want help with this, DM me" (sparingly) + +--- + +## The Formula + +``` +1. Find what's already working (don't guess) +2. Extract the patterns (hooks, formats, CTAs) +3. Layer your authentic voice on top +4. Test and iterate based on your own data +``` + +## Reverse Engineering Checklist + +- [ ] Identified 10-20 top creators in niche +- [ ] Collected 500+ posts for analysis +- [ ] Ranked by engagement rate +- [ ] Documented top 10 hook patterns +- [ ] Documented top 5 format patterns +- [ ] Documented top 5 CTA patterns +- [ ] Created voice guidelines (specificity, brevity, emotion) +- [ ] Built template library from patterns +- [ ] Set up tracking for your own content performance diff --git a/marketing-skill/social-media-analyzer/SKILL.md b/marketing-skill/social-media-analyzer/SKILL.md index ede4004..0d2af6c 100644 --- a/marketing-skill/social-media-analyzer/SKILL.md +++ b/marketing-skill/social-media-analyzer/SKILL.md @@ -278,3 +278,32 @@ The sample campaign shows: - Content type performance by platform - Optimal posting times and frequency - ROI calculation formulas + +## Proactive Triggers + +- **Engagement rate below platform average** → Content isn't resonating. Analyze top performers for patterns. +- **Follower growth stalled** → Content distribution or frequency issue. Audit posting patterns. +- **High impressions, low engagement** → Reach without resonance. Content quality issue. +- **Competitor outperforming significantly** → Content gap. Analyze their successful posts. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Social media audit" | Performance analysis across platforms with benchmarks | +| "What's performing?" | Top content analysis with patterns and recommendations | +| "Competitor social analysis" | Competitive social media comparison with gaps | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **social-content**: For creating social posts. Use this skill for analyzing performance. +- **campaign-analytics**: For cross-channel analytics including social. +- **content-strategy**: For planning social content themes. +- **marketing-context**: Provides audience context for better analysis. diff --git a/marketing-skill/social-media-manager/SKILL.md b/marketing-skill/social-media-manager/SKILL.md new file mode 100644 index 0000000..4f54e3e --- /dev/null +++ b/marketing-skill/social-media-manager/SKILL.md @@ -0,0 +1,197 @@ +--- +name: social-media-manager +description: "When the user wants to develop social media strategy, plan content calendars, manage community engagement, or grow their social presence across platforms. Also use when the user mentions 'social media strategy,' 'social calendar,' 'community management,' 'social media plan,' 'grow followers,' 'engagement rate,' 'social media audit,' or 'which platforms should I use.' For writing individual social posts, see social-content. For analyzing social performance data, see social-media-analyzer." +license: MIT +metadata: + version: 1.0.0 + author: Alireza Rezvani + category: marketing + updated: 2026-03-06 +--- + +# Social Media Manager + +You are a senior social media strategist who has grown accounts from zero to six figures across every major platform. Your goal is to help build a sustainable social media presence that drives business results — not just vanity metrics. + +## Before Starting + +**Check for marketing context first:** +If `marketing-context.md` exists, read it for brand voice, audience personas, and goals. Only ask for what's missing. + +Gather this context (ask if not provided): + +### 1. Current State +- Which platforms are you active on? +- Current follower counts and engagement rates? +- How often are you posting? Who manages it? +- What's working? What isn't? + +### 2. Goals +- Brand awareness, lead generation, community building, or thought leadership? +- What does success look like in 90 days? + +### 3. Resources +- Who creates content? How much time per week? +- Budget for paid social (if any)? +- Tools you're using (scheduling, analytics)? + +## How This Skill Works + +### Mode 1: Build Strategy from Scratch +No social presence or starting fresh on a platform. Define platforms, cadence, content pillars, and growth plan. + +### Mode 2: Audit & Optimize +Active social presence that's underperforming. Analyze what's working, identify gaps, and rebuild the approach. + +### Mode 3: Scale & Systematize +Growing social presence that needs structure — content calendars, workflows, team processes, and measurement frameworks. + +--- + +## Platform Selection + +Not every platform deserves your time. Choose based on where your audience already spends time, not where you think you should be. + +### Platform-Audience Fit + +| Platform | Best For | Content Style | Posting Cadence | +|----------|----------|---------------|-----------------| +| **LinkedIn** | B2B, thought leadership, recruiting | Long-form posts, carousels, articles | 3-5x/week | +| **Twitter/X** | Tech, media, real-time, community | Short takes, threads, engagement | 1-3x/day | +| **Instagram** | B2C, visual brands, lifestyle | Reels, stories, carousels | 4-7x/week | +| **TikTok** | Young audiences, viral potential | Short video, trends, authentic | 1-3x/day | +| **YouTube** | Education, tutorials, long-form | Videos, shorts | 1-2x/week | + +**Rule of thumb:** Do 1-2 platforms exceptionally well before adding a third. Half-hearted presence on 5 platforms beats zero engagement on all of them. + +## Content Pillar Framework + +Every social strategy needs 3-5 content pillars that balance value delivery with business outcomes. + +### Pillar Structure + +| Pillar Type | Purpose | Mix | Example | +|-------------|---------|-----|---------| +| **Educational** | Teach your audience something useful | 40% | How-tos, tips, frameworks | +| **Behind the Scenes** | Build trust through transparency | 20% | Process, team, journey | +| **Social Proof** | Demonstrate results and credibility | 15% | Case studies, testimonials, wins | +| **Engagement** | Start conversations and build community | 15% | Questions, polls, debates | +| **Promotional** | Drive business outcomes | 10% | Product features, launches, offers | + +The 10% promotional cap is intentional. If your feed feels like an ad channel, people unfollow. + +## Content Calendar Design + +### Weekly Template + +| Day | Pillar | Format | Notes | +|-----|--------|--------|-------| +| Mon | Educational | Long post or carousel | High-value start to the week | +| Tue | Engagement | Question or poll | Drive comments for algorithm boost | +| Wed | Behind the Scenes | Photo or short video | Humanize the brand | +| Thu | Educational | Thread or how-to | Deep-dive content | +| Fri | Social Proof or Promo | Case study or launch | End-of-week conversion focus | + +### Batch Creation Workflow + +``` +Week -1: Plan topics for next week (30 min) +Day 1: Batch-create 5 posts (2 hours) +Daily: 15 min engagement (reply to comments, engage with others) +Week +1: Review analytics, adjust next week (30 min) +``` + +## Community Engagement + +Posting without engaging is broadcasting, not social media. Engagement is half the game. + +### The 1:1 Rule +For every post you publish, spend equal time engaging with others' content. Comment, share, respond. + +### Response Framework +- **Questions about your product** → Answer within 2 hours during business hours +- **Complaints** → Acknowledge publicly, resolve privately, follow up publicly +- **Praise** → Thank them, amplify with a reshare or quote +- **Trolls** → Ignore unless factually wrong. Never feed trolls. +- **Industry discussion** → Add genuine value, not self-promotion + +## Growth Tactics + +### Organic Growth Levers + +1. **Consistency** — Post on schedule. Algorithms reward reliability. +2. **Engagement bait done right** — Genuine questions, not "like if you agree." Polls work. Hot takes work. Asking for opinions works. +3. **Collaboration** — Co-create content with complementary accounts. +4. **Repurposing** — One blog post → 5-10 social posts across platforms. +5. **Trend riding** — Jump on relevant trends fast, but only if authentic to your brand. +6. **Community building** — Create spaces (Discord, Slack, Groups) not just audiences. + +### Metrics That Matter + +| Metric | What It Tells You | Target | +|--------|-------------------|--------| +| Engagement rate | Content resonance | >3% (LinkedIn), >1% (Twitter), >2% (Instagram) | +| Follower growth rate | Audience building momentum | >5% monthly | +| Click-through rate | Content driving action | >1% | +| Share/save rate | Content worth keeping | Higher = content is genuinely useful | +| DM conversations | Real relationship building | Growing month-over-month | + +**Vanity metrics to deprioritize:** Raw follower count, impressions (without engagement), reach (without action). + +--- + +## Social Media Audit Checklist + +### Profile Audit +- [ ] Profile photo: recognizable, consistent across platforms +- [ ] Bio: clear value proposition, not job title listing +- [ ] Link: drives to relevant landing page (not just homepage) +- [ ] Pinned post: best-performing or most important content + +### Content Audit +- [ ] Posting consistency: regular cadence or sporadic? +- [ ] Content mix: balanced across pillars or all promotional? +- [ ] Format variety: text, images, video, carousels? +- [ ] Voice consistency: matches brand across all posts? + +### Engagement Audit +- [ ] Response time: within 2 hours or days later? +- [ ] Comment quality: genuine replies or "thanks!"? +- [ ] Outbound engagement: engaging with others' content? +- [ ] Community participation: in relevant groups/conversations? + +--- + +## Proactive Triggers + +- **Posting frequency dropped below 3x/week** → Consistency matters more than quality. Batch-create to maintain cadence. +- **Engagement rate below platform average** → Content isn't resonating. Audit last 20 posts for patterns — which got engagement, which didn't? +- **100% promotional content** → Audience fatigue incoming. Shift to 80/20 value/promo split. +- **No engagement with others' content** → Social media is bilateral. Spend 15 min/day commenting on relevant posts. +- **Same content format every post** → Algorithm fatigue. Mix formats: text, carousel, video, poll. + +## Output Artifacts + +| When you ask for... | You get... | +|---------------------|------------| +| "Social media strategy" | Platform selection + content pillars + posting cadence + 90-day growth plan | +| "Content calendar" | 4-week calendar with topics, formats, pillars, and posting times | +| "Social media audit" | Full audit: profile, content, engagement, growth with prioritized actions | +| "Grow my LinkedIn" | Platform-specific growth plan with content examples and engagement tactics | +| "Community management plan" | Response framework + engagement workflow + escalation rules | + +## Communication + +All output passes quality verification: +- Self-verify: source attribution, assumption audit, confidence scoring +- Output format: Bottom Line → What (with confidence) → Why → How to Act +- Results only. Every finding tagged: 🟢 verified, 🟔 medium, šŸ”“ assumed. + +## Related Skills + +- **social-content**: For writing individual social posts. NOT for strategy (that's this skill). +- **social-media-analyzer**: For analyzing social media performance data. +- **content-strategy**: For planning broader content that feeds into social. +- **copywriting**: For landing pages and web copy that social drives to. +- **marketing-context**: Foundation — reads brand voice for consistent social tone. +- **ad-creative**: For paid social ad copy, distinct from organic social content. diff --git a/marketing-skill/social-media-manager/scripts/social_calendar_generator.py b/marketing-skill/social-media-manager/scripts/social_calendar_generator.py new file mode 100644 index 0000000..f4098b7 --- /dev/null +++ b/marketing-skill/social-media-manager/scripts/social_calendar_generator.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python3 +""" +social_calendar_generator.py — Social Media Content Calendar Generator +100% stdlib, no pip installs required. + +Usage: + python3 social_calendar_generator.py # demo mode + python3 social_calendar_generator.py --config config.json + python3 social_calendar_generator.py --config config.json --json + python3 social_calendar_generator.py --config config.json --markdown > calendar.md + python3 social_calendar_generator.py --start 2026-04-01 --weeks 4 + +config.json format: + { + "pillars": [ + {"name": "Educational", "description": "Tips, tutorials, how-tos", "emoji": "šŸŽ“", "weight": 3}, + {"name": "Inspirational", "description": "Success stories, quotes", "emoji": "✨", "weight": 2}, + {"name": "Product", "description": "Features, demos", "emoji": "šŸ› ", "weight": 2}, + {"name": "Community", "description": "UGC, shoutouts, polls", "emoji": "šŸ¤", "weight": 1} + ], + "platforms": [ + {"name": "LinkedIn", "posts_per_week": 3, "best_days": ["Monday","Tuesday","Wednesday","Thursday"]}, + {"name": "Twitter/X", "posts_per_week": 5, "best_days": ["Monday","Tuesday","Wednesday","Thursday","Friday"]} + ], + "start_date": "2026-04-07", + "weeks": 4 + } +""" + +import argparse +import json +import sys +from datetime import date, timedelta +from collections import defaultdict + + +# --------------------------------------------------------------------------- +# Defaults / sample data +# --------------------------------------------------------------------------- + +DEMO_CONFIG = { + "pillars": [ + {"name": "Educational", "description": "Tips, tutorials, how-tos", "emoji": "šŸŽ“", "weight": 3}, + {"name": "Inspirational", "description": "Success stories & quotes", "emoji": "✨", "weight": 2}, + {"name": "Product", "description": "Feature demos & updates", "emoji": "šŸ›  ", "weight": 2}, + {"name": "Community", "description": "UGC, polls & shoutouts", "emoji": "šŸ¤", "weight": 1}, + ], + "platforms": [ + { + "name": "LinkedIn", + "posts_per_week": 3, + "best_days": ["Monday", "Tuesday", "Wednesday", "Thursday"], + "content_type_hint": "Long-form insights, carousels, thought leadership", + }, + { + "name": "Twitter/X", + "posts_per_week": 5, + "best_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], + "content_type_hint": "Threads, quick tips, hot takes, polls", + }, + ], + "start_date": None, # defaults to next Monday + "weeks": 4, +} + +CONTENT_TYPE_HINTS = { + "Educational": ["How-to thread", "Quick tip", "Carousel: 5 steps", "Tutorial link"], + "Inspirational": ["Quote image", "Success story", "Before/after", "Motivational thread"], + "Product": ["Feature demo GIF", "Changelog post", "Use-case spotlight", "Behind the scenes"], + "Community": ["Poll", "User shoutout", "Question post", "Community highlight"], +} + +WEEKDAY_NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] + + +# --------------------------------------------------------------------------- +# Pillar scheduler — weighted round-robin +# --------------------------------------------------------------------------- + +def build_pillar_sequence(pillars: list, length: int) -> list: + """ + Build a balanced pillar rotation of `length` posts using weighted distribution. + Uses a deterministic greedy algorithm (no random, reproducible). + """ + names = [p["name"] for p in pillars] + weights = [p.get("weight", 1) for p in pillars] + total_w = sum(weights) + + # Target proportion per pillar + targets = [w / total_w for w in weights] + + sequence = [] + counts = [0] * len(pillars) + + for _ in range(length): + # Pick pillar most "behind" its target proportion + scores = [] + for i, name in enumerate(names): + current_prop = counts[i] / (len(sequence) + 1) if sequence else 0 + scores.append(targets[i] - current_prop) + best = scores.index(max(scores)) + sequence.append(names[best]) + counts[best] += 1 + + return sequence + + +# --------------------------------------------------------------------------- +# Calendar builder +# --------------------------------------------------------------------------- + +def next_monday(from_date: date = None) -> date: + d = from_date or date.today() + days_ahead = (0 - d.weekday()) % 7 + if days_ahead == 0: + days_ahead = 7 + return d + timedelta(days=days_ahead) + + +def parse_date(s: str) -> date: + return date.fromisoformat(s) + + +def build_calendar(config: dict) -> dict: + pillars = config.get("pillars", DEMO_CONFIG["pillars"]) + platforms = config.get("platforms", DEMO_CONFIG["platforms"]) + weeks = config.get("weeks", 4) + + start_raw = config.get("start_date") + if start_raw: + start = parse_date(start_raw) + else: + start = next_monday() + + pillar_map = {p["name"]: p for p in pillars} + + # Pre-compute total posts per platform + calendar_by_platform = {} + + for platform in platforms: + pname = platform["name"] + ppw = platform.get("posts_per_week", 3) + best_days = platform.get("best_days", WEEKDAY_NAMES[:5]) + + # Generate post dates across the period + post_dates = [] + for week in range(weeks): + week_start = start + timedelta(weeks=week) + day_count = 0 + for day_offset in range(7): + if day_count >= ppw: + break + d = week_start + timedelta(days=day_offset) + d_name = WEEKDAY_NAMES[d.weekday()] + if d_name in best_days: + post_dates.append(d) + day_count += 1 + + total_posts = len(post_dates) + pillar_seq = build_pillar_sequence(pillars, total_posts) + + posts = [] + for i, (post_date, pillar_name) in enumerate(zip(post_dates, pillar_seq)): + pillar = pillar_map[pillar_name] + hints = CONTENT_TYPE_HINTS.get(pillar_name, ["Post"]) + ct_hint = hints[i % len(hints)] + posts.append({ + "date": post_date.isoformat(), + "weekday": WEEKDAY_NAMES[post_date.weekday()], + "week_number": (post_date - start).days // 7 + 1, + "platform": pname, + "pillar": pillar_name, + "pillar_emoji": pillar.get("emoji", ""), + "description": pillar.get("description", ""), + "content_type": ct_hint, + "content_type_hint": platform.get("content_type_hint", ""), + }) + + # Pillar distribution stats + dist = defaultdict(int) + for p in posts: + dist[p["pillar"]] += 1 + dist_pct = {k: round(v / total_posts * 100) for k, v in dist.items()} + + calendar_by_platform[pname] = { + "platform": pname, + "posts_per_week": ppw, + "total_weeks": weeks, + "total_posts": total_posts, + "best_days": best_days, + "posts": posts, + "pillar_distribution": dict(dist), + "pillar_pct": dist_pct, + } + + # Global summary + all_posts = [] + for pc in calendar_by_platform.values(): + all_posts.extend(pc["posts"]) + all_posts.sort(key=lambda p: (p["date"], p["platform"])) + + return { + "meta": { + "start_date": start.isoformat(), + "end_date": (start + timedelta(weeks=weeks) - timedelta(days=1)).isoformat(), + "weeks": weeks, + "platforms": [p["name"] for p in platforms], + "total_posts": len(all_posts), + "pillars": [p["name"] for p in pillars], + }, + "platforms": calendar_by_platform, + "timeline": all_posts, # merged, date-sorted + } + + +# --------------------------------------------------------------------------- +# Markdown output +# --------------------------------------------------------------------------- + +def build_markdown(result: dict) -> str: + m = result["meta"] + lines = [] + lines.append(f"# Social Media Content Calendar") + lines.append(f"**Period:** {m['start_date']} → {m['end_date']} " + f"| **{m['weeks']} weeks** | **{m['total_posts']} total posts**\n") + + # Per-platform distribution + for pname, pc in result["platforms"].items(): + lines.append(f"## {pname} ({pc['total_posts']} posts)\n") + lines.append("**Pillar distribution:**") + for pillar, count in pc["pillar_distribution"].items(): + pct = pc["pillar_pct"][pillar] + lines.append(f"- {pillar}: {count} posts ({pct}%)") + lines.append("") + + # Weekly calendar tables + for week_num in range(1, m["weeks"] + 1): + lines.append(f"## Week {week_num}\n") + header = "| Date | Day | " + " | ".join(m["platforms"]) + " |" + sep = "|---|---|" + "|".join(["---"] * len(m["platforms"])) + "|" + lines.append(header) + lines.append(sep) + + # Group by date + week_posts = defaultdict(dict) + for post in result["timeline"]: + if post["week_number"] == week_num: + week_posts[post["date"]][post["platform"]] = post + + for day_date in sorted(week_posts.keys()): + day_posts = week_posts[day_date] + weekday = list(day_posts.values())[0]["weekday"] if day_posts else "" + cells = [] + for pname in m["platforms"]: + if pname in day_posts: + p = day_posts[pname] + cell = f"{p['pillar_emoji']} **{p['pillar']}**
{p['content_type']}" + else: + cell = "—" + cells.append(cell) + lines.append(f"| {day_date} | {weekday} | " + " | ".join(cells) + " |") + + lines.append("") + + # Legend + lines.append("## Content Pillars\n") + for pc in result["platforms"].values(): + break + from_meta = result["meta"]["pillars"] + lines.append("| Pillar | Description |") + lines.append("|---|---|") + for pname, pc in result["platforms"].items(): + # Get pillar descriptions from first platform's posts + pillar_desc = {} + for post in pc["posts"]: + pillar_desc[post["pillar"]] = post["description"] + for pillar in from_meta: + desc = pillar_desc.get(pillar, "") + lines.append(f"| {pillar} | {desc} |") + break + + lines.append("") + return "\n".join(lines) + + +# --------------------------------------------------------------------------- +# Pretty terminal output +# --------------------------------------------------------------------------- + +def pretty_print(result: dict) -> None: + m = result["meta"] + print("\n" + "=" * 70) + print(" šŸ“… SOCIAL MEDIA CONTENT CALENDAR GENERATOR") + print("=" * 70) + print(f"\n Period : {m['start_date']} → {m['end_date']} ({m['weeks']} weeks)") + print(f" Platforms : {', '.join(m['platforms'])}") + print(f" Total posts: {m['total_posts']}") + print(f" Pillars : {', '.join(m['pillars'])}") + + for pname, pc in result["platforms"].items(): + print(f"\n {'─'*60}") + print(f" šŸ“£ {pname.upper()} — {pc['total_posts']} posts " + f"({pc['posts_per_week']}/week)") + print(f" Best days: {', '.join(pc['best_days'])}") + print(f" Pillar distribution:") + for pillar, count in pc["pillar_distribution"].items(): + pct = pc["pillar_pct"][pillar] + bar = "ā–ˆ" * (pct // 5) + "ā–‘" * (20 - pct // 5) + print(f" {pillar:<16} {count:>3} posts {pct:>3}% {bar}") + + print(f"\n {'─'*70}") + print(f" šŸ“† WEEKLY SCHEDULE\n") + + # Group timeline by week + from collections import defaultdict + weeks_data = defaultdict(list) + for post in result["timeline"]: + weeks_data[post["week_number"]].append(post) + + for week_num in sorted(weeks_data.keys()): + print(f" WEEK {week_num}") + print(f" {'Date':<12} {'Day':<11}" + + "".join(f" {p:<22}" for p in m["platforms"])) + print(" " + "─" * (12 + 11 + 23 * len(m["platforms"]))) + + # Group by date + day_map = defaultdict(dict) + for post in weeks_data[week_num]: + day_map[post["date"]][post["platform"]] = post + + for day_date in sorted(day_map.keys()): + dp = day_map[day_date] + weekday = list(dp.values())[0]["weekday"] + row = f" {day_date:<12} {weekday:<11}" + for pname in m["platforms"]: + if pname in dp: + p = dp[pname] + cell = f"{p['pillar_emoji']} {p['pillar'][:10]}/{p['content_type'][:8]}" + else: + cell = "—" + row += f" {cell:<22}" + print(row) + print() + + print(" šŸ’” TIP: Re-run with --markdown to export a copyable Markdown table.\n") + + +# --------------------------------------------------------------------------- +# CLI +# --------------------------------------------------------------------------- + +def parse_args(): + parser = argparse.ArgumentParser( + description="Generate a social media content calendar with balanced pillar distribution.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--config", type=str, default=None, + help="Path to JSON config file") + parser.add_argument("--start", type=str, default=None, + help="Start date YYYY-MM-DD (overrides config)") + parser.add_argument("--weeks", type=int, default=None, + help="Number of weeks to generate (overrides config)") + parser.add_argument("--json", action="store_true", + help="Output calendar as JSON") + parser.add_argument("--markdown", action="store_true", + help="Output calendar as Markdown") + return parser.parse_args() + + +def main(): + args = parse_args() + + if args.config: + with open(args.config) as f: + config = json.load(f) + else: + print("šŸ”¬ DEMO MODE — using sample config (4 pillars, 2 platforms)\n", + file=sys.stderr) + config = dict(DEMO_CONFIG) + + # CLI overrides + if args.start: + config["start_date"] = args.start + if args.weeks: + config["weeks"] = args.weeks + + result = build_calendar(config) + + if args.json: + print(json.dumps(result, indent=2, default=str)) + elif args.markdown: + print(build_markdown(result)) + else: + pretty_print(result) + + +if __name__ == "__main__": + main()