create-hq 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deps.d.ts +4 -0
- package/dist/deps.d.ts.map +1 -0
- package/dist/deps.js +65 -0
- package/dist/deps.js.map +1 -0
- package/dist/git.d.ts +3 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +19 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/scaffold.d.ts +8 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +130 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/ui.d.ts +7 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +36 -0
- package/dist/ui.js.map +1 -0
- package/package.json +41 -0
- package/template/.claude/CLAUDE.md +202 -0
- package/template/.claude/commands/checkpoint.md +127 -0
- package/template/.claude/commands/cleanup.md +307 -0
- package/template/.claude/commands/execute-task.md +440 -0
- package/template/.claude/commands/exit-plan.md +41 -0
- package/template/.claude/commands/handoff.md +97 -0
- package/template/.claude/commands/learn.md +218 -0
- package/template/.claude/commands/metrics.md +118 -0
- package/template/.claude/commands/newworker.md +162 -0
- package/template/.claude/commands/nexttask.md +67 -0
- package/template/.claude/commands/prd.md +238 -0
- package/template/.claude/commands/reanchor.md +51 -0
- package/template/.claude/commands/remember.md +126 -0
- package/template/.claude/commands/run-project.md +348 -0
- package/template/.claude/commands/run.md +110 -0
- package/template/.claude/commands/search-reindex.md +62 -0
- package/template/.claude/commands/search.md +100 -0
- package/template/.claude/commands/setup.md +381 -0
- package/template/.claude/scripts/pure-ralph-loop.ps1 +312 -0
- package/template/.claude/scripts/pure-ralph-loop.sh +859 -0
- package/template/CHANGELOG.md +220 -0
- package/template/LICENSE +21 -0
- package/template/MIGRATION.md +259 -0
- package/template/README.md +368 -0
- package/template/data/journal/.gitkeep +0 -0
- package/template/docs/images/ascii-banner-options.md +122 -0
- package/template/docs/images/hq-banner.svg +105 -0
- package/template/knowledge/Ralph/01-overview.md +71 -0
- package/template/knowledge/Ralph/02-core-concepts.md +114 -0
- package/template/knowledge/Ralph/03-how-ralph-works.md +184 -0
- package/template/knowledge/Ralph/04-back-pressure.md +222 -0
- package/template/knowledge/Ralph/05-specifications.md +210 -0
- package/template/knowledge/Ralph/06-agents-md.md +222 -0
- package/template/knowledge/Ralph/07-implementation.md +316 -0
- package/template/knowledge/Ralph/08-economics.md +182 -0
- package/template/knowledge/Ralph/09-resources.md +145 -0
- package/template/knowledge/Ralph/10-claude-code-workflow.md +212 -0
- package/template/knowledge/Ralph/11-team-training-guide.md +383 -0
- package/template/knowledge/Ralph/README.md +40 -0
- package/template/knowledge/ai-security-framework/CONTRIBUTING.md +139 -0
- package/template/knowledge/ai-security-framework/GLOSSARY.md +176 -0
- package/template/knowledge/ai-security-framework/LICENSE +21 -0
- package/template/knowledge/ai-security-framework/QUICK-START.md +172 -0
- package/template/knowledge/ai-security-framework/README.md +232 -0
- package/template/knowledge/ai-security-framework/checklists/browser-security.md +301 -0
- package/template/knowledge/ai-security-framework/checklists/credential-isolation.md +322 -0
- package/template/knowledge/ai-security-framework/checklists/incident-response.md +288 -0
- package/template/knowledge/ai-security-framework/checklists/pre-flight.md +249 -0
- package/template/knowledge/ai-security-framework/checklists/weekly-audit.md +159 -0
- package/template/knowledge/ai-security-framework/configs/audit-logging.md +372 -0
- package/template/knowledge/ai-security-framework/configs/kill-switches.md +354 -0
- package/template/knowledge/ai-security-framework/docs/01-core-principles.md +256 -0
- package/template/knowledge/ai-security-framework/docs/02-threat-landscape.md +326 -0
- package/template/knowledge/ai-security-framework/docs/03-security-posture.md +250 -0
- package/template/knowledge/ai-security-framework/templates/agents-security.md +233 -0
- package/template/knowledge/design-styles/README.md +42 -0
- package/template/knowledge/design-styles/american-industrial.md +136 -0
- package/template/knowledge/design-styles/ethereal-abstract.md +133 -0
- package/template/knowledge/design-styles/liminal-portal.md +111 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G-3m4YPW0AADdu2.jpeg +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G-JJlt5WwAABK3K.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G-JJmj5W0AEbJ-7.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G59fgNuXkAAKLJQ (1).jpeg +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G59fgNuXkAAKLJQ.jpeg +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G7fVkn3WEAAM-ST.jpeg +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G8ECO5JWEAIksyn.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G9-3GQSWoAA8eqZ.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G9xEOqrXkAEZRcs.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G_MVeJrXQAA8sx4.jpeg +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/G_RSkmGXkAAgAVZ.png +0 -0
- package/template/knowledge/design-styles/swipes/american-industrial/README.md +31 -0
- package/template/knowledge/design-styles/swipes/american-industrial/qyqtg7Dq.png +0 -0
- package/template/knowledge/dev-team/README.md +35 -0
- package/template/knowledge/dev-team/patterns/README.md +34 -0
- package/template/knowledge/dev-team/patterns/frontend/react-best-practices.md +178 -0
- package/template/knowledge/dev-team/troubleshooting/README.md +31 -0
- package/template/knowledge/dev-team/workflows/README.md +49 -0
- package/template/knowledge/hq/checkpoint-schema.json +51 -0
- package/template/knowledge/hq/index-md-spec.md +74 -0
- package/template/knowledge/hq/thread-schema.md +153 -0
- package/template/knowledge/hq-core/checkpoint-schema.json +51 -0
- package/template/knowledge/hq-core/index-md-spec.md +74 -0
- package/template/knowledge/hq-core/thread-schema.md +153 -0
- package/template/knowledge/loom/README.md +51 -0
- package/template/knowledge/loom/architecture.md +125 -0
- package/template/knowledge/loom/code-style.md +169 -0
- package/template/knowledge/loom/llm-proxy.md +132 -0
- package/template/knowledge/loom/state-machine.md +131 -0
- package/template/knowledge/loom/thread-system.md +117 -0
- package/template/knowledge/loom/tools.md +94 -0
- package/template/knowledge/loom/weaver.md +96 -0
- package/template/knowledge/loom/web-frontend.md +131 -0
- package/template/knowledge/projects/README.md +72 -0
- package/template/knowledge/projects/templates/README.template.md +28 -0
- package/template/knowledge/workers/README.md +195 -0
- package/template/knowledge/workers/ralph-loop-pattern.md +157 -0
- package/template/knowledge/workers/skill-schema.md +182 -0
- package/template/knowledge/workers/state-machine.md +102 -0
- package/template/knowledge/workers/templates/base-worker.yaml +73 -0
- package/template/knowledge/workers/templates/code-worker.yaml +85 -0
- package/template/knowledge/workers/templates/skill.yaml +49 -0
- package/template/knowledge/workers/templates/social-worker.yaml +70 -0
- package/template/modules/examples/full-manifest.yaml +92 -0
- package/template/modules/examples/minimal.yaml +14 -0
- package/template/modules/modules.yaml +59 -0
- package/template/projects/.gitkeep +0 -0
- package/template/projects/incorporate-workers-into-pure-ralph/prd.json +88 -0
- package/template/projects/pure-ralph-branch-isolation/README.md +114 -0
- package/template/projects/pure-ralph-branch-isolation/prd.json +123 -0
- package/template/projects/purist-ralph-loop/README.md +148 -0
- package/template/projects/purist-ralph-loop/prd.json +135 -0
- package/template/projects/ralph-test/prd.json +50 -0
- package/template/prompts/pure-ralph-base.md +551 -0
- package/template/settings/.gitkeep +0 -0
- package/template/settings/pure-ralph.json +42 -0
- package/template/social-content/drafts/INDEX.md +21 -0
- package/template/social-content/drafts/linkedin/.gitkeep +1 -0
- package/template/social-content/drafts/x/.gitkeep +1 -0
- package/template/social-content/images/.gitkeep +1 -0
- package/template/starter-projects/code-worker/README.md +97 -0
- package/template/starter-projects/code-worker/prd.json +45 -0
- package/template/starter-projects/personal-assistant/README.md +42 -0
- package/template/starter-projects/personal-assistant/prd.json +43 -0
- package/template/starter-projects/social-media/README.md +60 -0
- package/template/starter-projects/social-media/prd.json +43 -0
- package/template/workers/content-brand/README.md +59 -0
- package/template/workers/content-brand/skills/messaging-alignment.md +91 -0
- package/template/workers/content-brand/skills/tone-check.md +76 -0
- package/template/workers/content-brand/skills/voice-analysis.md +68 -0
- package/template/workers/content-brand/worker.yaml +81 -0
- package/template/workers/content-legal/README.md +80 -0
- package/template/workers/content-legal/skills/claim-substantiation.md +150 -0
- package/template/workers/content-legal/skills/compliance-scan.md +123 -0
- package/template/workers/content-legal/skills/disclaimer-check.md +146 -0
- package/template/workers/content-legal/worker.yaml +118 -0
- package/template/workers/content-product/README.md +77 -0
- package/template/workers/content-product/skills/claim-verification.md +96 -0
- package/template/workers/content-product/skills/feature-accuracy.md +117 -0
- package/template/workers/content-product/skills/stats-check.md +128 -0
- package/template/workers/content-product/worker.yaml +97 -0
- package/template/workers/content-sales/README.md +70 -0
- package/template/workers/content-sales/skills/conversion-analysis.md +96 -0
- package/template/workers/content-sales/skills/cta-audit.md +107 -0
- package/template/workers/content-sales/skills/value-prop-check.md +114 -0
- package/template/workers/content-sales/worker.yaml +93 -0
- package/template/workers/content-shared/cli.ts +242 -0
- package/template/workers/content-shared/index.ts +234 -0
- package/template/workers/content-shared/lib/accuracy-analyzer.ts +661 -0
- package/template/workers/content-shared/lib/analyze.ts +370 -0
- package/template/workers/content-shared/lib/brand-analyzer.ts +526 -0
- package/template/workers/content-shared/lib/cms-integration.ts +446 -0
- package/template/workers/content-shared/lib/compliance-analyzer.ts +655 -0
- package/template/workers/content-shared/lib/conversion-analyzer.ts +555 -0
- package/template/workers/content-shared/lib/github-integration.ts +582 -0
- package/template/workers/content-shared/lib/output.ts +373 -0
- package/template/workers/content-shared/lib/parser.ts +771 -0
- package/template/workers/content-shared/lib/priority.ts +439 -0
- package/template/workers/content-shared/lib/recommendations.ts +512 -0
- package/template/workers/content-shared/lib/reporter.ts +749 -0
- package/template/workers/content-shared/lib/restructure.ts +664 -0
- package/template/workers/content-shared/lib/scorer.ts +140 -0
- package/template/workers/content-shared/lib/types.ts +227 -0
- package/template/workers/content-shared/lib/variants.ts +595 -0
- package/template/workers/content-shared/package.json +51 -0
- package/template/workers/content-shared/pnpm-lock.yaml +39 -0
- package/template/workers/content-shared/test/sample-page.json +115 -0
- package/template/workers/content-shared/tsconfig.json +20 -0
- package/template/workers/dev-team/README.md +166 -0
- package/template/workers/dev-team/_template.yaml +70 -0
- package/template/workers/dev-team/architect/package.json +27 -0
- package/template/workers/dev-team/architect/skills/api-design.md +89 -0
- package/template/workers/dev-team/architect/skills/refactor-plan.md +96 -0
- package/template/workers/dev-team/architect/skills/system-design.md +100 -0
- package/template/workers/dev-team/architect/src/index.ts +49 -0
- package/template/workers/dev-team/architect/src/mcp-server.ts +122 -0
- package/template/workers/dev-team/architect/src/skills/api-design.ts +316 -0
- package/template/workers/dev-team/architect/src/skills/refactor-plan.ts +264 -0
- package/template/workers/dev-team/architect/src/skills/system-design.ts +212 -0
- package/template/workers/dev-team/architect/tsconfig.json +19 -0
- package/template/workers/dev-team/architect/worker.yaml +128 -0
- package/template/workers/dev-team/backend-dev/package-lock.json +1252 -0
- package/template/workers/dev-team/backend-dev/package.json +27 -0
- package/template/workers/dev-team/backend-dev/skills/implement-endpoint.md +70 -0
- package/template/workers/dev-team/backend-dev/skills/implement-service.md +62 -0
- package/template/workers/dev-team/backend-dev/src/index.ts +51 -0
- package/template/workers/dev-team/backend-dev/src/mcp-server.ts +109 -0
- package/template/workers/dev-team/backend-dev/src/skills/implement-endpoint.ts +122 -0
- package/template/workers/dev-team/backend-dev/src/skills/implement-service.ts +126 -0
- package/template/workers/dev-team/backend-dev/tsconfig.json +19 -0
- package/template/workers/dev-team/backend-dev/worker.yaml +128 -0
- package/template/workers/dev-team/code-reviewer/package-lock.json +1080 -0
- package/template/workers/dev-team/code-reviewer/package.json +24 -0
- package/template/workers/dev-team/code-reviewer/skills/merge-to-production.md +61 -0
- package/template/workers/dev-team/code-reviewer/skills/merge-to-staging.md +54 -0
- package/template/workers/dev-team/code-reviewer/skills/request-changes.md +63 -0
- package/template/workers/dev-team/code-reviewer/skills/review-pr.md +77 -0
- package/template/workers/dev-team/code-reviewer/src/index.ts +56 -0
- package/template/workers/dev-team/code-reviewer/src/mcp-server.ts +101 -0
- package/template/workers/dev-team/code-reviewer/tsconfig.json +19 -0
- package/template/workers/dev-team/code-reviewer/worker.yaml +90 -0
- package/template/workers/dev-team/database-dev/package.json +22 -0
- package/template/workers/dev-team/database-dev/skills/create-schema.md +48 -0
- package/template/workers/dev-team/database-dev/src/index.ts +50 -0
- package/template/workers/dev-team/database-dev/src/mcp-server.ts +76 -0
- package/template/workers/dev-team/database-dev/tsconfig.json +18 -0
- package/template/workers/dev-team/database-dev/worker.yaml +90 -0
- package/template/workers/dev-team/frontend-dev/package.json +22 -0
- package/template/workers/dev-team/frontend-dev/skills/create-component.md +26 -0
- package/template/workers/dev-team/frontend-dev/src/index.ts +50 -0
- package/template/workers/dev-team/frontend-dev/src/mcp-server.ts +77 -0
- package/template/workers/dev-team/frontend-dev/tsconfig.json +18 -0
- package/template/workers/dev-team/frontend-dev/worker.yaml +132 -0
- package/template/workers/dev-team/infra-dev/package.json +24 -0
- package/template/workers/dev-team/infra-dev/skills/add-monitoring.md +73 -0
- package/template/workers/dev-team/infra-dev/skills/configure-deployment.md +80 -0
- package/template/workers/dev-team/infra-dev/skills/create-dockerfile.md +62 -0
- package/template/workers/dev-team/infra-dev/skills/setup-cicd.md +63 -0
- package/template/workers/dev-team/infra-dev/src/index.ts +55 -0
- package/template/workers/dev-team/infra-dev/src/mcp-server.ts +82 -0
- package/template/workers/dev-team/infra-dev/tsconfig.json +19 -0
- package/template/workers/dev-team/infra-dev/worker.yaml +92 -0
- package/template/workers/dev-team/knowledge-curator/package.json +24 -0
- package/template/workers/dev-team/knowledge-curator/skills/curate-troubleshooting.md +63 -0
- package/template/workers/dev-team/knowledge-curator/skills/process-learnings.md +61 -0
- package/template/workers/dev-team/knowledge-curator/skills/sync-documentation.md +76 -0
- package/template/workers/dev-team/knowledge-curator/skills/update-patterns.md +63 -0
- package/template/workers/dev-team/knowledge-curator/src/index.ts +53 -0
- package/template/workers/dev-team/knowledge-curator/src/mcp-server.ts +92 -0
- package/template/workers/dev-team/knowledge-curator/tsconfig.json +19 -0
- package/template/workers/dev-team/knowledge-curator/worker.yaml +80 -0
- package/template/workers/dev-team/motion-designer/package.json +22 -0
- package/template/workers/dev-team/motion-designer/skills/add-animation.md +25 -0
- package/template/workers/dev-team/motion-designer/skills/generate-image.md +36 -0
- package/template/workers/dev-team/motion-designer/src/index.ts +63 -0
- package/template/workers/dev-team/motion-designer/src/mcp-server.ts +79 -0
- package/template/workers/dev-team/motion-designer/tsconfig.json +18 -0
- package/template/workers/dev-team/motion-designer/worker.yaml +84 -0
- package/template/workers/dev-team/product-planner/queue.json +4 -0
- package/template/workers/dev-team/product-planner/worker.yaml +220 -0
- package/template/workers/dev-team/project-manager/package-lock.json +1252 -0
- package/template/workers/dev-team/project-manager/package.json +27 -0
- package/template/workers/dev-team/project-manager/skills/create-prd.md +66 -0
- package/template/workers/dev-team/project-manager/skills/next-issue.md +51 -0
- package/template/workers/dev-team/project-manager/skills/project-status.md +59 -0
- package/template/workers/dev-team/project-manager/skills/update-learnings.md +65 -0
- package/template/workers/dev-team/project-manager/src/index.ts +54 -0
- package/template/workers/dev-team/project-manager/src/mcp-server.ts +207 -0
- package/template/workers/dev-team/project-manager/src/skills/create-prd.ts +86 -0
- package/template/workers/dev-team/project-manager/src/skills/next-issue.ts +137 -0
- package/template/workers/dev-team/project-manager/src/skills/project-status.ts +131 -0
- package/template/workers/dev-team/project-manager/src/skills/update-learnings.ts +94 -0
- package/template/workers/dev-team/project-manager/tsconfig.json +19 -0
- package/template/workers/dev-team/project-manager/worker.yaml +96 -0
- package/template/workers/dev-team/qa-tester/package.json +24 -0
- package/template/workers/dev-team/qa-tester/skills/create-demo-account.md +36 -0
- package/template/workers/dev-team/qa-tester/skills/run-tests.md +36 -0
- package/template/workers/dev-team/qa-tester/skills/write-test.md +27 -0
- package/template/workers/dev-team/qa-tester/src/index.ts +61 -0
- package/template/workers/dev-team/qa-tester/src/mcp-server.ts +88 -0
- package/template/workers/dev-team/qa-tester/tsconfig.json +18 -0
- package/template/workers/dev-team/qa-tester/worker.yaml +116 -0
- package/template/workers/dev-team/task-executor/package-lock.json +1252 -0
- package/template/workers/dev-team/task-executor/package.json +27 -0
- package/template/workers/dev-team/task-executor/skills/analyze-issue.md +101 -0
- package/template/workers/dev-team/task-executor/skills/execute.md +133 -0
- package/template/workers/dev-team/task-executor/skills/report-learnings.md +106 -0
- package/template/workers/dev-team/task-executor/skills/validate-completion.md +121 -0
- package/template/workers/dev-team/task-executor/src/index.ts +54 -0
- package/template/workers/dev-team/task-executor/src/mcp-server.ts +139 -0
- package/template/workers/dev-team/task-executor/src/skills/analyze-issue.ts +219 -0
- package/template/workers/dev-team/task-executor/src/skills/execute.ts +132 -0
- package/template/workers/dev-team/task-executor/src/skills/report-learnings.ts +119 -0
- package/template/workers/dev-team/task-executor/src/skills/validate-completion.ts +142 -0
- package/template/workers/dev-team/task-executor/tsconfig.json +19 -0
- package/template/workers/dev-team/task-executor/worker.yaml +110 -0
- package/template/workers/registry.yaml +171 -0
- package/template/workers/security-scanner/README.md +73 -0
- package/template/workers/security-scanner/skills/pre-deploy-check.md +205 -0
- package/template/workers/security-scanner/worker.yaml +26 -0
- package/template/workspace/checkpoints/.gitkeep +0 -0
- package/template/workspace/content-ideas/inbox.jsonl +0 -0
- package/template/workspace/drafts/.gitkeep +0 -0
- package/template/workspace/learnings/.gitkeep +3 -0
- package/template/workspace/orchestrator/.gitkeep +0 -0
- package/template/workspace/ralph-test/COMPLETE.md +18 -0
- package/template/workspace/ralph-test/hello.txt +2 -0
- package/template/workspace/reports/.gitkeep +0 -0
- package/template/workspace/scratch/.gitkeep +0 -0
- package/template/workspace/threads/.gitkeep +3 -0
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion Analyzer (US-008)
|
|
3
|
+
* Analyzes content for conversion optimization opportunities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
AnalysisInput,
|
|
8
|
+
ConversionAnalysis,
|
|
9
|
+
Finding,
|
|
10
|
+
Recommendation,
|
|
11
|
+
} from './types.js';
|
|
12
|
+
|
|
13
|
+
// ============================================
|
|
14
|
+
// Conversion Elements to Check
|
|
15
|
+
// ============================================
|
|
16
|
+
|
|
17
|
+
export const CONVERSION_ELEMENTS = {
|
|
18
|
+
// Strong CTA verbs and phrases
|
|
19
|
+
ctaStrength: {
|
|
20
|
+
strong: ['get started', 'start free', 'request demo', 'schedule call', 'book demo', 'try free', 'sign up free'],
|
|
21
|
+
moderate: ['learn more', 'see how', 'explore', 'discover', 'find out', 'contact us', 'talk to sales'],
|
|
22
|
+
weak: ['click here', 'submit', 'continue', 'next', 'read more'],
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Value indicators
|
|
26
|
+
valueIndicators: ['save', 'reduce', 'increase', 'improve', 'boost', 'grow', 'eliminate', 'cut', 'accelerate', 'streamline'],
|
|
27
|
+
|
|
28
|
+
// Quantified value (percentages, dollars, time)
|
|
29
|
+
quantifiedValue: [
|
|
30
|
+
/save\s+(?:\$[\d,]+|\d+%)/gi,
|
|
31
|
+
/reduce\s+(?:by\s+)?\d+%/gi,
|
|
32
|
+
/increase\s+(?:by\s+)?\d+%/gi,
|
|
33
|
+
/\d+x\s+(?:faster|more|better)/gi,
|
|
34
|
+
/in\s+(?:just\s+)?\d+\s+(?:minutes?|hours?|days?)/gi,
|
|
35
|
+
],
|
|
36
|
+
|
|
37
|
+
// Urgency words
|
|
38
|
+
urgencyWords: ['now', 'today', 'limited', 'exclusive', 'while', 'before', 'last chance', 'ending soon', 'hurry'],
|
|
39
|
+
|
|
40
|
+
// Social proof elements
|
|
41
|
+
proofElements: ['customers', 'clients', 'companies', 'teams', 'trusted by', 'used by', 'join', 'chosen by', 'preferred by'],
|
|
42
|
+
|
|
43
|
+
// Trust indicators
|
|
44
|
+
trustIndicators: ['secure', 'guaranteed', 'certified', 'compliant', 'protected', 'verified', 'trusted', 'enterprise-grade'],
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// ============================================
|
|
48
|
+
// Scoring Weights
|
|
49
|
+
// ============================================
|
|
50
|
+
|
|
51
|
+
const WEIGHTS = {
|
|
52
|
+
cta: 0.30,
|
|
53
|
+
valueProp: 0.30,
|
|
54
|
+
urgency: 0.15,
|
|
55
|
+
socialProof: 0.25,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ============================================
|
|
59
|
+
// Main Analysis Function
|
|
60
|
+
// ============================================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Analyze content for conversion optimization
|
|
64
|
+
*/
|
|
65
|
+
export function analyzeConversion(content: AnalysisInput): ConversionAnalysis {
|
|
66
|
+
const findings: Finding[] = [];
|
|
67
|
+
const recommendations: Recommendation[] = [];
|
|
68
|
+
|
|
69
|
+
// Analyze CTAs
|
|
70
|
+
const ctaResult = analyzeCTAs(content, findings, recommendations);
|
|
71
|
+
|
|
72
|
+
// Analyze value proposition
|
|
73
|
+
const valueResult = analyzeValueProp(content, findings, recommendations);
|
|
74
|
+
|
|
75
|
+
// Analyze urgency
|
|
76
|
+
const urgencyResult = analyzeUrgency(content, findings, recommendations);
|
|
77
|
+
|
|
78
|
+
// Analyze social proof
|
|
79
|
+
const socialProofResult = analyzeSocialProof(content, findings, recommendations);
|
|
80
|
+
|
|
81
|
+
// Calculate overall score
|
|
82
|
+
const overallScore = Math.round(
|
|
83
|
+
ctaResult.score * WEIGHTS.cta +
|
|
84
|
+
valueResult.score * WEIGHTS.valueProp +
|
|
85
|
+
urgencyResult.score * WEIGHTS.urgency +
|
|
86
|
+
socialProofResult.score * WEIGHTS.socialProof
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
overallScore,
|
|
91
|
+
ctaScore: ctaResult.score,
|
|
92
|
+
valuePropScore: valueResult.score,
|
|
93
|
+
urgencyScore: urgencyResult.score,
|
|
94
|
+
socialProofScore: socialProofResult.score,
|
|
95
|
+
findings,
|
|
96
|
+
recommendations,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ============================================
|
|
101
|
+
// CTA Analysis
|
|
102
|
+
// ============================================
|
|
103
|
+
|
|
104
|
+
interface ScoreResult {
|
|
105
|
+
score: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function analyzeCTAs(
|
|
109
|
+
content: AnalysisInput,
|
|
110
|
+
findings: Finding[],
|
|
111
|
+
recommendations: Recommendation[]
|
|
112
|
+
): ScoreResult {
|
|
113
|
+
let score = 100;
|
|
114
|
+
const { ctaStrength } = CONVERSION_ELEMENTS;
|
|
115
|
+
|
|
116
|
+
// Check if CTAs exist
|
|
117
|
+
if (content.ctas.length === 0) {
|
|
118
|
+
findings.push({
|
|
119
|
+
severity: 'critical',
|
|
120
|
+
category: 'Conversion - CTA',
|
|
121
|
+
message: 'No calls-to-action found on page',
|
|
122
|
+
});
|
|
123
|
+
recommendations.push({
|
|
124
|
+
priority: 'high',
|
|
125
|
+
category: 'CTA',
|
|
126
|
+
current: 'No CTAs present',
|
|
127
|
+
suggested: 'Add primary CTA (e.g., "Get Started Free", "Request Demo")',
|
|
128
|
+
rationale: 'Every page should guide visitors toward conversion',
|
|
129
|
+
});
|
|
130
|
+
return { score: 0 };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Analyze CTA strength
|
|
134
|
+
let strongCTAs = 0;
|
|
135
|
+
let moderateCTAs = 0;
|
|
136
|
+
let weakCTAs = 0;
|
|
137
|
+
|
|
138
|
+
for (const cta of content.ctas) {
|
|
139
|
+
const ctaLower = cta.text.toLowerCase();
|
|
140
|
+
|
|
141
|
+
if (ctaStrength.strong.some(phrase => ctaLower.includes(phrase))) {
|
|
142
|
+
strongCTAs++;
|
|
143
|
+
} else if (ctaStrength.moderate.some(phrase => ctaLower.includes(phrase))) {
|
|
144
|
+
moderateCTAs++;
|
|
145
|
+
} else if (ctaStrength.weak.some(phrase => ctaLower.includes(phrase))) {
|
|
146
|
+
weakCTAs++;
|
|
147
|
+
} else {
|
|
148
|
+
moderateCTAs++; // Assume moderate if not categorized
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Score based on CTA quality mix
|
|
153
|
+
if (strongCTAs === 0) {
|
|
154
|
+
findings.push({
|
|
155
|
+
severity: 'warning',
|
|
156
|
+
category: 'Conversion - CTA',
|
|
157
|
+
message: 'No strong CTAs found',
|
|
158
|
+
evidence: `Found ${moderateCTAs} moderate and ${weakCTAs} weak CTAs`,
|
|
159
|
+
});
|
|
160
|
+
score -= 20;
|
|
161
|
+
recommendations.push({
|
|
162
|
+
priority: 'high',
|
|
163
|
+
category: 'CTA',
|
|
164
|
+
current: content.ctas[0]?.text ?? 'No strong CTA',
|
|
165
|
+
suggested: 'Use action-oriented CTAs: "Get Started Free", "Request Demo", "Start Trial"',
|
|
166
|
+
rationale: 'Strong CTAs drive higher conversion rates',
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
findings.push({
|
|
170
|
+
severity: 'pass',
|
|
171
|
+
category: 'Conversion - CTA',
|
|
172
|
+
message: `Found ${strongCTAs} strong CTA(s)`,
|
|
173
|
+
evidence: content.ctas.slice(0, 3).map(c => c.text).join(', '),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (weakCTAs > 0) {
|
|
178
|
+
findings.push({
|
|
179
|
+
severity: 'info',
|
|
180
|
+
category: 'Conversion - CTA',
|
|
181
|
+
message: `${weakCTAs} weak CTA(s) could be strengthened`,
|
|
182
|
+
});
|
|
183
|
+
score -= weakCTAs * 5;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check CTA variety (primary vs secondary)
|
|
187
|
+
const hasPrimary = content.ctas.some(c => ctaStrength.strong.some(phrase =>
|
|
188
|
+
c.text.toLowerCase().includes(phrase)
|
|
189
|
+
));
|
|
190
|
+
const hasSecondary = content.ctas.some(c => ctaStrength.moderate.some(phrase =>
|
|
191
|
+
c.text.toLowerCase().includes(phrase)
|
|
192
|
+
));
|
|
193
|
+
|
|
194
|
+
if (hasPrimary && hasSecondary) {
|
|
195
|
+
findings.push({
|
|
196
|
+
severity: 'pass',
|
|
197
|
+
category: 'Conversion - CTA',
|
|
198
|
+
message: 'Good CTA hierarchy with primary and secondary options',
|
|
199
|
+
});
|
|
200
|
+
} else if (!hasSecondary && content.ctas.length < 2) {
|
|
201
|
+
findings.push({
|
|
202
|
+
severity: 'info',
|
|
203
|
+
category: 'Conversion - CTA',
|
|
204
|
+
message: 'Consider adding secondary CTA for visitors not ready to commit',
|
|
205
|
+
});
|
|
206
|
+
score -= 5;
|
|
207
|
+
recommendations.push({
|
|
208
|
+
priority: 'low',
|
|
209
|
+
category: 'CTA',
|
|
210
|
+
current: 'Only one type of CTA',
|
|
211
|
+
suggested: 'Add secondary option like "Learn More" or "See How It Works"',
|
|
212
|
+
rationale: 'Multiple CTAs accommodate different buyer stages',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Check for above-the-fold CTA
|
|
217
|
+
const heroSection = content.sections.find(s => s.type === 'hero');
|
|
218
|
+
if (heroSection) {
|
|
219
|
+
const heroCTA = content.ctas.find(c => c.link && (c.link.includes('#') || c.link.startsWith('/')));
|
|
220
|
+
if (!heroCTA) {
|
|
221
|
+
findings.push({
|
|
222
|
+
severity: 'info',
|
|
223
|
+
category: 'Conversion - CTA',
|
|
224
|
+
message: 'Ensure primary CTA is visible above the fold',
|
|
225
|
+
});
|
|
226
|
+
score -= 5;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { score: Math.max(0, Math.min(100, score)) };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ============================================
|
|
234
|
+
// Value Proposition Analysis
|
|
235
|
+
// ============================================
|
|
236
|
+
|
|
237
|
+
function analyzeValueProp(
|
|
238
|
+
content: AnalysisInput,
|
|
239
|
+
findings: Finding[],
|
|
240
|
+
recommendations: Recommendation[]
|
|
241
|
+
): ScoreResult {
|
|
242
|
+
let score = 100;
|
|
243
|
+
const allText = getAllText(content).toLowerCase();
|
|
244
|
+
|
|
245
|
+
// Check for value indicators
|
|
246
|
+
const valueTermsFound = CONVERSION_ELEMENTS.valueIndicators.filter(term =>
|
|
247
|
+
allText.includes(term)
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
if (valueTermsFound.length === 0) {
|
|
251
|
+
findings.push({
|
|
252
|
+
severity: 'warning',
|
|
253
|
+
category: 'Conversion - Value Proposition',
|
|
254
|
+
message: 'No clear value indicators found',
|
|
255
|
+
});
|
|
256
|
+
score -= 25;
|
|
257
|
+
recommendations.push({
|
|
258
|
+
priority: 'high',
|
|
259
|
+
category: 'Value Proposition',
|
|
260
|
+
current: 'Value proposition unclear',
|
|
261
|
+
suggested: 'Explicitly state benefits: "Save 50% on...", "Reduce X by..."',
|
|
262
|
+
rationale: 'Clear value propositions are essential for conversion',
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
findings.push({
|
|
266
|
+
severity: 'pass',
|
|
267
|
+
category: 'Conversion - Value Proposition',
|
|
268
|
+
message: `${valueTermsFound.length} value indicator(s) found`,
|
|
269
|
+
evidence: valueTermsFound.join(', '),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check for quantified value (numbers, percentages)
|
|
274
|
+
let quantifiedCount = 0;
|
|
275
|
+
for (const pattern of CONVERSION_ELEMENTS.quantifiedValue) {
|
|
276
|
+
const matches = allText.match(pattern);
|
|
277
|
+
if (matches) quantifiedCount += matches.length;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (quantifiedCount === 0) {
|
|
281
|
+
findings.push({
|
|
282
|
+
severity: 'warning',
|
|
283
|
+
category: 'Conversion - Value Proposition',
|
|
284
|
+
message: 'No quantified benefits found',
|
|
285
|
+
});
|
|
286
|
+
score -= 20;
|
|
287
|
+
recommendations.push({
|
|
288
|
+
priority: 'high',
|
|
289
|
+
category: 'Value Proposition',
|
|
290
|
+
current: 'Benefits are not quantified',
|
|
291
|
+
suggested: 'Add specific metrics: "Save 40%", "10x faster", "In just 5 minutes"',
|
|
292
|
+
rationale: 'Specific numbers are more persuasive than vague claims',
|
|
293
|
+
});
|
|
294
|
+
} else {
|
|
295
|
+
findings.push({
|
|
296
|
+
severity: 'pass',
|
|
297
|
+
category: 'Conversion - Value Proposition',
|
|
298
|
+
message: `Found ${quantifiedCount} quantified benefit(s)`,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Check stats coverage
|
|
303
|
+
if (content.stats.length > 0) {
|
|
304
|
+
findings.push({
|
|
305
|
+
severity: 'pass',
|
|
306
|
+
category: 'Conversion - Value Proposition',
|
|
307
|
+
message: `${content.stats.length} statistics/metrics displayed`,
|
|
308
|
+
evidence: content.stats.slice(0, 3).map(s => s.value).join(', '),
|
|
309
|
+
});
|
|
310
|
+
} else {
|
|
311
|
+
findings.push({
|
|
312
|
+
severity: 'info',
|
|
313
|
+
category: 'Conversion - Value Proposition',
|
|
314
|
+
message: 'Consider adding key statistics or metrics',
|
|
315
|
+
});
|
|
316
|
+
score -= 10;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Check hero section for value prop
|
|
320
|
+
const heroSection = content.sections.find(s => s.type === 'hero');
|
|
321
|
+
if (heroSection) {
|
|
322
|
+
const heroText = heroSection.content.join(' ').toLowerCase();
|
|
323
|
+
const hasValueInHero = CONVERSION_ELEMENTS.valueIndicators.some(term =>
|
|
324
|
+
heroText.includes(term)
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
if (!hasValueInHero) {
|
|
328
|
+
findings.push({
|
|
329
|
+
severity: 'warning',
|
|
330
|
+
category: 'Conversion - Value Proposition',
|
|
331
|
+
message: 'Hero section lacks clear value proposition',
|
|
332
|
+
location: 'Hero section',
|
|
333
|
+
});
|
|
334
|
+
score -= 15;
|
|
335
|
+
recommendations.push({
|
|
336
|
+
priority: 'high',
|
|
337
|
+
category: 'Value Proposition',
|
|
338
|
+
current: 'Hero section missing value prop',
|
|
339
|
+
suggested: 'Lead with primary benefit in hero headline or subheadline',
|
|
340
|
+
rationale: 'Visitors should understand value within seconds',
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return { score: Math.max(0, Math.min(100, score)) };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ============================================
|
|
349
|
+
// Urgency Analysis
|
|
350
|
+
// ============================================
|
|
351
|
+
|
|
352
|
+
function analyzeUrgency(
|
|
353
|
+
content: AnalysisInput,
|
|
354
|
+
findings: Finding[],
|
|
355
|
+
recommendations: Recommendation[]
|
|
356
|
+
): ScoreResult {
|
|
357
|
+
let score = 70; // Start at 70 since urgency isn't always appropriate
|
|
358
|
+
const allText = getAllText(content).toLowerCase();
|
|
359
|
+
|
|
360
|
+
// Check for urgency words
|
|
361
|
+
const urgencyFound = CONVERSION_ELEMENTS.urgencyWords.filter(term =>
|
|
362
|
+
allText.includes(term)
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
if (urgencyFound.length > 0) {
|
|
366
|
+
findings.push({
|
|
367
|
+
severity: 'pass',
|
|
368
|
+
category: 'Conversion - Urgency',
|
|
369
|
+
message: `Urgency elements present: ${urgencyFound.length} indicator(s)`,
|
|
370
|
+
evidence: urgencyFound.join(', '),
|
|
371
|
+
});
|
|
372
|
+
score += 20;
|
|
373
|
+
|
|
374
|
+
// Check for authentic vs artificial urgency
|
|
375
|
+
const artificialUrgency = ['limited time', 'act now', 'hurry', 'last chance'];
|
|
376
|
+
const hasArtificial = artificialUrgency.some(phrase => allText.includes(phrase));
|
|
377
|
+
|
|
378
|
+
if (hasArtificial && !allText.includes('offer') && !allText.includes('promo')) {
|
|
379
|
+
findings.push({
|
|
380
|
+
severity: 'info',
|
|
381
|
+
category: 'Conversion - Urgency',
|
|
382
|
+
message: 'Urgency language may feel artificial without context',
|
|
383
|
+
});
|
|
384
|
+
score -= 10;
|
|
385
|
+
recommendations.push({
|
|
386
|
+
priority: 'low',
|
|
387
|
+
category: 'Urgency',
|
|
388
|
+
current: 'Generic urgency language',
|
|
389
|
+
suggested: 'Tie urgency to specific context (limited seats, trial ending, etc.)',
|
|
390
|
+
rationale: 'Authentic urgency is more effective than manufactured scarcity',
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
findings.push({
|
|
395
|
+
severity: 'info',
|
|
396
|
+
category: 'Conversion - Urgency',
|
|
397
|
+
message: 'No urgency elements found',
|
|
398
|
+
});
|
|
399
|
+
recommendations.push({
|
|
400
|
+
priority: 'low',
|
|
401
|
+
category: 'Urgency',
|
|
402
|
+
current: 'No urgency drivers',
|
|
403
|
+
suggested: 'Consider adding contextual urgency (limited beta spots, early pricing, etc.)',
|
|
404
|
+
rationale: 'Appropriate urgency can accelerate decision-making',
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Check CTAs for urgency
|
|
409
|
+
const ctasWithUrgency = content.ctas.filter(cta => {
|
|
410
|
+
const ctaLower = cta.text.toLowerCase();
|
|
411
|
+
return CONVERSION_ELEMENTS.urgencyWords.some(word => ctaLower.includes(word));
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
if (ctasWithUrgency.length > 0) {
|
|
415
|
+
findings.push({
|
|
416
|
+
severity: 'pass',
|
|
417
|
+
category: 'Conversion - Urgency',
|
|
418
|
+
message: 'CTA includes urgency element',
|
|
419
|
+
evidence: ctasWithUrgency[0].text,
|
|
420
|
+
});
|
|
421
|
+
score += 10;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return { score: Math.max(0, Math.min(100, score)) };
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// ============================================
|
|
428
|
+
// Social Proof Analysis
|
|
429
|
+
// ============================================
|
|
430
|
+
|
|
431
|
+
function analyzeSocialProof(
|
|
432
|
+
content: AnalysisInput,
|
|
433
|
+
findings: Finding[],
|
|
434
|
+
recommendations: Recommendation[]
|
|
435
|
+
): ScoreResult {
|
|
436
|
+
let score = 100;
|
|
437
|
+
const allText = getAllText(content).toLowerCase();
|
|
438
|
+
|
|
439
|
+
// Check for social proof elements
|
|
440
|
+
const proofFound = CONVERSION_ELEMENTS.proofElements.filter(term =>
|
|
441
|
+
allText.includes(term)
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
if (proofFound.length === 0) {
|
|
445
|
+
findings.push({
|
|
446
|
+
severity: 'warning',
|
|
447
|
+
category: 'Conversion - Social Proof',
|
|
448
|
+
message: 'No social proof elements found',
|
|
449
|
+
});
|
|
450
|
+
score -= 30;
|
|
451
|
+
recommendations.push({
|
|
452
|
+
priority: 'high',
|
|
453
|
+
category: 'Social Proof',
|
|
454
|
+
current: 'Missing social proof',
|
|
455
|
+
suggested: 'Add customer count, logos, testimonials, or case study references',
|
|
456
|
+
rationale: 'Social proof significantly increases conversion rates',
|
|
457
|
+
});
|
|
458
|
+
} else {
|
|
459
|
+
findings.push({
|
|
460
|
+
severity: 'pass',
|
|
461
|
+
category: 'Conversion - Social Proof',
|
|
462
|
+
message: `Social proof present: ${proofFound.length} indicator(s)`,
|
|
463
|
+
evidence: proofFound.join(', '),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Check for testimonials section
|
|
468
|
+
const hasTestimonials = content.sections.some(s => s.type === 'testimonials');
|
|
469
|
+
if (hasTestimonials) {
|
|
470
|
+
findings.push({
|
|
471
|
+
severity: 'pass',
|
|
472
|
+
category: 'Conversion - Social Proof',
|
|
473
|
+
message: 'Testimonials section present',
|
|
474
|
+
});
|
|
475
|
+
} else {
|
|
476
|
+
findings.push({
|
|
477
|
+
severity: 'info',
|
|
478
|
+
category: 'Conversion - Social Proof',
|
|
479
|
+
message: 'No dedicated testimonials section found',
|
|
480
|
+
});
|
|
481
|
+
score -= 10;
|
|
482
|
+
recommendations.push({
|
|
483
|
+
priority: 'medium',
|
|
484
|
+
category: 'Social Proof',
|
|
485
|
+
current: 'No testimonials section',
|
|
486
|
+
suggested: 'Add customer testimonials with names, titles, and companies',
|
|
487
|
+
rationale: 'Named testimonials build credibility and trust',
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Check for trust indicators
|
|
492
|
+
const trustFound = CONVERSION_ELEMENTS.trustIndicators.filter(term =>
|
|
493
|
+
allText.includes(term)
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
if (trustFound.length > 0) {
|
|
497
|
+
findings.push({
|
|
498
|
+
severity: 'pass',
|
|
499
|
+
category: 'Conversion - Social Proof',
|
|
500
|
+
message: `Trust indicators present: ${trustFound.length}`,
|
|
501
|
+
evidence: trustFound.join(', '),
|
|
502
|
+
});
|
|
503
|
+
} else {
|
|
504
|
+
findings.push({
|
|
505
|
+
severity: 'info',
|
|
506
|
+
category: 'Conversion - Social Proof',
|
|
507
|
+
message: 'No explicit trust indicators found',
|
|
508
|
+
});
|
|
509
|
+
score -= 10;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Check for specific numbers (more credible)
|
|
513
|
+
const specificNumbers = allText.match(/(?:over\s+)?\d{1,3}(?:,\d{3})*\+?\s+(?:customers?|clients?|companies?|teams?)/gi);
|
|
514
|
+
if (specificNumbers && specificNumbers.length > 0) {
|
|
515
|
+
findings.push({
|
|
516
|
+
severity: 'pass',
|
|
517
|
+
category: 'Conversion - Social Proof',
|
|
518
|
+
message: 'Specific customer count mentioned',
|
|
519
|
+
evidence: specificNumbers[0],
|
|
520
|
+
});
|
|
521
|
+
} else {
|
|
522
|
+
findings.push({
|
|
523
|
+
severity: 'info',
|
|
524
|
+
category: 'Conversion - Social Proof',
|
|
525
|
+
message: 'Consider adding specific customer count',
|
|
526
|
+
});
|
|
527
|
+
score -= 5;
|
|
528
|
+
recommendations.push({
|
|
529
|
+
priority: 'low',
|
|
530
|
+
category: 'Social Proof',
|
|
531
|
+
current: 'Generic social proof',
|
|
532
|
+
suggested: 'Add specific number: "Trusted by 10,000+ companies"',
|
|
533
|
+
rationale: 'Specific numbers are more credible than vague claims',
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return { score: Math.max(0, Math.min(100, score)) };
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ============================================
|
|
541
|
+
// Helper Functions
|
|
542
|
+
// ============================================
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Get all text from content
|
|
546
|
+
*/
|
|
547
|
+
function getAllText(content: AnalysisInput): string {
|
|
548
|
+
return [
|
|
549
|
+
content.title,
|
|
550
|
+
...content.headings,
|
|
551
|
+
...content.paragraphs,
|
|
552
|
+
...content.ctas.map(c => c.text),
|
|
553
|
+
...content.claims,
|
|
554
|
+
].join(' ');
|
|
555
|
+
}
|