AI Content-Generierung in Drupal: Automatische Texterstellung mit ChatGPT

Steven Schulz
Steven Schulz

AI Content-Generierung in Drupal: Automatische Texterstellung mit ChatGPT

Mit dem Drupal AI Module können Sie Content automatisch generieren lassen – von Blog-Posts über Produktbeschreibungen bis hin zu SEO-optimierten Meta-Tags. Dieser Guide zeigt praktische Implementierungen für verschiedene Anwendungsfälle.

Setup: AI Content Module

Installation

# AI Content Module installieren
composer require drupal/ai
composer require drupal/ai_openai
composer require drupal/ai_content

# Module aktivieren
drush en ai ai_openai ai_content ai_automator -y

Konfiguration

Navigation: /admin/config/ai/content

Default Provider: OpenAI
Default Model: gpt-4o-mini
Temperature: 0.7
Max Tokens: 2000
Fallback on Error: true
Cache Results: true
Cache TTL: 86400 # 24 Stunden

Use Case 1: Automatische Blog-Post Generierung

Bulk Content Creation

<?php
namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Bulk Blog Post Generator Form.
 */
class AiBlogGeneratorForm extends FormBase {

  public function getFormId() {
    return 'ai_blog_generator_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['topic'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Haupt-Thema'),
      '#required' => TRUE,
      '#description' => $this->t('z.B. "Drupal Module Development"'),
    ];

    $form['keywords'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Keywords'),
      '#description' => $this->t('Ein Keyword pro Zeile'),
    ];

    $form['count'] = [
      '#type' => 'number',
      '#title' => $this->t('Anzahl Artikel'),
      '#default_value' => 5,
      '#min' => 1,
      '#max' => 50,
    ];

    $form['tone'] = [
      '#type' => 'select',
      '#title' => $this->t('Tonalität'),
      '#options' => [
        'professional' => $this->t('Professionell'),
        'casual' => $this->t('Locker'),
        'technical' => $this->t('Technisch'),
        'educational' => $this->t('Lehrreich'),
      ],
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Artikel generieren'),
    ];

    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $topic = $form_state->getValue('topic');
    $keywords = array_filter(explode("\n", $form_state->getValue('keywords')));
    $count = $form_state->getValue('count');
    $tone = $form_state->getValue('tone');

    $batch = [
      'title' => $this->t('Generiere Blog-Posts...'),
      'operations' => [],
      'finished' => '\Drupal\mymodule\Batch\AiBlogGeneratorBatch::finished',
    ];

    foreach ($keywords as $keyword) {
      $batch['operations'][] = [
        '\Drupal\mymodule\Batch\AiBlogGeneratorBatch::generatePost',
        [$topic, trim($keyword), $tone],
      ];
    }

    batch_set($batch);
  }
}

Batch Processing

<?php
namespace Drupal\mymodule\Batch;

use Drupal\node\Entity\Node;

/**
 * Batch operations for AI blog generation.
 */
class AiBlogGeneratorBatch {

  public static function generatePost($topic, $keyword, $tone, &$context) {
    $ai_provider = \Drupal::service('ai.provider');

    // System Prompt basierend auf Tonalität
    $system_prompts = [
      'professional' => 'Du bist ein professioneller Tech-Blogger mit Expertise in Drupal.',
      'casual' => 'Du bist ein freundlicher Blogger, der komplexe Themen einfach erklärt.',
      'technical' => 'Du bist ein technischer Experte, der detaillierte Implementierungen beschreibt.',
      'educational' => 'Du bist ein geduldiger Lehrer, der Schritt-für-Schritt erklärt.',
    ];

    $prompt = <<<PROMPT
Erstelle einen ausführlichen Blog-Post zum Thema: {$topic}
Fokus-Keyword: {$keyword}

Anforderungen:
- 800-1200 Wörter
- Mindestens 3 Haupt-Abschnitte mit H2 Überschriften
- Praktische Code-Beispiele wo relevant
- SEO-optimiert für das Keyword "{$keyword}"
- Tonalität: {$tone}
- Format: Markdown
- Deutsche Sprache

Struktur:
1. Einleitung mit Hook
2. Hauptteil mit technischen Details
3. Praktisches Beispiel
4. Best Practices
5. Fazit

Beginne direkt mit dem Titel (# Format).
PROMPT;

    try {
      $response = $ai_provider->chat([
        'model' => 'gpt-4o-mini',
        'messages' => [
          ['role' => 'system', 'content' => $system_prompts[$tone]],
          ['role' => 'user', 'content' => $prompt],
        ],
        'temperature' => 0.8,
        'max_tokens' => 3000,
      ]);

      $content = $response->getNormalized();

      // Titel extrahieren (erste # Zeile)
      preg_match('/^#\s+(.+)$/m', $content, $matches);
      $title = $matches[1] ?? "{$keyword} - {$topic}";

      // Titel aus Content entfernen für Body
      $body = preg_replace('/^#\s+.+$/m', '', $content, 1);

      // Meta Description generieren
      $meta_desc_prompt = "Erstelle eine SEO-optimierte Meta-Description (max 155 Zeichen) für: {$title}";
      $meta_response = $ai_provider->chat([
        'model' => 'gpt-4o-mini',
        'messages' => [
          ['role' => 'user', 'content' => $meta_desc_prompt]
        ],
        'temperature' => 0.7,
        'max_tokens' => 100,
      ]);

      $meta_description = $meta_response->getNormalized();

      // Node erstellen
      $node = Node::create([
        'type' => 'article',
        'title' => $title,
        'body' => [
          'value' => $body,
          'format' => 'full_html',
        ],
        'field_meta_description' => $meta_description,
        'field_ai_generated' => TRUE,
        'field_keywords' => $keyword,
        'status' => 0, // Unpublished for review
      ]);

      $node->save();

      $context['results'][] = $node->id();
      $context['message'] = t('Generiert: @title', ['@title' => $title]);

    }
    catch (\Exception $e) {
      \Drupal::logger('ai_blog')->error('Failed to generate post: @error', [
        '@error' => $e->getMessage(),
      ]);
    }
  }

  public static function finished($success, $results, $operations) {
    if ($success) {
      $message = \Drupal::translation()->formatPlural(
        count($results),
        'Ein Blog-Post wurde generiert.',
        '@count Blog-Posts wurden generiert.'
      );
      \Drupal::messenger()->addStatus($message);
    }
    else {
      \Drupal::messenger()->addError(t('Fehler bei der Generierung.'));
    }
  }
}

Use Case 2: Produktbeschreibungen generieren

Product Import mit AI Enhancement

<?php
namespace Drupal\mymodule\Plugin\migrate\process;

use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;

/**
 * Generate product description using AI.
 *
 * @MigrateProcessPlugin(
 *   id = "ai_product_description"
 * )
 */
class AiProductDescription extends ProcessPluginBase {

  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {

    // Wert ist z.B. ein kurzer Produkt-Name
    $product_name = $value;
    $category = $row->getSourceProperty('category');
    $features = $row->getSourceProperty('features');

    $ai_provider = \Drupal::service('ai.provider');

    $prompt = <<<PROMPT
Erstelle eine überzeugende E-Commerce Produktbeschreibung:

Produkt: {$product_name}
Kategorie: {$category}
Features: {$features}

Anforderungen:
- 150-200 Wörter
- Überzeugend und verkaufsfördernd
- Hebe Benefits hervor (nicht nur Features)
- Professioneller Ton
- Strukturiert mit Absätzen
- Deutsche Sprache
- SEO-optimiert

Format: HTML (nur p, ul, li, strong Tags)
PROMPT;

    try {
      $response = $ai_provider->chat([
        'model' => 'gpt-4o-mini',
        'messages' => [
          ['role' => 'system', 'content' => 'Du bist ein E-Commerce Copywriter.'],
          ['role' => 'user', 'content' => $prompt],
        ],
        'temperature' => 0.8,
      ]);

      return $response->getNormalized();
    }
    catch (\Exception $e) {
      \Drupal::logger('ai_product')->error($e->getMessage());
      return $product_name; // Fallback
    }
  }
}

Verwendung in Migration YAML

# migrate_plus.migration.products.yml
id: products
label: 'Product Import with AI'
source:
  plugin: csv
  path: /path/to/products.csv
  header_offset: 0
  keys:
    - sku

process:
  title: name
  body/value:
    plugin: ai_product_description
    source: name
  body/format:
    plugin: default_value
    default_value: full_html

destination:
  plugin: 'entity:node'
  default_bundle: product

Use Case 3: Content Translation mit AI

Multilingual Content Generator

<?php
/**
 * AI-gestützte Übersetzung für mehrsprachige Sites.
 */
function ai_translate_node(Node $node, $target_language) {
  $ai_provider = \Drupal::service('ai.provider');

  $source_title = $node->getTitle();
  $source_body = $node->get('body')->value;

  $language_names = [
    'de' => 'Deutsch',
    'en' => 'Englisch',
    'fr' => 'Französisch',
    'es' => 'Spanisch',
    'it' => 'Italienisch',
  ];

  $target_lang_name = $language_names[$target_language] ?? $target_language;

  // Titel übersetzen
  $title_response = $ai_provider->chat([
    'model' => 'gpt-4o',
    'messages' => [
      [
        'role' => 'user',
        'content' => "Übersetze nach {$target_lang_name}: {$source_title}"
      ]
    ],
    'temperature' => 0.3, // Niedrig für konsistente Übersetzungen
  ]);

  // Body übersetzen (in Chunks bei langen Texten)
  $body_chunks = chunk_ai_text($source_body, 2000);
  $translated_chunks = [];

  foreach ($body_chunks as $chunk) {
    $chunk_response = $ai_provider->chat([
      'model' => 'gpt-4o',
      'messages' => [
        [
          'role' => 'system',
          'content' => "Du bist ein professioneller Übersetzer. Übersetze präzise nach {$target_lang_name}. Behalte HTML-Tags und Formatierung bei."
        ],
        [
          'role' => 'user',
          'content' => $chunk
        ]
      ],
      'temperature' => 0.3,
    ]);

    $translated_chunks[] = $chunk_response->getNormalized();
  }

  // Translation Node erstellen
  if ($node->hasTranslation($target_language)) {
    $translation = $node->getTranslation($target_language);
  }
  else {
    $translation = $node->addTranslation($target_language);
  }

  $translation->setTitle($title_response->getNormalized());
  $translation->set('body', [
    'value' => implode("\n\n", $translated_chunks),
    'format' => 'full_html',
  ]);

  $translation->save();

  return $translation;
}

/**
 * Text in AI-freundliche Chunks aufteilen.
 */
function chunk_ai_text($text, $max_chars = 2000) {
  // An Absätzen splitten
  $paragraphs = preg_split('/\n\n+/', $text);
  $chunks = [];
  $current_chunk = '';

  foreach ($paragraphs as $paragraph) {
    if (strlen($current_chunk) + strlen($paragraph) > $max_chars) {
      if ($current_chunk) {
        $chunks[] = $current_chunk;
        $current_chunk = '';
      }
    }

    $current_chunk .= ($current_chunk ? "\n\n" : '') . $paragraph;
  }

  if ($current_chunk) {
    $chunks[] = $current_chunk;
  }

  return $chunks;
}

Use Case 4: SEO Content Optimizer

Automated SEO Enhancement

<?php
namespace Drupal\mymodule\Service;

/**
 * SEO Optimizer Service using AI.
 */
class AiSeoOptimizer {

  protected $aiProvider;

  public function __construct($ai_provider) {
    $this->aiProvider = $ai_provider;
  }

  /**
   * Optimiere Content für SEO.
   */
  public function optimizeContent(Node $node, $target_keyword) {

    $original_body = $node->get('body')->value;

    $prompt = <<<PROMPT
SEO-Optimierung eines Artikels:

Original-Text:
{$original_body}

Ziel-Keyword: {$target_keyword}

Aufgaben:
1. Keyword natürlich in den Text einarbeiten (Dichte: 1-2%)
2. Variationen und Synonyme verwenden
3. Semantisch verwandte Begriffe hinzufügen
4. Lesbarkeit beibehalten
5. H2/H3 Überschriften optimieren
6. Formatierung mit HTML beibehalten

Gib den optimierten Text zurück.
PROMPT;

    $response = $this->aiProvider->chat([
      'model' => 'gpt-4o',
      'messages' => [
        ['role' => 'system', 'content' => 'Du bist ein SEO-Experte.'],
        ['role' => 'user', 'content' => $prompt],
      ],
      'temperature' => 0.6,
    ]);

    $optimized_body = $response->getNormalized();

    // Meta Title generieren
    $meta_title = $this->generateMetaTitle($node->getTitle(), $target_keyword);

    // Meta Description generieren
    $meta_desc = $this->generateMetaDescription($optimized_body, $target_keyword);

    // Strukturierte Daten vorschlagen
    $schema_markup = $this->generateSchemaMarkup($node, $optimized_body);

    return [
      'body' => $optimized_body,
      'meta_title' => $meta_title,
      'meta_description' => $meta_desc,
      'schema_markup' => $schema_markup,
    ];
  }

  /**
   * Generiere optimierten Meta Title.
   */
  protected function generateMetaTitle($current_title, $keyword) {
    $prompt = "Erstelle einen SEO-optimierten Meta-Title (max 60 Zeichen) " .
              "für den Titel '{$current_title}' mit Keyword '{$keyword}'.";

    $response = $this->aiProvider->chat([
      'model' => 'gpt-4o-mini',
      'messages' => [['role' => 'user', 'content' => $prompt]],
      'temperature' => 0.7,
    ]);

    return $response->getNormalized();
  }

  /**
   * Generiere Meta Description.
   */
  protected function generateMetaDescription($body_text, $keyword) {
    $summary = substr(strip_tags($body_text), 0, 500);

    $prompt = <<<PROMPT
Erstelle eine überzeugende Meta-Description (max 155 Zeichen):

Inhalt: {$summary}
Keyword: {$keyword}

Anforderungen:
- Enthält Keyword
- Call-to-Action
- Überzeugend
- Exakt unter 155 Zeichen
PROMPT;

    $response = $this->aiProvider->chat([
      'model' => 'gpt-4o-mini',
      'messages' => [['role' => 'user', 'content' => $prompt]],
      'temperature' => 0.8,
    ]);

    return $response->getNormalized();
  }

  /**
   * Generiere Schema.org JSON-LD.
   */
  protected function generateSchemaMarkup(Node $node, $body_text) {
    $summary = substr(strip_tags($body_text), 0, 300);

    $prompt = <<<PROMPT
Erstelle Schema.org JSON-LD Markup für einen Artikel:

Titel: {$node->getTitle()}
Zusammenfassung: {$summary}
Autor: {$node->getOwner()->getDisplayName()}
Datum: {$node->getCreatedTime()}

Verwende Schema.org/Article mit allen relevanten Properties.
Gib nur valides JSON zurück.
PROMPT;

    $response = $this->aiProvider->chat([
      'model' => 'gpt-4o-mini',
      'messages' => [['role' => 'user', 'content' => $prompt]],
      'temperature' => 0.3,
    ]);

    return $response->getNormalized();
  }
}

Use Case 5: Content Rewriting & Variations

A/B Testing Content Generator

<?php
/**
 * Erstelle Content-Variationen für A/B Testing.
 */
function generate_content_variations($original_text, $variations = 3) {
  $ai_provider = \Drupal::service('ai.provider');
  $results = [];

  $styles = [
    'emotional' => 'emotional und fesselnd',
    'factual' => 'sachlich und datenbasiert',
    'storytelling' => 'storytelling-orientiert',
    'concise' => 'prägnant und direkt',
  ];

  foreach (array_slice($styles, 0, $variations) as $key => $style) {
    $prompt = <<<PROMPT
Schreibe den folgenden Text neu im Stil: {$style}

Original:
{$original_text}

Anforderungen:
- Gleiche Kernaussage
- Gleiche Länge (±10%)
- Stil: {$style}
- Zielgruppe: Fachpublikum
- Deutsche Sprache
PROMPT;

    $response = $ai_provider->chat([
      'model' => 'gpt-4o-mini',
      'messages' => [['role' => 'user', 'content' => $prompt]],
      'temperature' => 0.9, // Höher für mehr Kreativität
    ]);

    $results[$key] = $response->getNormalized();
  }

  return $results;
}

Quality Control & Human Review

AI Content Checker

<?php
/**
 * Prüfe AI-generierten Content auf Qualität.
 */
function check_ai_content_quality($generated_text) {
  $ai_provider = \Drupal::service('ai.provider');

  $prompt = <<<PROMPT
Analysiere die Qualität dieses Textes:

{$generated_text}

Bewerte nach:
1. Grammatik & Rechtschreibung (0-10)
2. Kohärenz & Struktur (0-10)
3. Faktische Korrektheit (0-10)
4. SEO-Tauglichkeit (0-10)
5. Lesbarkeit (0-10)

Antworte im JSON-Format:
{
  "scores": {
    "grammar": 0-10,
    "coherence": 0-10,
    "factual": 0-10,
    "seo": 0-10,
    "readability": 0-10
  },
  "overall": 0-10,
  "issues": ["liste von problemen"],
  "suggestions": ["verbesserungsvorschläge"]
}
PROMPT;

  $response = $ai_provider->chat([
    'model' => 'gpt-4o',
    'messages' => [
      ['role' => 'system', 'content' => 'Du bist ein Content-Quality-Analyst.'],
      ['role' => 'user', 'content' => $prompt],
    ],
    'temperature' => 0.3,
  ]);

  return json_decode($response->getNormalized(), TRUE);
}

Human Review Workflow

<?php
/**
 * Workflow für menschliche Review von AI Content.
 */
function setup_ai_content_workflow() {
  // Moderation State setzen
  $node->set('moderation_state', 'ai_review');

  // Quality Check durchführen
  $quality = check_ai_content_quality($node->get('body')->value);

  // Bei niedriger Qualität: Auto-Reject
  if ($quality['overall'] < 6) {
    $node->set('moderation_state', 'draft');
    $node->set('field_review_notes', implode(', ', $quality['issues']));
  }

  // Bei hoher Qualität: Fast-Track
  if ($quality['overall'] >= 9) {
    $node->set('moderation_state', 'ready_for_publish');
  }

  // Editor benachrichtigen
  notify_content_editor($node, $quality);

  $node->save();
}

Performance Monitoring

<?php
/**
 * Track AI Content Generation Performance.
 */
function track_ai_generation_metrics($operation, $start_time, $tokens_used) {
  $duration = microtime(TRUE) - $start_time;

  \Drupal::database()->insert('ai_content_metrics')
    ->fields([
      'operation' => $operation,
      'duration' => $duration,
      'tokens_used' => $tokens_used,
      'cost_estimate' => calculate_cost($tokens_used),
      'timestamp' => time(),
    ])
    ->execute();
}

Fazit

AI-gestützte Content-Generierung in Drupal ist kein Zukunftsszenario mehr, sondern Production-Ready. Mit dem AI Module können Sie:

  • Skalierbare Content-Produktion aufbauen
  • SEO-optimierte Texte automatisch erstellen
  • Mehrsprachige Inhalte effizient generieren
  • Content-Qualität durch AI-Analysen verbessern

Wichtig bleibt die Balance zwischen Automatisierung und menschlicher Qualitätssicherung.


Interesse an AI-Content-Automatisierung für Ihre Drupal-Site? Kontakt: mail@stevenschulz.net oder 04037420859

Häufig gestellte Fragen (FAQ)

Kann AI-generierter Content für SEO schädlich sein?
Nein, wenn er richtig eingesetzt wird. Google bewertet Content nach Qualität, nicht nach Entstehungsart. Wichtig ist: Menschliche Review, einzigartiger Mehrwert, faktengeprüfter Inhalt und natürliche Keyword-Integration. AI-Content sollte als Basis dienen, die Sie verfeinern.
Wie automatisiere ich die Generierung von Produktbeschreibungen in Drupal?
Nutzen Sie ein Custom Migrate Process Plugin (AiProductDescription), das während des Product Imports automatisch überzeugende Beschreibungen generiert. Der AI-Provider erhält Produktname, Kategorie und Features und erstellt verkaufsfördernde Texte mit 150-200 Wörtern.
Welche Qualitätssicherung brauche ich für AI-generierten Content?
Implementieren Sie einen Hybrid-Workflow: AI generiert Content mit Moderation State 'needs_review', ein automatischer Quality Check bewertet Grammatik, Kohärenz und SEO-Tauglichkeit (0-10 Punkte). Bei Scores unter 6 erfolgt Auto-Reject, bei über 9 Fast-Track zur Publikation.
Wie erstelle ich Content-Variationen für A/B Testing?
Die Funktion generate_content_variations() generiert verschiedene Versionen eines Textes in unterschiedlichen Stilen (emotional, faktisch, storytelling, prägnant). Mit höherer Temperature (0.9) für mehr Kreativität bei gleicher Kernaussage - ideal für Conversion-Optimierung.
Was kostet die automatische Content-Generierung mit OpenAI?
Mit gpt-4o-mini zahlen Sie etwa $0.15 pro 1 Million Tokens. Ein 800-Wörter Blog-Post kostet ca. $0.002-0.005. Für 100 Artikel monatlich entstehen Kosten von nur $0.20-0.50 - ein Bruchteil der Kosten für menschliche Autoren.

Das könnte Sie auch interessieren

← Zurück zum Blog