Content is the lifeblood of dynamic websites. From blog posts and product descriptions to meta tags and social media snippets, the demand for quality content has never been higher. According to Content Marketing Institute, 73% of B2B marketers and 70% of B2C marketers use content marketing as part of their overall strategy. The challenge? Creating quality content at scale while maintaining brand voice, SEO optimization, and uniqueness across thousands of pages.
AI-powered content generation has matured from experimental technology to production-ready systems. Companies like Jasper, Copy.ai, and enterprises using OpenAI's API have demonstrated that AI can generate content that matches or exceeds human-written quality in specific use cases. In this comprehensive guide, we'll explore how to build automated content systems that scale from 100 to 10,000+ pages while maintaining quality and avoiding duplicate content penalties.
Content Generation Architecture
Building a robust AI content generation system requires a well-designed architecture that handles content planning, generation, quality assurance, and publishing. Here's a complete content generation pipeline:
// content-generation-pipeline.ts
import OpenAI from 'openai';
import { z } from 'zod';
// Content request schema
const ContentRequestSchema = z.object({
type: z.enum(['blog', 'product', 'landing', 'meta', 'social']),
topic: z.string().min(10),
keywords: z.array(z.string()).min(1).max(10),
targetLength: z.number().min(100).max(10000),
tone: z.enum(['professional', 'casual', 'authoritative', 'friendly', 'technical']),
targetAudience: z.string(),
brandVoice: z.object({
personality: z.array(z.string()),
avoidWords: z.array(z.string()),
preferredPhrases: z.array(z.string())
}).optional()
});
type ContentRequest = z.infer;
interface GeneratedContent {
id: string;
title: string;
content: string;
metaDescription: string;
keywords: string[];
headings: string[];
wordCount: number;
readabilityScore: number;
seoScore: number;
uniquenessScore: number;
brandVoiceScore: number;
generatedAt: Date;
status: 'draft' | 'review' | 'approved' | 'published';
}
interface ContentQualityMetrics {
readability: {
fleschKincaid: number;
gradeLevel: number;
sentenceLength: number;
};
seo: {
keywordDensity: Record;
titleTagScore: number;
metaDescriptionScore: number;
headingStructure: number;
internalLinks: number;
externalLinks: number;
};
uniqueness: {
plagiarismScore: number;
semanticUniqueness: number;
structuralVariation: number;
};
brandVoice: {
toneAlignment: number;
vocabularyMatch: number;
styleConsistency: number;
};
}
class AIContentGenerator {
private openai: OpenAI;
private brandStyleGuide: BrandStyleGuide;
private contentCache: Map = new Map();
constructor(apiKey: string, brandStyleGuide: BrandStyleGuide) {
this.openai = new OpenAI({ apiKey });
this.brandStyleGuide = brandStyleGuide;
}
async generateContent(request: ContentRequest): Promise {
// Validate request
const validatedRequest = ContentRequestSchema.parse(request);
// Build the generation prompt
const systemPrompt = this.buildSystemPrompt(validatedRequest);
const userPrompt = this.buildUserPrompt(validatedRequest);
// Generate content with structured output
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
],
temperature: 0.7,
max_tokens: Math.min(validatedRequest.targetLength * 2, 4000),
response_format: { type: 'json_object' }
});
const rawContent = JSON.parse(response.choices[0].message.content || '{}');
// Post-process and validate content
const processedContent = await this.postProcessContent(rawContent, validatedRequest);
// Calculate quality metrics
const qualityMetrics = await this.calculateQualityMetrics(processedContent, validatedRequest);
// Generate unique ID
const contentId = this.generateContentId(validatedRequest);
const generatedContent: GeneratedContent = {
id: contentId,
title: processedContent.title,
content: processedContent.body,
metaDescription: processedContent.metaDescription,
keywords: validatedRequest.keywords,
headings: this.extractHeadings(processedContent.body),
wordCount: this.countWords(processedContent.body),
readabilityScore: qualityMetrics.readability.fleschKincaid,
seoScore: this.calculateOverallSEOScore(qualityMetrics.seo),
uniquenessScore: qualityMetrics.uniqueness.semanticUniqueness,
brandVoiceScore: qualityMetrics.brandVoice.toneAlignment,
generatedAt: new Date(),
status: this.determineStatus(qualityMetrics)
};
// Cache the content
this.contentCache.set(contentId, generatedContent);
return generatedContent;
}
private buildSystemPrompt(request: ContentRequest): string {
const brandInstructions = request.brandVoice
? `
Brand Voice Guidelines:
- Personality traits: ${request.brandVoice.personality.join(', ')}
- Avoid these words: ${request.brandVoice.avoidWords.join(', ')}
- Use these preferred phrases when appropriate: ${request.brandVoice.preferredPhrases.join(', ')}
`
: '';
return `You are an expert content writer specializing in ${request.type} content.
Your writing should be ${request.tone} in tone and optimized for the target audience: ${request.targetAudience}.
${brandInstructions}
SEO Requirements:
- Include target keywords naturally (2-3% density)
- Use proper heading hierarchy (H2, H3)
- Write compelling meta descriptions (150-160 characters)
- Include internal linking opportunities marked as [INTERNAL_LINK: topic]
- Suggest external authoritative sources marked as [EXTERNAL_LINK: description]
Quality Standards:
- Write at a ${this.getReadabilityLevel(request.targetAudience)} reading level
- Use short paragraphs (2-4 sentences)
- Include actionable insights
- Avoid fluff and filler content
- Be specific with data and examples
Output Format:
Return a JSON object with: title, body, metaDescription, suggestedInternalLinks, suggestedExternalLinks`;
}
private buildUserPrompt(request: ContentRequest): string {
return `Create ${request.type} content about: "${request.topic}"
Target Keywords: ${request.keywords.join(', ')}
Target Length: ${request.targetLength} words
Tone: ${request.tone}
Requirements:
1. Write engaging, valuable content that provides real insights
2. Include practical examples and code snippets if relevant
3. Structure with clear headings and subheadings
4. End with a clear call-to-action or next steps
5. Ensure the content is original and not derivative
Generate the content now.`;
}
private async postProcessContent(
rawContent: any,
request: ContentRequest
): Promise<{ title: string; body: string; metaDescription: string }> {
let body = rawContent.body || rawContent.content || '';
// Apply brand voice transformations
if (request.brandVoice) {
body = this.applyBrandVoice(body, request.brandVoice);
}
// Ensure proper heading structure
body = this.normalizeHeadings(body);
// Add semantic HTML markers
body = this.addSemanticMarkers(body);
// Validate and fix meta description length
let metaDescription = rawContent.metaDescription || '';
if (metaDescription.length > 160) {
metaDescription = metaDescription.substring(0, 157) + '...';
}
return {
title: rawContent.title || this.generateTitle(request.topic),
body,
metaDescription
};
}
private applyBrandVoice(content: string, brandVoice: ContentRequest['brandVoice']): string {
if (!brandVoice) return content;
let processedContent = content;
// Replace avoided words with alternatives
brandVoice.avoidWords.forEach(word => {
const regex = new RegExp(`\\b${word}\\b`, 'gi');
const alternative = this.findAlternative(word, brandVoice.preferredPhrases);
processedContent = processedContent.replace(regex, alternative);
});
return processedContent;
}
private async calculateQualityMetrics(
content: { title: string; body: string; metaDescription: string },
request: ContentRequest
): Promise {
const readability = this.calculateReadability(content.body);
const seo = this.calculateSEOMetrics(content, request.keywords);
const uniqueness = await this.calculateUniqueness(content.body);
const brandVoice = this.calculateBrandVoiceAlignment(content.body, request);
return { readability, seo, uniqueness, brandVoice };
}
private calculateReadability(text: string): ContentQualityMetrics['readability'] {
const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
const words = text.split(/\s+/).filter(w => w.length > 0);
const syllables = words.reduce((count, word) => count + this.countSyllables(word), 0);
const avgSentenceLength = words.length / sentences.length;
const avgSyllablesPerWord = syllables / words.length;
// Flesch-Kincaid Grade Level
const gradeLevel = 0.39 * avgSentenceLength + 11.8 * avgSyllablesPerWord - 15.59;
// Flesch Reading Ease
const fleschKincaid = 206.835 - 1.015 * avgSentenceLength - 84.6 * avgSyllablesPerWord;
return {
fleschKincaid: Math.max(0, Math.min(100, fleschKincaid)),
gradeLevel: Math.max(0, gradeLevel),
sentenceLength: avgSentenceLength
};
}
private calculateSEOMetrics(
content: { title: string; body: string; metaDescription: string },
keywords: string[]
): ContentQualityMetrics['seo'] {
const wordCount = this.countWords(content.body);
const keywordDensity: Record = {};
keywords.forEach(keyword => {
const regex = new RegExp(keyword, 'gi');
const matches = content.body.match(regex) || [];
keywordDensity[keyword] = (matches.length / wordCount) * 100;
});
// Title tag scoring
const titleScore = this.scoreTitleTag(content.title, keywords);
// Meta description scoring
const metaScore = this.scoreMetaDescription(content.metaDescription, keywords);
// Heading structure analysis
const headingScore = this.scoreHeadingStructure(content.body);
// Count links
const internalLinks = (content.body.match(/\[INTERNAL_LINK:/g) || []).length;
const externalLinks = (content.body.match(/\[EXTERNAL_LINK:/g) || []).length;
return {
keywordDensity,
titleTagScore: titleScore,
metaDescriptionScore: metaScore,
headingStructure: headingScore,
internalLinks,
externalLinks
};
}
private async calculateUniqueness(text: string): Promise {
// Simulate plagiarism check - in production, use Copyscape API or similar
const plagiarismScore = 95 + Math.random() * 5; // 95-100%
// Calculate semantic uniqueness using sentence structure variation
const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
const sentenceStarts = sentences.map(s => s.trim().split(' ').slice(0, 3).join(' '));
const uniqueStarts = new Set(sentenceStarts);
const structuralVariation = (uniqueStarts.size / sentences.length) * 100;
return {
plagiarismScore,
semanticUniqueness: plagiarismScore,
structuralVariation
};
}
private calculateBrandVoiceAlignment(
text: string,
request: ContentRequest
): ContentQualityMetrics['brandVoice'] {
// Simple heuristic-based scoring
// In production, use embeddings comparison with brand samples
const toneScore = this.scoreToneAlignment(text, request.tone);
const vocabularyScore = request.brandVoice
? this.scoreVocabularyMatch(text, request.brandVoice)
: 80;
const styleScore = this.scoreStyleConsistency(text);
return {
toneAlignment: toneScore,
vocabularyMatch: vocabularyScore,
styleConsistency: styleScore
};
}
private determineStatus(metrics: ContentQualityMetrics): GeneratedContent['status'] {
const avgScore = (
metrics.readability.fleschKincaid +
this.calculateOverallSEOScore(metrics.seo) +
metrics.uniqueness.semanticUniqueness +
metrics.brandVoice.toneAlignment
) / 4;
if (avgScore >= 85) return 'approved';
if (avgScore >= 70) return 'review';
return 'draft';
}
// Helper methods
private countWords(text: string): number {
return text.split(/\s+/).filter(w => w.length > 0).length;
}
private countSyllables(word: string): number {
word = word.toLowerCase();
if (word.length <= 3) return 1;
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
word = word.replace(/^y/, '');
const matches = word.match(/[aeiouy]{1,2}/g);
return matches ? matches.length : 1;
}
private extractHeadings(content: string): string[] {
const headingRegex = /^#{1,6}\s+(.+)$/gm;
const headings: string[] = [];
let match;
while ((match = headingRegex.exec(content)) !== null) {
headings.push(match[1]);
}
return headings;
}
private generateContentId(request: ContentRequest): string {
const timestamp = Date.now();
const hash = this.simpleHash(request.topic + timestamp);
return `${request.type}-${hash}`;
}
private simpleHash(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return Math.abs(hash).toString(36);
}
}
Automated Blog Generation Pipeline
Blog content requires special handling for structure, SEO, and engagement. Here's a complete blog generation system that creates publish-ready articles:
// blog-generation-system.ts
import { AIContentGenerator, ContentRequest } from './content-generation-pipeline';
interface BlogOutline {
title: string;
introduction: string;
sections: BlogSection[];
conclusion: string;
cta: string;
}
interface BlogSection {
heading: string;
subheadings: string[];
keyPoints: string[];
examples: string[];
codeSnippets?: CodeSnippet[];
}
interface CodeSnippet {
language: string;
description: string;
code: string;
}
interface BlogGenerationConfig {
minWordCount: number;
maxWordCount: number;
includeCodeExamples: boolean;
includeFAQ: boolean;
includeTableOfContents: boolean;
targetSEOScore: number;
requiredSections: string[];
}
class BlogGenerator {
private contentGenerator: AIContentGenerator;
private config: BlogGenerationConfig;
constructor(contentGenerator: AIContentGenerator, config: BlogGenerationConfig) {
this.contentGenerator = contentGenerator;
this.config = config;
}
async generateBlog(
topic: string,
keywords: string[],
targetAudience: string
): Promise {
// Step 1: Research and outline
const outline = await this.createOutline(topic, keywords);
// Step 2: Generate each section
const sections = await this.generateSections(outline, keywords, targetAudience);
// Step 3: Generate supporting elements
const [introduction, conclusion, faq] = await Promise.all([
this.generateIntroduction(topic, outline, keywords),
this.generateConclusion(topic, outline, keywords),
this.config.includeFAQ ? this.generateFAQ(topic, keywords) : null
]);
// Step 4: Assemble the complete blog post
const fullContent = this.assembleBlogPost({
introduction,
sections,
conclusion,
faq
});
// Step 5: Generate meta elements
const metaElements = await this.generateMetaElements(topic, fullContent, keywords);
// Step 6: Quality check and optimization
const optimizedContent = await this.optimizeForSEO(fullContent, keywords);
return {
title: metaElements.title,
slug: this.generateSlug(metaElements.title),
content: optimizedContent,
excerpt: metaElements.excerpt,
metaDescription: metaElements.metaDescription,
metaKeywords: keywords,
tableOfContents: this.generateTableOfContents(sections),
faq: faq,
estimatedReadTime: this.calculateReadTime(optimizedContent),
wordCount: this.countWords(optimizedContent),
publishReady: true
};
}
private async createOutline(topic: string, keywords: string[]): Promise {
const response = await this.contentGenerator.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are an expert content strategist. Create detailed blog outlines that:
1. Cover the topic comprehensively
2. Include practical, actionable sections
3. Structure for optimal reader engagement
4. Support SEO for target keywords
5. Include opportunities for code examples and real-world applications`
},
{
role: 'user',
content: `Create a detailed outline for a technical blog post about: "${topic}"
Target keywords: ${keywords.join(', ')}
Requirements:
- 5-7 main sections
- 2-3 subheadings per section
- Key points and examples for each section
- Progressive complexity (beginner to advanced)
Return as JSON with structure:
{
"title": "SEO-optimized title",
"introduction": "Overview of what will be covered",
"sections": [
{
"heading": "Section title",
"subheadings": ["Subheading 1", "Subheading 2"],
"keyPoints": ["Point 1", "Point 2"],
"examples": ["Example description"]
}
],
"conclusion": "Summary and next steps",
"cta": "Call to action"
}`
}
],
temperature: 0.7,
response_format: { type: 'json_object' }
});
return JSON.parse(response.choices[0].message.content || '{}');
}
private async generateSections(
outline: BlogOutline,
keywords: string[],
targetAudience: string
): Promise {
const sectionPromises = outline.sections.map(async (section, index) => {
const sectionContent = await this.generateSection(
section,
keywords,
targetAudience,
index === 0 // First section gets more context
);
return {
heading: section.heading,
content: sectionContent,
order: index
};
});
return Promise.all(sectionPromises);
}
private async generateSection(
section: BlogSection,
keywords: string[],
targetAudience: string,
isFirstSection: boolean
): Promise {
const codeExampleInstructions = this.config.includeCodeExamples
? `Include practical code examples in TypeScript/JavaScript when relevant.
Format code with proper syntax highlighting markers.
Explain code step by step.`
: '';
const response = await this.contentGenerator.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are a technical writer creating engaging, practical content.
${codeExampleInstructions}
Writing guidelines:
- Use short paragraphs (2-4 sentences max)
- Include bullet points for lists
- Add transitions between ideas
- Be specific with examples and data
- Write for ${targetAudience}`
},
{
role: 'user',
content: `Write the "${section.heading}" section of a blog post.
Subheadings to cover:
${section.subheadings.map(sh => `- ${sh}`).join('\n')}
Key points:
${section.keyPoints.map(kp => `- ${kp}`).join('\n')}
Examples to include:
${section.examples.map(ex => `- ${ex}`).join('\n')}
Target keywords (use naturally): ${keywords.join(', ')}
${isFirstSection ? 'This is the first section, so ensure smooth transition from the introduction.' : ''}
Write comprehensive content (400-600 words) with proper markdown formatting.`
}
],
temperature: 0.7,
max_tokens: 2000
});
return response.choices[0].message.content || '';
}
private async generateFAQ(topic: string, keywords: string[]): Promise {
const response = await this.contentGenerator.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Generate FAQ content that:
1. Answers common questions about the topic
2. Uses natural language patterns for voice search
3. Includes keywords where appropriate
4. Provides actionable, specific answers`
},
{
role: 'user',
content: `Create 5 FAQ items for a blog about: "${topic}"
Keywords: ${keywords.join(', ')}
Return as JSON array:
[
{
"question": "Natural question with keyword",
"answer": "Comprehensive answer (50-100 words)"
}
]`
}
],
temperature: 0.7,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{"faqs": []}');
return result.faqs || result;
}
private async optimizeForSEO(content: string, keywords: string[]): Promise {
// Check keyword density
const wordCount = this.countWords(content);
const keywordAnalysis = this.analyzeKeywordDensity(content, keywords);
// Identify sections needing optimization
const underOptimized = keywords.filter(kw => keywordAnalysis[kw] < 1);
const overOptimized = keywords.filter(kw => keywordAnalysis[kw] > 3);
if (underOptimized.length === 0 && overOptimized.length === 0) {
return content;
}
// Request optimization
const response = await this.contentGenerator.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are an SEO optimization expert. Adjust content to:
1. Naturally incorporate underused keywords
2. Reduce overuse of certain keywords
3. Maintain natural reading flow
4. Keep the meaning and structure intact`
},
{
role: 'user',
content: `Optimize this content for SEO:
Current keyword densities:
${Object.entries(keywordAnalysis).map(([kw, density]) =>
`- "${kw}": ${density.toFixed(2)}% (target: 1.5-2.5%)`
).join('\n')}
Keywords to add more naturally: ${underOptimized.join(', ')}
Keywords to reduce: ${overOptimized.join(', ')}
Content:
${content}
Return the optimized content only.`
}
],
temperature: 0.3
});
return response.choices[0].message.content || content;
}
private analyzeKeywordDensity(content: string, keywords: string[]): Record {
const wordCount = this.countWords(content);
const density: Record = {};
keywords.forEach(keyword => {
const regex = new RegExp(keyword, 'gi');
const matches = content.match(regex) || [];
density[keyword] = (matches.length / wordCount) * 100;
});
return density;
}
private generateSlug(title: string): string {
return title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
}
private calculateReadTime(content: string): number {
const wordCount = this.countWords(content);
const wordsPerMinute = 200;
return Math.ceil(wordCount / wordsPerMinute);
}
private countWords(text: string): number {
return text.split(/\s+/).filter(w => w.length > 0).length;
}
}
AI-Generated Product Descriptions
E-commerce sites with hundreds or thousands of products need scalable description generation. According to Shopify research, compelling product descriptions can increase conversion rates by 30% or more. Here's a production-ready product description generator:
// product-description-generator.ts
interface ProductData {
name: string;
sku: string;
category: string;
subcategory?: string;
specifications: Record;
features: string[];
materials?: string[];
dimensions?: {
width: number;
height: number;
depth: number;
unit: 'cm' | 'in';
};
weight?: { value: number; unit: 'kg' | 'lb' };
price: number;
compareAtPrice?: number;
images: string[];
variants?: ProductVariant[];
}
interface ProductVariant {
name: string;
sku: string;
options: Record;
price: number;
available: boolean;
}
interface ProductDescriptionOutput {
shortDescription: string;
longDescription: string;
bulletPoints: string[];
seoTitle: string;
metaDescription: string;
altTexts: string[];
socialSnippets: {
facebook: string;
instagram: string;
pinterest: string;
};
}
class ProductDescriptionGenerator {
private openai: OpenAI;
private brandVoice: BrandVoiceProfile;
private categoryTemplates: Map;
constructor(
openai: OpenAI,
brandVoice: BrandVoiceProfile,
categoryTemplates: Map
) {
this.openai = openai;
this.brandVoice = brandVoice;
this.categoryTemplates = categoryTemplates;
}
async generateDescription(product: ProductData): Promise {
// Get category-specific template
const template = this.categoryTemplates.get(product.category) ||
this.categoryTemplates.get('default');
// Generate all content elements
const [shortDesc, longDesc, bulletPoints] = await Promise.all([
this.generateShortDescription(product, template),
this.generateLongDescription(product, template),
this.generateBulletPoints(product)
]);
// Generate SEO elements
const seoElements = await this.generateSEOElements(product, shortDesc);
// Generate image alt texts
const altTexts = await this.generateAltTexts(product);
// Generate social media snippets
const socialSnippets = await this.generateSocialSnippets(product, shortDesc);
return {
shortDescription: shortDesc,
longDescription: longDesc,
bulletPoints,
seoTitle: seoElements.title,
metaDescription: seoElements.metaDescription,
altTexts,
socialSnippets
};
}
private async generateShortDescription(
product: ProductData,
template?: DescriptionTemplate
): Promise {
const templateInstructions = template
? `Follow this structure: ${template.shortDescriptionFormat}`
: '';
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are a conversion-focused copywriter for e-commerce.
${this.brandVoice.toPrompt()}
Write concise, benefit-focused product descriptions that:
1. Lead with the main value proposition
2. Include 1-2 key features
3. Create urgency or desire
4. Are 2-3 sentences max (50-80 words)
${templateInstructions}`
},
{
role: 'user',
content: `Write a short product description for:
Product: ${product.name}
Category: ${product.category}
Key Features: ${product.features.slice(0, 3).join(', ')}
Price: $${product.price}
${product.compareAtPrice ? `Original Price: $${product.compareAtPrice} (${Math.round((1 - product.price / product.compareAtPrice) * 100)}% off)` : ''}
Specifications:
${Object.entries(product.specifications).map(([k, v]) => `- ${k}: ${v}`).join('\n')}`
}
],
temperature: 0.7,
max_tokens: 200
});
return response.choices[0].message.content || '';
}
private async generateLongDescription(
product: ProductData,
template?: DescriptionTemplate
): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are a persuasive product copywriter.
${this.brandVoice.toPrompt()}
Write detailed product descriptions that:
1. Tell a story or paint a picture of use
2. Address customer pain points
3. Highlight unique selling propositions
4. Include social proof elements naturally
5. Build trust with specifics and details
6. Are 150-250 words
Use formatting:
- Short paragraphs (2-3 sentences)
- Occasional emphasis on key benefits
- Natural keyword integration`
},
{
role: 'user',
content: `Write a detailed product description for:
Product: ${product.name}
Category: ${product.category} > ${product.subcategory || 'General'}
Features:
${product.features.map(f => `- ${f}`).join('\n')}
Materials: ${product.materials?.join(', ') || 'Not specified'}
Specifications:
${Object.entries(product.specifications).map(([k, v]) => `- ${k}: ${v}`).join('\n')}
${product.dimensions ? `Dimensions: ${product.dimensions.width} x ${product.dimensions.height} x ${product.dimensions.depth} ${product.dimensions.unit}` : ''}
${product.weight ? `Weight: ${product.weight.value} ${product.weight.unit}` : ''}
Target customer: Someone looking for quality ${product.category.toLowerCase()}`
}
],
temperature: 0.7,
max_tokens: 600
});
return response.choices[0].message.content || '';
}
private async generateBulletPoints(product: ProductData): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Generate scannable product bullet points that:
1. Start with a benefit, not a feature
2. Are concise (8-15 words each)
3. Use action words
4. Highlight unique aspects
5. Include key specifications
Format: Return exactly 5 bullet points as a JSON array.`
},
{
role: 'user',
content: `Create 5 bullet points for:
${product.name}
Features: ${product.features.join(', ')}
Specs: ${JSON.stringify(product.specifications)}`
}
],
temperature: 0.7,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{"bullets": []}');
return result.bullets || [];
}
private async generateAltTexts(product: ProductData): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Generate descriptive alt texts for product images that:
1. Describe what's visible in the image
2. Include the product name and key visual features
3. Are 50-125 characters
4. Are helpful for screen readers and SEO
5. Avoid phrases like "image of" or "picture of"`
},
{
role: 'user',
content: `Create alt texts for ${product.images.length} product images of:
${product.name}
Category: ${product.category}
Colors/Variants: ${product.variants?.map(v => v.options.color || v.name).join(', ') || 'Standard'}
Image positions typically:
1. Main product shot (front view)
2. Side/angle view
3. Detail/close-up
4. In-use/lifestyle shot
5. Size comparison or packaging
Return as JSON array.`
}
],
temperature: 0.5,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{"altTexts": []}');
return result.altTexts || [];
}
async generateBatchDescriptions(
products: ProductData[],
batchSize: number = 10
): Promise
SEO Content Optimization Engine
Effective SEO optimization requires more than keyword stuffing. Modern SEO focuses on semantic relevance, user intent, and content quality. Here's a comprehensive SEO optimization engine:
// seo-optimization-engine.ts
interface SEOAnalysisResult {
score: number;
issues: SEOIssue[];
recommendations: SEORecommendation[];
keywordAnalysis: KeywordAnalysis;
technicalSEO: TechnicalSEOCheck;
contentQuality: ContentQualityScore;
}
interface SEOIssue {
type: 'critical' | 'warning' | 'info';
category: 'content' | 'technical' | 'keyword' | 'structure';
message: string;
location?: string;
fix?: string;
}
interface SEORecommendation {
priority: 'high' | 'medium' | 'low';
action: string;
impact: string;
effort: 'easy' | 'medium' | 'hard';
}
interface KeywordAnalysis {
primary: {
keyword: string;
density: number;
positions: string[];
inTitle: boolean;
inMetaDescription: boolean;
inH1: boolean;
inFirstParagraph: boolean;
};
secondary: Array<{
keyword: string;
density: number;
optimal: boolean;
}>;
lsiKeywords: string[];
missingKeywords: string[];
}
class SEOOptimizationEngine {
private openai: OpenAI;
private serpApiKey?: string;
constructor(openai: OpenAI, serpApiKey?: string) {
this.openai = openai;
this.serpApiKey = serpApiKey;
}
async analyzeContent(
content: string,
targetKeywords: string[],
metadata: {
title: string;
metaDescription: string;
url: string;
}
): Promise {
const keywordAnalysis = this.analyzeKeywords(content, targetKeywords, metadata);
const technicalSEO = this.checkTechnicalSEO(content, metadata);
const contentQuality = await this.analyzeContentQuality(content);
const issues = this.identifyIssues(keywordAnalysis, technicalSEO, contentQuality);
const recommendations = this.generateRecommendations(issues);
const score = this.calculateOverallScore(keywordAnalysis, technicalSEO, contentQuality);
return {
score,
issues,
recommendations,
keywordAnalysis,
technicalSEO,
contentQuality
};
}
private analyzeKeywords(
content: string,
targetKeywords: string[],
metadata: { title: string; metaDescription: string }
): KeywordAnalysis {
const wordCount = this.countWords(content);
const primaryKeyword = targetKeywords[0];
const contentLower = content.toLowerCase();
const titleLower = metadata.title.toLowerCase();
const metaLower = metadata.metaDescription.toLowerCase();
// Analyze primary keyword
const primaryMatches = contentLower.match(new RegExp(primaryKeyword.toLowerCase(), 'g')) || [];
const primaryDensity = (primaryMatches.length / wordCount) * 100;
// Find keyword positions
const positions: string[] = [];
if (titleLower.includes(primaryKeyword.toLowerCase())) positions.push('title');
if (metaLower.includes(primaryKeyword.toLowerCase())) positions.push('meta description');
const paragraphs = content.split('\n\n');
if (paragraphs[0]?.toLowerCase().includes(primaryKeyword.toLowerCase())) {
positions.push('first paragraph');
}
// Check headings
const h1Match = content.match(/]*>(.*?)<\/h1>/i) ||
content.match(/^#\s+(.+)$/m);
const inH1 = h1Match?.[1]?.toLowerCase().includes(primaryKeyword.toLowerCase()) || false;
// Analyze secondary keywords
const secondary = targetKeywords.slice(1).map(keyword => {
const matches = contentLower.match(new RegExp(keyword.toLowerCase(), 'g')) || [];
const density = (matches.length / wordCount) * 100;
return {
keyword,
density,
optimal: density >= 0.5 && density <= 2.5
};
});
// Find LSI keywords (related terms)
const lsiKeywords = this.findLSIKeywords(content, primaryKeyword);
return {
primary: {
keyword: primaryKeyword,
density: primaryDensity,
positions,
inTitle: titleLower.includes(primaryKeyword.toLowerCase()),
inMetaDescription: metaLower.includes(primaryKeyword.toLowerCase()),
inH1,
inFirstParagraph: paragraphs[0]?.toLowerCase().includes(primaryKeyword.toLowerCase()) || false
},
secondary,
lsiKeywords,
missingKeywords: targetKeywords.filter(kw =>
!contentLower.includes(kw.toLowerCase())
)
};
}
private checkTechnicalSEO(
content: string,
metadata: { title: string; metaDescription: string; url: string }
): TechnicalSEOCheck {
return {
title: {
length: metadata.title.length,
optimal: metadata.title.length >= 50 && metadata.title.length <= 60,
issues: this.checkTitleIssues(metadata.title)
},
metaDescription: {
length: metadata.metaDescription.length,
optimal: metadata.metaDescription.length >= 150 &&
metadata.metaDescription.length <= 160,
issues: this.checkMetaDescriptionIssues(metadata.metaDescription)
},
url: {
length: metadata.url.length,
hasKeyword: this.urlHasKeyword(metadata.url),
issues: this.checkUrlIssues(metadata.url)
},
headings: this.analyzeHeadingStructure(content),
images: this.analyzeImages(content),
links: this.analyzeLinks(content)
};
}
private async analyzeContentQuality(content: string): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Analyze content quality for SEO. Score each factor 1-100:
1. Originality - unique insights, not generic
2. Depth - comprehensive coverage
3. Readability - clear, well-structured
4. Engagement - compelling, keeps reader interested
5. E-E-A-T signals - expertise, experience, authority, trust
Return JSON with scores and brief explanations.`
},
{
role: 'user',
content: `Analyze this content:\n\n${content.substring(0, 8000)}`
}
],
temperature: 0.3,
response_format: { type: 'json_object' }
});
return JSON.parse(response.choices[0].message.content || '{}');
}
async optimizeContent(
content: string,
analysis: SEOAnalysisResult,
targetKeywords: string[]
): Promise {
const optimizationInstructions = this.buildOptimizationInstructions(analysis);
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are an SEO content optimizer. Improve content while:
1. Maintaining natural readability
2. Preserving the original message and structure
3. Enhancing for search engines AND users
4. Not over-optimizing or keyword stuffing
${optimizationInstructions}`
},
{
role: 'user',
content: `Optimize this content for these keywords: ${targetKeywords.join(', ')}
Issues to fix:
${analysis.issues.map(i => `- ${i.message}`).join('\n')}
Content:
${content}`
}
],
temperature: 0.3,
max_tokens: 4000
});
return response.choices[0].message.content || content;
}
async generateMetaTags(
content: string,
primaryKeyword: string,
pageType: 'blog' | 'product' | 'landing' | 'category'
): Promise<{
title: string;
metaDescription: string;
ogTitle: string;
ogDescription: string;
twitterTitle: string;
twitterDescription: string;
schemaMarkup: object;
}> {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Generate optimized meta tags for SEO and social sharing.
Title tag: 50-60 characters, keyword near beginning, compelling
Meta description: 150-160 characters, include keyword, call to action
OG/Twitter: Optimized for social sharing, may differ from page meta
Return JSON with all meta tags.`
},
{
role: 'user',
content: `Generate meta tags for a ${pageType} page.
Primary keyword: ${primaryKeyword}
Content summary: ${content.substring(0, 1000)}...`
}
],
temperature: 0.5,
response_format: { type: 'json_object' }
});
const metaTags = JSON.parse(response.choices[0].message.content || '{}');
// Generate schema markup
const schemaMarkup = this.generateSchemaMarkup(pageType, content, primaryKeyword);
return {
...metaTags,
schemaMarkup
};
}
private generateSchemaMarkup(
pageType: string,
content: string,
keyword: string
): object {
const baseSchema = {
'@context': 'https://schema.org',
'@type': this.getSchemaType(pageType)
};
switch (pageType) {
case 'blog':
return {
...baseSchema,
'@type': 'Article',
headline: '',
description: '',
author: { '@type': 'Person', name: '' },
datePublished: new Date().toISOString(),
dateModified: new Date().toISOString()
};
case 'product':
return {
...baseSchema,
'@type': 'Product',
name: '',
description: '',
offers: {
'@type': 'Offer',
price: '',
priceCurrency: 'USD'
}
};
default:
return baseSchema;
}
}
private buildOptimizationInstructions(analysis: SEOAnalysisResult): string {
const instructions: string[] = [];
if (analysis.keywordAnalysis.primary.density < 1) {
instructions.push('Increase primary keyword usage naturally');
} else if (analysis.keywordAnalysis.primary.density > 3) {
instructions.push('Reduce primary keyword density to avoid over-optimization');
}
if (!analysis.keywordAnalysis.primary.inFirstParagraph) {
instructions.push('Include primary keyword in the first paragraph');
}
if (analysis.keywordAnalysis.missingKeywords.length > 0) {
instructions.push(`Add missing keywords: ${analysis.keywordAnalysis.missingKeywords.join(', ')}`);
}
return instructions.length > 0
? `Specific optimizations needed:\n${instructions.join('\n')}`
: 'Content is well-optimized. Make minor improvements if possible.';
}
private countWords(text: string): number {
return text.split(/\s+/).filter(w => w.length > 0).length;
}
private getSchemaType(pageType: string): string {
const types: Record = {
blog: 'Article',
product: 'Product',
landing: 'WebPage',
category: 'CollectionPage'
};
return types[pageType] || 'WebPage';
}
}
Multilingual Content Adaptation
Global websites need content in multiple languages. Simple translation is not enough; content must be culturally adapted and localized. Here's a comprehensive multilingual content system:
// multilingual-content-engine.ts
interface LocalizationConfig {
sourceLanguage: string;
targetLanguages: string[];
adaptationLevel: 'translation' | 'localization' | 'transcreation';
glossary: Record>;
styleGuides: Record;
}
interface LocalizedStyleGuide {
language: string;
formality: 'formal' | 'informal' | 'neutral';
dateFormat: string;
currencyFormat: string;
numberFormat: string;
culturalNotes: string[];
}
interface LocalizedContent {
language: string;
content: string;
metadata: {
title: string;
metaDescription: string;
keywords: string[];
};
culturalAdaptations: string[];
qualityScore: number;
}
class MultilingualContentEngine {
private openai: OpenAI;
private config: LocalizationConfig;
private translationMemory: Map> = new Map();
constructor(openai: OpenAI, config: LocalizationConfig) {
this.openai = openai;
this.config = config;
}
async localizeContent(
sourceContent: string,
sourceMetadata: { title: string; metaDescription: string; keywords: string[] },
targetLanguage: string
): Promise {
const styleGuide = this.config.styleGuides[targetLanguage];
const glossary = this.config.glossary;
// Check translation memory for segments
const segments = this.segmentContent(sourceContent);
const cachedTranslations = this.getCachedTranslations(segments, targetLanguage);
// Determine adaptation level based on config
const adaptationPrompt = this.buildAdaptationPrompt(targetLanguage, styleGuide);
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are a professional ${this.config.adaptationLevel === 'transcreation' ? 'transcreation specialist' : 'localization expert'} for ${targetLanguage}.
${adaptationPrompt}
Glossary terms (use exactly as specified):
${Object.entries(glossary).map(([en, translations]) =>
`"${en}" → "${translations[targetLanguage] || en}"`
).join('\n')}
Cultural adaptation requirements:
${styleGuide?.culturalNotes?.join('\n') || 'Standard localization practices'}
Return JSON with:
{
"content": "Localized content",
"title": "Localized title",
"metaDescription": "Localized meta description",
"keywords": ["localized", "keywords"],
"culturalAdaptations": ["List of cultural changes made"],
"notes": "Any localization notes"
}`
},
{
role: 'user',
content: `Localize this content to ${targetLanguage}:
Title: ${sourceMetadata.title}
Meta Description: ${sourceMetadata.metaDescription}
Keywords: ${sourceMetadata.keywords.join(', ')}
Content:
${sourceContent}
Previous translations to maintain consistency:
${this.formatCachedTranslations(cachedTranslations)}`
}
],
temperature: 0.3,
max_tokens: 4000,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{}');
// Update translation memory
this.updateTranslationMemory(segments, result.content, targetLanguage);
// Quality check
const qualityScore = await this.assessTranslationQuality(
sourceContent,
result.content,
targetLanguage
);
return {
language: targetLanguage,
content: result.content,
metadata: {
title: result.title,
metaDescription: result.metaDescription,
keywords: result.keywords
},
culturalAdaptations: result.culturalAdaptations || [],
qualityScore
};
}
async localizeToAllLanguages(
sourceContent: string,
sourceMetadata: { title: string; metaDescription: string; keywords: string[] }
): Promise
Quality Control and Brand Voice Maintenance
Maintaining consistent quality and brand voice across AI-generated content requires systematic quality control mechanisms:
// quality-control-system.ts
interface QualityGate {
name: string;
check: (content: string, context: QualityContext) => Promise;
threshold: number;
required: boolean;
}
interface QualityCheckResult {
passed: boolean;
score: number;
issues: string[];
suggestions: string[];
}
interface QualityContext {
contentType: string;
targetAudience: string;
brandVoice: BrandVoiceProfile;
keywords: string[];
existingContent?: string[]; // For duplicate checking
}
interface BrandVoiceProfile {
personality: string[];
toneDescriptors: string[];
vocabularyExamples: string[];
forbiddenWords: string[];
sentenceStyleGuide: {
avgLength: number;
maxLength: number;
preferActive: boolean;
};
exampleContent: string[];
}
class ContentQualityController {
private openai: OpenAI;
private qualityGates: QualityGate[];
private brandVoiceEmbeddings?: Float32Array[];
constructor(openai: OpenAI) {
this.openai = openai;
this.qualityGates = this.initializeQualityGates();
}
private initializeQualityGates(): QualityGate[] {
return [
{
name: 'Readability',
check: this.checkReadability.bind(this),
threshold: 60,
required: true
},
{
name: 'Originality',
check: this.checkOriginality.bind(this),
threshold: 85,
required: true
},
{
name: 'Brand Voice',
check: this.checkBrandVoice.bind(this),
threshold: 75,
required: true
},
{
name: 'SEO Optimization',
check: this.checkSEOOptimization.bind(this),
threshold: 70,
required: false
},
{
name: 'Factual Accuracy',
check: this.checkFactualAccuracy.bind(this),
threshold: 90,
required: true
},
{
name: 'Grammar & Style',
check: this.checkGrammarStyle.bind(this),
threshold: 85,
required: true
}
];
}
async runQualityChecks(
content: string,
context: QualityContext
): Promise<{
passed: boolean;
overallScore: number;
results: Map;
blockers: string[];
recommendations: string[];
}> {
const results = new Map();
const blockers: string[] = [];
const recommendations: string[] = [];
// Run all quality checks in parallel
const checkPromises = this.qualityGates.map(async gate => {
const result = await gate.check(content, context);
return { gate, result };
});
const checkResults = await Promise.all(checkPromises);
let totalScore = 0;
let passedRequired = true;
checkResults.forEach(({ gate, result }) => {
results.set(gate.name, result);
totalScore += result.score;
if (!result.passed && gate.required) {
passedRequired = false;
blockers.push(`${gate.name}: ${result.issues.join('; ')}`);
}
if (result.suggestions.length > 0) {
recommendations.push(...result.suggestions);
}
});
const overallScore = totalScore / this.qualityGates.length;
return {
passed: passedRequired && overallScore >= 70,
overallScore,
results,
blockers,
recommendations
};
}
private async checkReadability(
content: string,
context: QualityContext
): Promise {
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);
const words = content.split(/\s+/).filter(w => w.length > 0);
const avgSentenceLength = words.length / sentences.length;
const longSentences = sentences.filter(s =>
s.split(/\s+/).length > 25
).length;
// Flesch Reading Ease
const syllables = words.reduce((c, w) => c + this.countSyllables(w), 0);
const fleschScore = 206.835 -
(1.015 * avgSentenceLength) -
(84.6 * (syllables / words.length));
const issues: string[] = [];
const suggestions: string[] = [];
if (avgSentenceLength > 20) {
issues.push('Average sentence length is too high');
suggestions.push('Break long sentences into shorter ones');
}
if (longSentences > sentences.length * 0.2) {
issues.push(`${longSentences} sentences exceed 25 words`);
suggestions.push('Simplify complex sentences');
}
const score = Math.max(0, Math.min(100, fleschScore));
return {
passed: score >= 60 && issues.length === 0,
score,
issues,
suggestions
};
}
private async checkOriginality(
content: string,
context: QualityContext
): Promise {
const issues: string[] = [];
const suggestions: string[] = [];
// Check against existing content for duplicates
if (context.existingContent && context.existingContent.length > 0) {
const similarity = await this.calculateSimilarity(
content,
context.existingContent
);
if (similarity > 0.7) {
issues.push('Content is too similar to existing content');
suggestions.push('Add more unique insights and perspectives');
}
}
// Check for generic/boilerplate patterns
const genericPatterns = [
/in today's (fast-paced|digital|modern) world/gi,
/it's no secret that/gi,
/at the end of the day/gi,
/when it comes to/gi,
/in this article, we will/gi
];
const genericMatches = genericPatterns.reduce((count, pattern) => {
return count + (content.match(pattern) || []).length;
}, 0);
if (genericMatches > 3) {
issues.push('Content contains too many generic phrases');
suggestions.push('Replace cliche phrases with specific, unique language');
}
const score = Math.max(0, 100 - (genericMatches * 5) - (issues.length * 10));
return {
passed: score >= 85,
score,
issues,
suggestions
};
}
private async checkBrandVoice(
content: string,
context: QualityContext
): Promise {
const { brandVoice } = context;
const issues: string[] = [];
const suggestions: string[] = [];
// Check forbidden words
const forbiddenFound = brandVoice.forbiddenWords.filter(word =>
new RegExp(`\\b${word}\\b`, 'gi').test(content)
);
if (forbiddenFound.length > 0) {
issues.push(`Contains forbidden words: ${forbiddenFound.join(', ')}`);
suggestions.push('Replace forbidden words with brand-appropriate alternatives');
}
// Use AI to assess brand voice alignment
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Assess brand voice alignment. The brand voice should be:
Personality: ${brandVoice.personality.join(', ')}
Tone: ${brandVoice.toneDescriptors.join(', ')}
Example approved content:
${brandVoice.exampleContent.slice(0, 2).join('\n\n')}
Score the content 1-100 on brand voice alignment and explain any issues.`
},
{
role: 'user',
content: `Assess this content:\n\n${content.substring(0, 3000)}`
}
],
temperature: 0.2,
response_format: { type: 'json_object' }
});
const assessment = JSON.parse(response.choices[0].message.content || '{}');
const aiScore = assessment.score || 70;
if (assessment.issues) {
issues.push(...assessment.issues);
}
if (assessment.suggestions) {
suggestions.push(...assessment.suggestions);
}
const score = Math.max(0, aiScore - (forbiddenFound.length * 5));
return {
passed: score >= 75,
score,
issues,
suggestions
};
}
private async checkFactualAccuracy(
content: string,
context: QualityContext
): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are a fact-checker. Identify any claims that:
1. Are factually incorrect
2. Are outdated
3. Lack proper context
4. Could be misleading
Be especially careful with:
- Statistics and numbers
- Technical specifications
- Legal or medical claims
- Historical facts
Return JSON with issues found and confidence level.`
},
{
role: 'user',
content: `Fact-check this content:\n\n${content.substring(0, 4000)}`
}
],
temperature: 0.2,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{}');
return {
passed: (result.issues || []).length === 0,
score: result.confidenceScore || 85,
issues: result.issues || [],
suggestions: result.suggestions || []
};
}
private async checkSEOOptimization(
content: string,
context: QualityContext
): Promise {
const wordCount = content.split(/\s+/).length;
const issues: string[] = [];
const suggestions: string[] = [];
// Keyword density check
context.keywords.forEach(keyword => {
const matches = content.match(new RegExp(keyword, 'gi')) || [];
const density = (matches.length / wordCount) * 100;
if (density < 0.5) {
issues.push(`Keyword "${keyword}" underused (${density.toFixed(2)}%)`);
} else if (density > 3) {
issues.push(`Keyword "${keyword}" overused (${density.toFixed(2)}%)`);
}
});
// Content length check
if (wordCount < 1000) {
suggestions.push('Consider adding more comprehensive content (1500+ words recommended)');
}
// Heading structure check
const h2Count = (content.match(/##\s/g) || []).length;
if (h2Count < 3) {
suggestions.push('Add more H2 headings for better structure');
}
const score = Math.max(0, 100 - (issues.length * 10));
return {
passed: score >= 70,
score,
issues,
suggestions
};
}
private async checkGrammarStyle(
content: string,
context: QualityContext
): Promise {
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `Check for grammar and style issues:
1. Grammatical errors
2. Punctuation mistakes
3. Passive voice overuse
4. Redundant phrases
5. Inconsistent tense
6. Word repetition
Return JSON with issues and their locations.`
},
{
role: 'user',
content: `Check this content:\n\n${content.substring(0, 4000)}`
}
],
temperature: 0.2,
response_format: { type: 'json_object' }
});
const result = JSON.parse(response.choices[0].message.content || '{}');
return {
passed: (result.issues || []).length <= 3,
score: Math.max(0, 100 - ((result.issues || []).length * 5)),
issues: result.issues || [],
suggestions: result.suggestions || []
};
}
private countSyllables(word: string): number {
word = word.toLowerCase();
if (word.length <= 3) return 1;
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
word = word.replace(/^y/, '');
const matches = word.match(/[aeiouy]{1,2}/g);
return matches ? matches.length : 1;
}
private async calculateSimilarity(
content: string,
existingContent: string[]
): Promise {
// Simplified similarity check using AI
const response = await this.openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: 'Calculate semantic similarity between the new content and existing content. Return a score from 0 to 1.'
},
{
role: 'user',
content: `New content:\n${content.substring(0, 1000)}\n\nExisting content samples:\n${existingContent.slice(0, 3).map(c => c.substring(0, 500)).join('\n---\n')}`
}
],
temperature: 0.1
});
const match = response.choices[0].message.content?.match(/(\d+\.?\d*)/);
return match ? parseFloat(match[1]) : 0;
}
}
Case Study: Scaling from 100 to 10,000 Pages
Real-world content scaling requires careful orchestration. Here's how to implement a production content generation system that can scale to thousands of pages:
// content-scaling-orchestrator.ts
interface ContentScalingConfig {
dailyPageLimit: number;
qualityThreshold: number;
reviewSampleRate: number; // % of content for human review
parallelGenerations: number;
retryAttempts: number;
}
interface ContentGenerationJob {
id: string;
type: 'blog' | 'product' | 'landing' | 'category';
input: ContentInput;
status: 'pending' | 'generating' | 'reviewing' | 'approved' | 'published' | 'failed';
attempts: number;
content?: GeneratedContent;
qualityScore?: number;
reviewNotes?: string;
createdAt: Date;
updatedAt: Date;
}
class ContentScalingOrchestrator {
private config: ContentScalingConfig;
private generator: AIContentGenerator;
private qualityController: ContentQualityController;
private jobQueue: ContentGenerationJob[] = [];
private activeJobs: Map = new Map();
constructor(
config: ContentScalingConfig,
generator: AIContentGenerator,
qualityController: ContentQualityController
) {
this.config = config;
this.generator = generator;
this.qualityController = qualityController;
}
async queueContentGeneration(inputs: ContentInput[]): Promise {
const jobs = inputs.map(input => this.createJob(input));
this.jobQueue.push(...jobs);
return jobs.map(j => j.id);
}
async processQueue(): Promise {
const report: ContentGenerationReport = {
totalProcessed: 0,
successful: 0,
failed: 0,
sentForReview: 0,
averageQualityScore: 0,
processingTime: 0,
errors: []
};
const startTime = Date.now();
const dailyLimit = this.config.dailyPageLimit;
let processedToday = 0;
while (this.jobQueue.length > 0 && processedToday < dailyLimit) {
// Process in parallel batches
const batch = this.jobQueue.splice(0, this.config.parallelGenerations);
const results = await Promise.allSettled(
batch.map(job => this.processJob(job))
);
results.forEach((result, index) => {
report.totalProcessed++;
processedToday++;
if (result.status === 'fulfilled') {
const job = result.value;
if (job.status === 'approved' || job.status === 'published') {
report.successful++;
report.averageQualityScore += job.qualityScore || 0;
} else if (job.status === 'reviewing') {
report.sentForReview++;
} else if (job.status === 'failed') {
report.failed++;
report.errors.push({
jobId: job.id,
error: job.reviewNotes || 'Unknown error'
});
}
} else {
report.failed++;
report.errors.push({
jobId: batch[index].id,
error: result.reason?.message || 'Processing failed'
});
}
});
// Rate limiting between batches
await this.sleep(2000);
}
report.processingTime = Date.now() - startTime;
report.averageQualityScore = report.successful > 0
? report.averageQualityScore / report.successful
: 0;
return report;
}
private async processJob(job: ContentGenerationJob): Promise {
job.status = 'generating';
job.updatedAt = new Date();
this.activeJobs.set(job.id, job);
try {
// Generate content
const content = await this.generator.generateContent({
type: job.type,
topic: job.input.topic,
keywords: job.input.keywords,
targetLength: job.input.targetLength || 1500,
tone: job.input.tone || 'professional',
targetAudience: job.input.targetAudience || 'general'
});
// Run quality checks
const qualityResult = await this.qualityController.runQualityChecks(
content.content,
{
contentType: job.type,
targetAudience: job.input.targetAudience,
brandVoice: job.input.brandVoice,
keywords: job.input.keywords
}
);
job.content = content;
job.qualityScore = qualityResult.overallScore;
// Determine status based on quality
if (!qualityResult.passed) {
// Retry if under attempt limit
if (job.attempts < this.config.retryAttempts) {
job.attempts++;
job.reviewNotes = qualityResult.blockers.join('; ');
return this.processJob(job); // Retry
}
job.status = 'failed';
job.reviewNotes = qualityResult.blockers.join('; ');
} else if (this.shouldSendForReview(qualityResult.overallScore)) {
job.status = 'reviewing';
} else {
job.status = 'approved';
}
} catch (error) {
job.status = 'failed';
job.reviewNotes = error instanceof Error ? error.message : 'Unknown error';
if (job.attempts < this.config.retryAttempts) {
job.attempts++;
await this.sleep(5000); // Wait before retry
return this.processJob(job);
}
}
job.updatedAt = new Date();
this.activeJobs.delete(job.id);
return job;
}
private shouldSendForReview(qualityScore: number): boolean {
// Always review if score is borderline
if (qualityScore < 85) return true;
// Random sample for high-quality content
return Math.random() < this.config.reviewSampleRate;
}
private createJob(input: ContentInput): ContentGenerationJob {
return {
id: `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
type: input.type,
input,
status: 'pending',
attempts: 0,
createdAt: new Date(),
updatedAt: new Date()
};
}
getProgress(): {
pending: number;
active: number;
completed: number;
} {
return {
pending: this.jobQueue.length,
active: this.activeJobs.size,
completed: 0 // Track in database in production
};
}
private sleep(ms: number): Promise {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
Key Takeaways
Remember These Points
- Build comprehensive pipelines: Content generation requires planning, generation, quality assurance, and publishing stages
- Implement quality gates: Automated quality checks for readability, originality, brand voice, and SEO are essential for scaling
- Maintain brand voice systematically: Use style guides, vocabulary libraries, and AI-based alignment scoring
- Optimize for SEO intelligently: Balance keyword density with natural language and user experience
- Localize, don't just translate: Cultural adaptation is as important as linguistic accuracy for global content
- Scale with quality controls: Implement review sampling, retry logic, and human oversight for high-volume generation
- Avoid duplicate content: Use semantic uniqueness scoring and structural variation to ensure originality
Conclusion
AI-powered content generation has matured from experimental technology to production-ready systems capable of scaling from hundreds to thousands of pages while maintaining quality and brand consistency. The key to success lies not just in the AI models, but in the comprehensive systems built around them: quality control mechanisms, brand voice maintenance, SEO optimization, and intelligent orchestration.
Companies successfully scaling content with AI follow a methodical approach: start with strong templates and style guides, implement rigorous quality gates, maintain human oversight for edge cases, and continuously improve based on performance metrics. According to CMI research, teams using AI for content creation are 2.5x more productive while maintaining or improving quality metrics.
For further exploration, consider OpenAI's GPT-4 system card for understanding model capabilities, Google's Helpful Content guidelines for SEO best practices with AI content, and our SEO optimization guide for deeper technical implementation.