تخطي إلى المحتوى

Dec 24, 2024

AI-Powered Content Generation for B2B: Claude API Deep Dive

10 min · AI · Content Generation · Claude API · Automation · B2B Content

AI-Powered Content Generation for B2B: Claude API Deep Dive

Content is the engine of B2B marketing. But producing high-quality content at scale is expensive and time-consuming. Enter Claude API: a powerful language model that can generate blog posts, product descriptions, email campaigns, and more—while maintaining brand voice and quality standards.

This guide explores building production-grade content generation systems using Claude, from simple use cases to complex automation workflows.

Why Claude for B2B Content?

Claude excels at B2B content generation because it:

  • Understands context deeply: Can maintain consistent voice across long pieces
  • Handles nuance: Explains technical concepts for diverse audiences
  • Produces factual content: Less prone to hallucination than some competitors
  • Supports long prompts: Can process detailed briefs and specifications
  • Works with structured data: Converts CSV, JSON, and databases into prose

Getting Started with Claude API

Setup

npm install @anthropic-ai/sdk dotenv
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
  apiKey: process.env.CLAUDE_API_KEY,
});

Basic Content Generation

async function generateBlogPost(topic: string, keyPoints: string[]): Promise<string> {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 2048,
    messages: [
      {
        role: 'user',
        content: `Write a comprehensive blog post about: ${topic}

Key points to cover:
${keyPoints.map((point) => `- ${point}`).join('\n')}

Requirements:
- Length: 1500-2000 words
- Format: Markdown with H2 and H3 headings
- Tone: Professional but accessible
- Include practical examples and code where relevant
- End with a clear call-to-action`,
      },
    ],
  });

  return message.content[0].type === 'text' ? message.content[0].text : '';
}

// Usage
const post = await generateBlogPost('Database Scaling Strategies', [
  'Connection pooling patterns',
  'Read replicas for performance',
  'Sharding vs partitioning',
  'Monitoring and optimization',
]);

console.log(post);

Advanced: Content Generation Pipeline

Build a complete content generation workflow:

interface ContentBrief {
  title: string;
  topic: string;
  targetAudience: string;
  keyPoints: string[];
  includeCodeExamples: boolean;
  tone: 'technical' | 'business' | 'casual';
  length: 'short' | 'medium' | 'long'; // 500, 1500, 2500 words
}

interface GeneratedContent {
  title: string;
  content: string;
  seo: {
    metaDescription: string;
    keywords: string[];
  };
  qualityScore: number;
  readabilityScore: number;
}

async function generateContentPipeline(brief: ContentBrief): Promise<GeneratedContent> {
  // Step 1: Generate outline
  const outline = await generateOutline(brief);

  // Step 2: Generate full content
  const content = await generateFullContent(brief, outline);

  // Step 3: Generate SEO metadata
  const seo = await generateSEOMetadata(brief.title, content);

  // Step 4: Quality verification
  const qualityScore = await verifyContentQuality(content, brief);
  const readabilityScore = await calculateReadability(content);

  return {
    title: brief.title,
    content,
    seo,
    qualityScore,
    readabilityScore,
  };
}

// Step 1: Generate outline
async function generateOutline(brief: ContentBrief): Promise<string[]> {
  const lengthMap = { short: 3, medium: 5, long: 7 };
  const sectionCount = lengthMap[brief.length];

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 512,
    messages: [
      {
        role: 'user',
        content: `Create a ${sectionCount}-section outline for: "${brief.title}"

Topic: ${brief.topic}
Target Audience: ${brief.targetAudience}
Tone: ${brief.tone}

Return as JSON array of section titles:
["Section 1", "Section 2", ...]`,
      },
    ],
  });

  const responseText =
    message.content[0].type === 'text' ? message.content[0].text : '[]';
  try {
    return JSON.parse(responseText);
  } catch {
    return [];
  }
}

// Step 2: Generate full content
async function generateFullContent(brief: ContentBrief, outline: string[]): Promise<string> {
  const systemPrompt = `You are an expert B2B content writer specializing in technical topics.
Your content is clear, accurate, and compelling.
You maintain a consistent brand voice across all writing.
You include practical examples and actionable insights.
${brief.includeCodeExamples ? 'Include relevant code examples in TypeScript/Go where helpful.' : ''}
Avoid marketing hype; focus on substance and value.`;

  const userPrompt = `Write a comprehensive article about: "${brief.title}"

Outline to follow:
${outline.map((s, i) => `${i + 1}. ${s}`).join('\n')}

Requirements:
- Target word count: ${brief.length === 'short' ? '500-800' : brief.length === 'medium' ? '1200-1800' : '2000-2500'}
- Tone: ${brief.tone}
- Include a compelling introduction and conclusion
- Use markdown formatting (H2 for sections, H3 for subsections)
${brief.includeCodeExamples ? '- Include 2-3 relevant code examples in code blocks' : ''}

Key points to emphasize:
${brief.keyPoints.map((p) => `- ${p}`).join('\n')}`;

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 4096,
    system: systemPrompt,
    messages: [
      {
        role: 'user',
        content: userPrompt,
      },
    ],
  });

  return message.content[0].type === 'text' ? message.content[0].text : '';
}

// Step 3: Generate SEO metadata
async function generateSEOMetadata(
  title: string,
  content: string
): Promise<{ metaDescription: string; keywords: string[] }> {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 256,
    messages: [
      {
        role: 'user',
        content: `For this article:
Title: "${title}"

Content preview: ${content.substring(0, 500)}...

Generate:
1. Meta description (150-160 characters)
2. 5-7 SEO keywords

Return as JSON:
{
  "metaDescription": "...",
  "keywords": ["keyword1", "keyword2", ...]
}`,
      },
    ],
  });

  const responseText =
    message.content[0].type === 'text' ? message.content[0].text : '{}';
  try {
    return JSON.parse(responseText);
  } catch {
    return { metaDescription: '', keywords: [] };
  }
}

// Step 4: Verify content quality
async function verifyContentQuality(
  content: string,
  brief: ContentBrief
): Promise<number> {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 512,
    messages: [
      {
        role: 'user',
        content: `Evaluate this article for quality on a scale of 0-100:

Title: "${brief.title}"
Content length: ${content.length} characters
Target audience: ${brief.targetAudience}

Scoring criteria (equal weight):
1. Accuracy and factuality
2. Relevance to title and topic
3. Clarity and readability
4. Practical value and actionability
5. Proper structure and formatting

Content preview: ${content.substring(0, 1000)}...

Respond ONLY with a number 0-100.`,
      },
    ],
  });

  const responseText =
    message.content[0].type === 'text' ? message.content[0].text : '0';
  return parseInt(responseText.trim(), 10);
}

// Step 5: Calculate readability
async function calculateReadability(content: string): Promise<number> {
  const words = content.split(/\s+/).length;
  const sentences = content.split(/[.!?]+/).length;
  const syllables = countSyllables(content);

  // Flesch Reading Ease: 100 = easy, 0 = difficult
  const fleschScore =
    206.835 -
    1.015 * (words / sentences) -
    84.6 * (syllables / words);

  return Math.max(0, Math.min(100, fleschScore));
}

function countSyllables(text: string): number {
  const words = text.toLowerCase().match(/\b[a-z]+\b/g) || [];
  let count = 0;

  for (const word of words) {
    count += word.match(/[aeiouy]/g)?.length || 0;
    if (word.endsWith('e')) count--;
    if (word.endsWith('le') && word.length > 2) count++;
    if (count === 0) count = 1;
  }

  return count;
}

Real-World Use Cases

Product Description Generation

interface Product {
  name: string;
  sku: string;
  category: string;
  specifications: Record<string, string>;
  targetMarkets: string[];
  price: number;
}

async function generateProductDescription(product: Product): Promise<string> {
  const specsText = Object.entries(product.specifications)
    .map(([key, value]) => `${key}: ${value}`)
    .join('\n');

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 512,
    messages: [
      {
        role: 'user',
        content: `Generate a compelling product description:

Product: ${product.name}
SKU: ${product.sku}
Category: ${product.category}
Price: $${product.price}

Specifications:
${specsText}

Target Markets: ${product.targetMarkets.join(', ')}

Requirements:
- 150-200 words
- Lead with key benefit (not features)
- Highlight what problem it solves
- Include a call-to-action
- Professional but accessible tone`,
      },
    ],
  });

  return message.content[0].type === 'text' ? message.content[0].text : '';
}

Email Campaign Generation

interface EmailCampaign {
  objective: string; // 'demo_request', 'lead_nurture', 'win_back'
  recipientRole: string; // 'engineer', 'manager', 'c-suite'
  productBenefit: string;
  companyName: string;
}

async function generateEmailSequence(campaign: EmailCampaign): Promise<string[]> {
  const emails: string[] = [];

  for (let i = 1; i <= 3; i++) {
    const message = await client.messages.create({
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 512,
      messages: [
        {
          role: 'user',
          content: `Write email #${i} of a 3-email sequence for: "${campaign.objective}"

Recipient: ${campaign.recipientRole}
Product benefit: ${campaign.productBenefit}
Company: ${campaign.companyName}

${i === 1 ? 'Email 1: Introduction and value prop' : ''}
${i === 2 ? 'Email 2: Overcome objection and build credibility' : ''}
${i === 3 ? 'Email 3: Final call-to-action with urgency' : ''}

Requirements:
- Keep subject line separate
- Max 150 words
- Clear call-to-action
- Personalized feel despite being generated`,
        },
      ],
    });

    emails.push(
      message.content[0].type === 'text' ? message.content[0].text : ''
    );
  }

  return emails;
}

Bulk Content Generation

interface ContentJob {
  id: string;
  briefs: ContentBrief[];
  status: 'pending' | 'processing' | 'completed' | 'failed';
  results?: GeneratedContent[];
  errorMessage?: string;
}

async function processBulkContentJob(job: ContentJob): Promise<void> {
  try {
    const results: GeneratedContent[] = [];

    for (const brief of job.briefs) {
      const content = await generateContentPipeline(brief);

      // Quality filter: reject if score < 70
      if (content.qualityScore >= 70) {
        results.push(content);
      } else {
        console.warn(
          `Content rejected for "${brief.title}" (score: ${content.qualityScore})`
        );
      }

      // Rate limiting: 1 request per 2 seconds
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }

    job.status = 'completed';
    job.results = results;
  } catch (error) {
    job.status = 'failed';
    job.errorMessage = error instanceof Error ? error.message : 'Unknown error';
  }

  // Save job to database
  await saveContentJob(job);
}

Quality Assurance

Always implement quality checks before publishing:

interface QualityCheck {
  factualAccuracy: boolean;
  brandConsistency: boolean;
  keyPointsCovered: boolean;
  properFormatting: boolean;
  noPlaceholders: boolean;
  plagiarismCheck: boolean;
}

async function performQualityChecks(
  content: GeneratedContent,
  brief: ContentBrief
): Promise<QualityCheck> {
  return {
    factualAccuracy: content.qualityScore >= 75,
    brandConsistency: await checkBrandVoice(content.content),
    keyPointsCovered: brief.keyPoints.every((point) =>
      content.content.toLowerCase().includes(point.toLowerCase())
    ),
    properFormatting: /^# |^## /.test(content.content),
    noPlaceholders: !content.content.includes('[INSERT]'),
    plagiarismCheck: true, // In production, use plagiarism API
  };
}

function areAllChecksPass(checks: QualityCheck): boolean {
  return Object.values(checks).every((check) => check === true);
}

Cost Optimization

Claude's pricing is usage-based. Optimize costs:

interface CostOptimization {
  useCache: boolean; // Leverage prompt caching for repeated briefs
  batchProcessing: boolean; // Use batch API for non-urgent content
  maxTokensPerRequest: number;
}

// Using prompt caching for repeated content types
async function generateWithCache(brief: ContentBrief): Promise<string> {
  const systemPrompt = `You are an expert B2B content writer...`; // Frequently repeated

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 2048,
    system: [
      {
        type: 'text',
        text: systemPrompt,
        cache_control: { type: 'ephemeral' }, // Cache system prompt
      },
    ],
    messages: [
      {
        role: 'user',
        content: generateUserPrompt(brief),
      },
    ],
  });

  return message.content[0].type === 'text' ? message.content[0].text : '';
}

Integration with Your B2B Platform

Connect Claude content generation to your website:

// API endpoint for content generation
export async function POST(request: Request) {
  const { brief } = await request.json();

  try {
    const content = await generateContentPipeline(brief);

    // Save to database
    await db.content.create({
      title: content.title,
      body: content.content,
      metaDescription: content.seo.metaDescription,
      keywords: content.seo.keywords,
      qualityScore: content.qualityScore,
      readabilityScore: content.readabilityScore,
      createdAt: new Date(),
    });

    return Response.json({
      success: true,
      content,
    });
  } catch (error) {
    return Response.json(
      { error: 'Content generation failed' },
      { status: 500 }
    );
  }
}

Combining with Other Tools

For maximum effectiveness, integrate Claude with other services:

  • Scraping + Claude: Scrape competitor content, have Claude analyze and generate original insights
  • Search + Claude: Research trending topics, have Claude create timely content
  • Email APIs + Claude: Generate personalized email sequences at scale
  • CMS + Claude: Automatically publish generated content to your website

For a deeper look at how these tools work together, see our guide on [AI Chatbots for B2B Sales](../ai-chatbots-for-b2b-sales).

Common Pitfalls to Avoid

Don't:

  • Publish Claude output without review (always QA)
  • Use outdated product information in briefs
  • Generate content without clear brand voice guidelines
  • Forget to include primary keywords for SEO
  • Ignore plagiarism concerns

Do:

  • Set clear quality standards upfront
  • Review 100% of generated content initially
  • Gradually increase automation as you refine the process
  • Include human expertise in verification
  • Track performance of generated content

Conclusion

Claude API makes high-quality B2B content generation achievable at scale. By implementing proper pipelines, quality checks, and integration with your platform, you can reduce content production time by 70-80% while maintaining quality standards.

The key is treating Claude as a powerful tool that amplifies human creativity, not as a replacement for human judgment.

MK