Okay, diese Log-Einträge zeigen klar, dass die Gemini-API für die Social-Media-Posts nicht die erwartete Struktur mit START_NETWORK_... und END_NETWORK_... Blöcken liefert. Deshalb können die einzelnen Texte und Hashtags nicht geparst werden, und das Plugin greift auf die Fallback-Texte zurück. Mögliche Ursachen und Lösungsansätze: Gemini interpretiert den Prompt anders als erwartet: Obwohl der Prompt sehr spezifisch ist, könnte Gemini ihn gelegentlich (oder dauerhaft, wenn das Modellverhalten sich geändert hat) missverstehen und eine Antwort in einem anderen Format generieren. Lösungsversuch 1: Prompt-Anpassung – Vereinfachung oder Umformulierung. Versuche, den Teil des Prompts, der die Ausgabestruktur definiert, noch klarer oder anders zu formulieren. Manchmal hilft es, die Platzhalter {{NETZWERK_NAME_OBEN_IN_GROSSBUCHSTABEN_UND_MIT_UNTERSTRICH_STATT_SLASH}} durch tatsächliche Beispiele zu ersetzen, auch wenn das den Prompt länger macht. Eventuell ist der Prompt zu komplex geworden, und eine leichtere Variation wird besser verstanden. Modell-Update bei Gemini: Es ist möglich, dass das verwendete Gemini-Modell (z.B. gemini-1.5-flash) kürzlich ein Update erhalten hat, das sein Verhalten bei der Einhaltung komplexer Formatierungsanweisungen geändert hat. Zeichen im Prompt, die Gemini stören: Manchmal können bestimmte Sonderzeichen oder Formatierungen im Prompt die KI verwirren. Dein Prompt sieht aber auf den ersten Blick unproblematisch aus. Debugging-Schritte und Code-Anpassung: Schritt 1: Den genauen Output der Gemini-API loggen (wichtig!) Um zu sehen, was genau Gemini zurückliefert, wenn es die Struktur nicht einhält, ist es entscheidend, die komplette, unverarbeitete Antwort von Gemini für den Social-Media-Prompt zu loggen. In fccg_generate_social_media_post, direkt nach dem API-Aufruf: // ... $result = fccg_call_gemini_api($complex_prompt, 180, $preferred_model, $api_key_to_use); if (is_wp_error($result) || empty($result['content'])) { // ... Fehlerbehandlung bleibt gleich ... } else { $raw_output = trim($result['content']); // NEUES, DETAILLIERTES LOGGING DER ROHANTWORT: fccg_log_entry("Social Media API Komplette Roh-Antwort für ID {$post_id} (Modell: " . ($result['model'] ?? 'N/A') . "):\n>>>>>>>>>>\n" . $raw_output . "\n<<<<<<<<<<", 'debug'); // 'debug' oder 'info' // ... Rest der Parsing-Logik ... } // ... Lass dann einen neuen Beitrag generieren und schau dir diese Log-Ausgabe genau an. Das wird zeigen, in welchem Format Gemini antwortet, wenn es nicht die START_NETWORK_...-Blöcke verwendet. Schritt 2: Anpassung des Prompts (Experimentell) Basierend darauf, was du im Log siehst, können wir den Prompt anpassen. Hier sind ein paar Varianten, die du testen könntest (immer nur eine auf einmal): Variante A: Vereinfachte Platzhalter und explizitere Anweisung // In fccg_generate_social_media_post // ... $prompt_parts[] = "\nBitte formatiere deine Antwort GENAU wie folgt, mit exakt diesen Trennern für JEDES angeforderte Netzwerk. Ersetze nur den Inhalt innerhalb der eckigen Klammern:"; $prompt_parts[] = "START_NETWORK_FACEBOOK_OUTPUT"; // Konkreter Platzhalter $prompt_parts[] = "TEXT:[Hier der generierte Text für Facebook]"; $prompt_parts[] = "HASHTAGS:[Hier die kommaseparierten Hashtags für Facebook]"; $prompt_parts[] = "END_NETWORK_FACEBOOK_OUTPUT"; $prompt_parts[] = "\nSTART_NETWORK_TWITTER_X_THREADS_OUTPUT"; // Konkreter Platzhalter $prompt_parts[] = "TEXT:[Hier der generierte Text für Twitter/X/Threads]"; $prompt_parts[] = "HASHTAGS:[Hier die kommaseparierten Hashtags für Twitter/X/Threads]"; $prompt_parts[] = "END_NETWORK_TWITTER_X_THREADS_OUTPUT"; if (isset($networks_config['linkedin'])) { // Nur wenn LinkedIn angefordert wird $prompt_parts[] = "\nSTART_NETWORK_LINKEDIN_OUTPUT"; // Konkreter Platzhalter $prompt_parts[] = "TEXT:[Hier der generierte Text für LinkedIn]"; $prompt_parts[] = "HASHTAGS:[Hier die kommaseparierten Hashtags für LinkedIn]"; $prompt_parts[] = "END_NETWORK_LINKEDIN_OUTPUT"; } // ... // Dann im Parsing-Teil die $network_label_upper entsprechend anpassen: // $network_label_upper = strtoupper(str_replace(['/', ' '], '_', $details['prompt_name'])) . "_OUTPUT"; IGNORE_WHEN_COPYING_START content_copy download Use code with caution. PHP IGNORE_WHEN_COPYING_END Variante B: Weniger strikte Formatierung im Prompt, robustere Parsing-Logik (wenn Gemini die Blöcke oft ignoriert) Wenn Gemini die START_NETWORK_... Blöcke konsequent ignoriert, aber vielleicht immer noch für jedes Netzwerk einen Abschnitt generiert (z.B. mit "Facebook:", "Twitter:", "LinkedIn:" als Überschriften), dann müssten wir die Parsing-Logik in fccg_generate_social_media_post anpassen, um diese weniger strukturierten Antworten zu verarbeiten. Das ist aber aufwendiger und hängt stark davon ab, wie die "fehlerhafte" Antwort aussieht. Schritt 3: Code-Anpassung für das Parsing basierend auf den Logs Wenn du siehst, dass Gemini z.B. immer Facebook Text: [...] Facebook Hashtags: [...] ohne die START_NETWORK Blöcke liefert, müsste der Regex in der foreach ($networks_config as $net_key => $details) Schleife angepasst werden. Vorschlag für die aktuelle fccg_generate_social_media_post mit dem verbesserten Logging: function fccg_generate_social_media_post($post_id, $post_title, $text_for_prompt, $category_key = '', $preferred_model = null, $api_key_to_use = null) { $excerpt_for_social = wp_strip_all_tags(wp_trim_words($text_for_prompt, 50, '...')); $is_gutenacht_social = (strtolower($category_key) === 'gutenachtgeschichten'); $social_handle = "@Familienblog"; $blog_url_short = home_url(); $uniqueness_social_instruction = "Jede generierte Social-Media-Nachricht MUSS einen komplett eigenen Aufhänger (Hook) haben und sich in Tonalität und Call to Action deutlich von den anderen Nachrichten für unterschiedliche Netzwerke unterscheiden. Sei kreativ und vermeide Wiederholungen im Ansatz."; $fallback_text_default = "Neuer Artikel auf unserem Blog: " . $post_title . "! Schau vorbei für mehr Infos und Tipps. {$social_handle}"; $fallback_hashtags_default = "Familie,Eltern,Kinder,Blog,Neuigkeiten"; $networks_config = [ 'facebook' => ['prompt_name' => "Facebook", 'length_desc' => "einen etwas längeren, ansprechenden Text (ca. 2-4 Sätze)", 'cta_suggestion' => "Fordere klar zum Lesen des Artikels auf {$blog_url_short} und zum Liken/Teilen/Kommentieren an. Stelle eine Frage, um Interaktion zu fördern.", 'emoji_suggestion' => "Verwende 3-5 passende Emojis (z.B. 💖👨‍👩‍👧‍👦🎉).", 'hashtag_desc' => "5-8 relevante, breit gefächerte Hashtags"], 'twitter' => ['prompt_name' => "Twitter_X_Threads", 'length_desc' => "einen sehr kurzen, prägnanten Text (ideal unter 200 Zeichen, maximal 250 Zeichen, der Link zum Artikel wird später automatisch angefügt)", 'cta_suggestion' => "Starker Hook oder direkte Frage. Fordere zum Lesen des Artikels und zum Folgen von {$social_handle} auf.", 'emoji_suggestion' => "Verwende 2-4 passende Emojis (z.B. 🚀💡📣).", 'hashtag_desc' => "3-5 prägnante, ggf. trendige Hashtags"], 'linkedin' => ['prompt_name' => "LinkedIn", 'length_desc' => "einen professionellen, informativen Text (ca. 2-3 Sätze), der den Mehrwert betont", 'cta_suggestion' => "Fordere zum Lesen des vollständigen Artikels auf {$blog_url_short} für detaillierte Einblicke oder zur Diskussion auf.", 'emoji_suggestion' => "Verwende 1-2 dezente, professionelle Emojis (z.B. 🔗💡📈).", 'hashtag_desc' => "3-5 branchenspezifische oder themenrelevante Hashtags"], ]; if ($is_gutenacht_social) { $networks_config['facebook'] = ['prompt_name' => "Facebook", 'length_desc' => "einen kurzen, liebevollen Text (1-2 Sätze)", 'cta_suggestion' => "Lade zum Träumen und Lesen der Geschichte auf {$blog_url_short} ein. Erwähne {$social_handle}.", 'emoji_suggestion' => "Verwende 2-3 passende Emojis (z.B. ✨🌙🧸).", 'hashtag_desc' => "5-7 kindgerechte Hashtags"]; $networks_config['twitter'] = ['prompt_name' => "Twitter_X_Threads", 'length_desc' => "einen sehr kurzen, süßen Tweet (maximal 200 Zeichen, Link wird später angefügt)", 'cta_suggestion' => "CTA 'Süße Träume! ✨'. Erwähne {$social_handle}.", 'emoji_suggestion' => "Verwende 1-2 passende Emojis (z.B. 😴🌟).", 'hashtag_desc' => "2-4 kindgerechte Hashtags"]; unset($networks_config['linkedin']); $fallback_text_default = "Eine neue Gute-Nacht-Geschichte wartet auf euch: " . $post_title . " ✨ {$social_handle}"; $fallback_hashtags_default = "Gutenachtgeschichte,Kinderbuch,Vorlesen,Familienzeit,Träume"; } $prompt_parts = ["Generiere Social-Media-Posts für einen Blogbeitrag mit dem Titel \"{$post_title}\" und folgendem Inhalt (Auszug): \"{$excerpt_for_social}\". Die Zielgruppe sind Familien/Eltern. {$uniqueness_social_instruction}"]; $prompt_parts[] = "Erstelle spezifische Variationen für folgende Netzwerke mit den jeweiligen Anforderungen. Gib die Hashtags ohne das '#' Symbol aus, nur kommasepariert:"; foreach ($networks_config as $net_key => $details) { $prompt_parts[] = "\nNetzwerk: {$details['prompt_name']}"; $prompt_parts[] = "- Text: {$details['length_desc']}. {$details['cta_suggestion']} {$details['emoji_suggestion']}"; $prompt_parts[] = "- Hashtags: {$details['hashtag_desc']}."; } // WICHTIG: Den Platzhalter hier beibehalten, da er im Code referenziert wird. // Wenn du Variante A testest, musst du auch die $network_label_upper Logik unten anpassen. $prompt_parts[] = "\nStruktur der Ausgabe für JEDES Netzwerk (wiederhole diesen Block pro Netzwerk, ersetze {{NETZWERK_NAME_OBEN_IN_GROSSBUCHSTABEN_UND_MIT_UNTERSTRICH_STATT_SLASH}} mit dem jeweiligen Namen wie FACEBOOK oder TWITTER_X_THREADS):"; $prompt_parts[] = "START_NETWORK_{{NETZWERK_NAME_OBEN_IN_GROSSBUCHSTABEN_UND_MIT_UNTERSTRICH_STATT_SLASH}}"; $prompt_parts[] = "TEXT:[Hier der generierte Text für dieses Netzwerk]"; $prompt_parts[] = "HASHTAGS:[Hier die kommaseparierten Hashtags für dieses Netzwerk]"; $prompt_parts[] = "END_NETWORK_{{NETZWERK_NAME_OBEN_IN_GROSSBUCHSTABEN_UND_MIT_UNTERSTRICH_STATT_SLASH}}"; $complex_prompt = implode("\n", $prompt_parts); // Temporäres Logging des gesamten Prompts für Social Media // fccg_log_entry("Social Media Komplexer Prompt an API für ID {$post_id}:\n{$complex_prompt}", 'debug'); $result = fccg_call_gemini_api($complex_prompt, 180, $preferred_model, $api_key_to_use); if (is_wp_error($result) || empty($result['content'])) { $err_msg = is_wp_error($result) ? $result->get_error_message() : 'Leere API Antwort'; fccg_log_entry("❌ Fehler Komplexer Social Media Gen (ID {$post_id}): {$err_msg}. Speichere Fallback.", 'error'); foreach (array_keys($networks_config) as $network_key_for_meta) { update_post_meta($post_id, '_fccg_social_media_text_' . $network_key_for_meta, $fallback_text_default); update_post_meta($post_id, '_fccg_social_media_hashtags_' . $network_key_for_meta, $fallback_hashtags_default); } update_post_meta($post_id, '_fccg_social_media_text', $fallback_text_default); update_post_meta($post_id, '_fccg_social_media_hashtags', $fallback_hashtags_default); return ['text' => $fallback_text_default, 'hashtags' => $fallback_hashtags_default]; } else { $raw_output = trim($result['content']); // DETAILLIERTES LOGGING DER ROHANTWORT: fccg_log_entry("Social Media API Komplette Roh-Antwort für ID {$post_id} (Modell: " . ($result['model'] ?? 'N/A') . "):\n>>>>>>>>>>\n" . $raw_output . "\n<<<<<<<<<<", 'debug'); $all_texts_found = true; foreach ($networks_config as $net_key => $details) { $network_label_upper = strtoupper(str_replace(['/', ' '], '_', $details['prompt_name'])); // Wenn du Variante A des Prompts testest, ändere dies zu: // $network_label_upper = strtoupper(str_replace(['/', ' '], '_', $details['prompt_name'])) . "_OUTPUT"; $pattern = "/START_NETWORK_{$network_label_upper}\s*TEXT:\[(.*?)\]\s*HASHTAGS:\[(.*?)\]\s*END_NETWORK_{$network_label_upper}/s"; if (preg_match($pattern, $raw_output, $matches)) { $specific_text = trim($matches[1]); $specific_hashtags_str = trim(str_replace('#', '', $matches[2])); if (!empty($specific_text)) { $specific_text = trim(str_ireplace(["@[DeinSocialMediaHandle]", "[DeinSocialMediaHandle]"], $social_handle, $specific_text)); update_post_meta($post_id, '_fccg_social_media_text_' . $net_key, $specific_text); update_post_meta($post_id, '_fccg_social_media_hashtags_' . $net_key, $specific_hashtags_str); fccg_log_entry("✅ Social Media für {$details['prompt_name']} (ID {$post_id}) gespeichert. Text: ".mb_substr($specific_text,0,50)."... H: {$specific_hashtags_str}", 'info'); if ($net_key === 'facebook') { update_post_meta($post_id, '_fccg_social_media_text', $specific_text); update_post_meta($post_id, '_fccg_social_media_hashtags', $specific_hashtags_str); } } else { fccg_log_entry("⚠️ Kein TEXT für {$details['prompt_name']} (ID {$post_id}) im Block gefunden. Pattern: {$pattern}. Block: ".esc_html(mb_substr($matches[0] ?? 'NOT FOUND',0,200)), 'warning'); update_post_meta($post_id, '_fccg_social_media_text_' . $net_key, $fallback_text_default); update_post_meta($post_id, '_fccg_social_media_hashtags_' . $net_key, $fallback_hashtags_default); $all_texts_found = false; } } else { fccg_log_entry("⚠️ Konnte Block START_NETWORK_{$network_label_upper} für {$details['prompt_name']} (ID {$post_id}) nicht finden. Nutze Fallback.", 'warning'); update_post_meta($post_id, '_fccg_social_media_text_' . $net_key, $fallback_text_default); update_post_meta($post_id, '_fccg_social_media_hashtags_' . $net_key, $fallback_hashtags_default); $all_texts_found = false; } } if (empty(get_post_meta($post_id, '_fccg_social_media_text', true))) { $fb_text = get_post_meta($post_id, '_fccg_social_media_text_facebook', true); update_post_meta($post_id, '_fccg_social_media_text', $fb_text ?: $fallback_text_default); update_post_meta($post_id, '_fccg_social_media_hashtags', get_post_meta($post_id, '_fccg_social_media_hashtags_facebook', true) ?: $fallback_hashtags_default); } if (!$all_texts_found) { fccg_log_entry("Einige Social Media Texte konnten nicht korrekt geparst werden für ID {$post_id}. Fallbacks wurden verwendet.", 'warning'); } } return ['text' => get_post_meta($post_id, '_fccg_social_media_text', true), 'hashtags' => get_post_meta($post_id, '_fccg_social_media_hashtags', true)]; }