{
  "name": "18 \u2014 Google Business Auto-Posts",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 10 * * 2,5"
            }
          ]
        }
      },
      "id": "trigger-dienstag-freitag",
      "name": "Di+Fr 10:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        300
      ],
      "notes": "Dienstag und Freitag 10:00 \u2014 optimale Posting-Zeiten f\u00fcr lokale Businesses"
    },
    {
      "parameters": {
        "jsCode": "// Post-Kategorien rotieren\nconst categories = [\n  {\n    type: 'angebot',\n    prompt: 'Erstelle einen Google Business Post f\u00fcr ein aktuelles Angebot von Meck-Pomm Elektronik. Themen: Smartphone-Reparatur, Laptop-Service, Website-Redesign oder IT-Dienstleistung. W\u00e4hle ein konkretes Angebot mit Preis. Beispiel: Display-Reparatur ab 49\u20ac, Website-Check kostenlos, Laptop-Reinigung 29\u20ac.',\n    cta: 'CALL'\n  },\n  {\n    type: 'tipp',\n    prompt: 'Erstelle einen hilfreichen Google Business Post mit einem IT-Tipp f\u00fcr Kleinunternehmer. Themen: Website-Sicherheit, Handy-Pflege, Datensicherung, DSGVO-Basics, Google Business optimieren. Kurz, praktisch, sofort umsetzbar.',\n    cta: 'LEARN_MORE'\n  },\n  {\n    type: 'produkt',\n    prompt: 'Erstelle einen Google Business Post \u00fcber ein Produkt/Service von Meck-Pomm Elektronik. Themen: Gebrauchte Laptops, Smartphone-Zubeh\u00f6r, KI-gest\u00fctzte Website-Erstellung, IT-Wartungsvertr\u00e4ge. Betone den lokalen Vorteil.',\n    cta: 'ORDER'\n  },\n  {\n    type: 'behind_scenes',\n    prompt: 'Erstelle einen authentischen Google Business Post der Einblick in den Arbeitsalltag von Meck-Pomm Elektronik gibt. Themen: Aktuelle Reparatur, neues Tool im Einsatz, Kundenfeedback, lokales Event. Pers\u00f6nlich und nahbar.',\n    cta: 'CALL'\n  }\n];\n\n// Kategorie basierend auf Kalenderwoche rotieren\nconst now = new Date();\nconst startOfYear = new Date(now.getFullYear(), 0, 1);\nconst weekNumber = Math.ceil(((now - startOfYear) / 86400000 + startOfYear.getDay() + 1) / 7);\nconst dayOfWeek = now.getDay(); // 2=Di, 5=Fr\nconst index = (weekNumber * 2 + (dayOfWeek === 5 ? 1 : 0)) % categories.length;\nconst category = categories[index];\n\nreturn [{\n  json: {\n    category: category.type,\n    prompt: category.prompt,\n    cta_type: category.cta,\n    week_number: weekNumber,\n    post_date: now.toLocaleDateString('de-DE')\n  }\n}];"
      },
      "id": "select-category",
      "name": "Post-Kategorie w\u00e4hlen",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "notes": "Rotiert durch 4 Kategorien: Angebot, Tipp, Produkt, Behind-the-Scenes"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://100.86.93.109:8317/v1/chat/completions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"kimi-k2.5\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"Du schreibst Google Business Posts f\u00fcr Meck-Pomm Elektronik, einen IT-Dienstleister und Elektronik-Reparaturbetrieb in Mecklenburg-Vorpommern (Krakow am See). Brand Voice: Technisch kompetent aber verst\u00e4ndlich, direkt und ehrlich, lokal verwurzelt, pragmatisch. VERBOTEN: Hype-W\u00f6rter (revolution\u00e4r, disruptiv, Premium), Anglizismen ohne Not, Ausrufezeichen-Spam. FORMAT: Max 150 W\u00f6rter. Erster Satz = Hook. Letzter Satz = klarer Call-to-Action. Keine Emojis im Flie\u00dftext, max 2 am Ende erlaubt. Schreibe wie ein kompetenter Nachbar, nicht wie eine Werbeagentur.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"{{ $json.prompt }}\\n\\nKategorie: {{ $json.category }}\\nDatum: {{ $json.post_date }}\\n\\nAntworte NUR mit dem Post-Text, keine Erkl\u00e4rungen.\"\n    }\n  ],\n  \"max_tokens\": 400,\n  \"temperature\": 0.8\n}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "ai-generate-post",
      "name": "CLIProxyAPI: Post generieren",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        300
      ],
      "continueOnFail": true,
      "notes": "CLIProxyAPI auf NAS (:8317) generiert Google Business Post mit Brand Voice"
    },
    {
      "parameters": {
        "jsCode": "const item = $input.item.json;\nconst prev = $('Post-Kategorie w\u00e4hlen').item.json;\n\nlet postText = '';\ntry {\n  const choices = item.choices || [];\n  postText = choices[0]?.message?.content || '';\n  postText = postText.trim();\n} catch (e) {\n  postText = '';\n}\n\n// Fallback-Posts wenn AI nicht verf\u00fcgbar\nconst fallbacks = {\n  'angebot': 'Smartphone-Display kaputt? Bei Meck-Pomm Elektronik reparieren wir die meisten Displays innerhalb von 60 Minuten. Kostenvoranschlag ist immer kostenlos. Einfach vorbeikommen oder anrufen.',\n  'tipp': 'Schneller IT-Tipp: Sichern Sie Ihre wichtigen Daten regelm\u00e4\u00dfig auf einer externen Festplatte oder in der Cloud. Ein Festplattenausfall kommt oft ohne Vorwarnung. Wir beraten Sie gerne zur besten L\u00f6sung f\u00fcr Ihren Bedarf.',\n  'produkt': 'Gebrauchte Laptops mit Garantie \u2014 bei uns bekommen Sie gepr\u00fcfte Ger\u00e4te zu fairen Preisen. Jedes Ger\u00e4t wird gereinigt, getestet und mit frischem System aufgesetzt. Ideal f\u00fcr B\u00fcro, Schule oder zu Hause.',\n  'behind_scenes': 'Heute im Werkstatt-Alltag: Laptop-Reinigung und SSD-Upgrade. Aus einem langsamen 5 Jahre alten Ger\u00e4t wird wieder ein flotter Arbeitsrechner. Manchmal braucht es keine neue Hardware \u2014 nur die richtige Pflege.'\n};\n\nif (!postText || postText.length < 30) {\n  postText = fallbacks[prev.category] || fallbacks['tipp'];\n}\n\n// Post auf 1500 Zeichen begrenzen (Google Business Limit)\nif (postText.length > 1500) {\n  postText = postText.substring(0, 1497) + '...';\n}\n\nreturn [{\n  json: {\n    ...prev,\n    post_text: postText,\n    post_length: postText.length,\n    ai_generated: postText.length > 30 && !Object.values(fallbacks).includes(postText)\n  }\n}];"
      },
      "id": "parse-post",
      "name": "Post parsen + Fallback",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        300
      ],
      "notes": "Parst AI Response, 1500-Zeichen-Limit, Fallback-Templates pro Kategorie"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://mybusiness.googleapis.com/v4/accounts/{{ $env.GOOGLE_BUSINESS_ACCOUNT_ID || 'ACCOUNT_ID' }}/locations/{{ $env.GOOGLE_BUSINESS_LOCATION_ID || 'LOCATION_ID' }}/localPosts",
        "authentication": "oAuth2Api",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"languageCode\": \"de\",\n  \"summary\": \"{{ $json.post_text.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\",\n  \"topicType\": \"STANDARD\",\n  \"callToAction\": {\n    \"actionType\": \"{{ $json.cta_type }}\",\n    \"url\": \"https://meckpomm-elektronik.de\"\n  }\n}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "google-business-post",
      "name": "Google Business: Post ver\u00f6ffentlichen",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        200
      ],
      "credentials": {
        "oAuth2Api": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true,
      "notes": "Google Business Profile API. VORAUSSETZUNG: OAuth2 Credentials + API aktiviert in Google Cloud Console (Project: 95068514069)"
    },
    {
      "parameters": {
        "jsCode": "const item = $input.item.json;\nconst post = $('Post parsen + Fallback').item.json;\n\n// Pr\u00fcfe ob Google Business Post erfolgreich war\nconst success = item.name && !item.error;\n\nreturn [{\n  json: {\n    ...post,\n    google_posted: success,\n    google_response: success ? item.name : (item.error || item.message || 'API nicht verf\u00fcgbar'),\n    needs_discord_fallback: !success\n  }\n}];"
      },
      "id": "check-google-result",
      "name": "Google API Ergebnis pr\u00fcfen",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        200
      ],
      "notes": "Pr\u00fcft ob Google Business Post erfolgreich war"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.DISCORD_WEBHOOK_BUSINESS || 'https://discord.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN' }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"content\": null,\n  \"embeds\": [{\n    \"title\": \"{{ $json.google_posted ? '\u2705 Google Business Post ver\u00f6ffentlicht' : '\u26a0\ufe0f Google Business Post \u2014 manuell posten!' }}\",\n    \"description\": \"**Kategorie:** {{ $json.category }}\\n**Datum:** {{ $json.post_date }}\\n{{ $json.google_posted ? '' : '**Grund:** ' + $json.google_response + '\\\\n\\\\n' }}**Post-Text:**\\n{{ $json.post_text.substring(0, 800) }}\",\n    \"color\": {{ $json.google_posted ? 3066993 : 16776960 }},\n    \"footer\": {\n      \"text\": \"{{ $json.ai_generated ? 'AI-generiert' : 'Fallback-Template' }} | {{ $json.post_length }} Zeichen\"\n    },\n    \"timestamp\": \"{{ new Date().toISOString() }}\"\n  }]\n}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "discord-notification",
      "name": "Discord: Post-Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1440,
        200
      ],
      "continueOnFail": true,
      "notes": "Discord Notification: Erfolg oder Fallback-Hinweis mit Post-Text zum manuellen Posten"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.DISCORD_WEBHOOK_ALERTS || 'https://discord.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN' }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"content\": null,\n  \"embeds\": [{\n    \"title\": \"\ud83d\udd34 Google Business Autoposter \u2014 Fehler\",\n    \"description\": \"**Fehler:** CLIProxyAPI oder Post-Generierung fehlgeschlagen.\\n\\nWorkflow konnte keinen Post erstellen. Bitte manuell pr\u00fcfen.\",\n    \"color\": 15158332,\n    \"timestamp\": \"{{ new Date().toISOString() }}\"\n  }]\n}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "discord-error",
      "name": "Discord: Fehler melden",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        540
      ],
      "notes": "Discord Alert bei komplettem Workflow-Fehler"
    },
    {
      "parameters": {
        "jsCode": "const item = $input.item.json;\n\n// CLIProxyAPI Error Check\nif (item.error || (!item.choices && !item.id)) {\n  return [{\n    json: {\n      error: true,\n      message: item.error || item.message || 'CLIProxyAPI nicht erreichbar'\n    }\n  }];\n}\n\nreturn [{ json: { error: false } }];"
      },
      "id": "error-check-ai",
      "name": "Error Check: AI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        540
      ],
      "notes": "Pr\u00fcft ob CLIProxyAPI erreichbar und Antwort g\u00fcltig"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "is-error",
              "leftValue": "={{ $json.error }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ]
        }
      },
      "id": "filter-error",
      "name": "Filter: AI Fehler?",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        600,
        680
      ]
    }
  ],
  "connections": {
    "Di+Fr 10:00": {
      "main": [
        [
          {
            "node": "Post-Kategorie w\u00e4hlen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post-Kategorie w\u00e4hlen": {
      "main": [
        [
          {
            "node": "CLIProxyAPI: Post generieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CLIProxyAPI: Post generieren": {
      "main": [
        [
          {
            "node": "Post parsen + Fallback",
            "type": "main",
            "index": 0
          },
          {
            "node": "Error Check: AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post parsen + Fallback": {
      "main": [
        [
          {
            "node": "Google Business: Post ver\u00f6ffentlichen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Business: Post ver\u00f6ffentlichen": {
      "main": [
        [
          {
            "node": "Google API Ergebnis pr\u00fcfen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google API Ergebnis pr\u00fcfen": {
      "main": [
        [
          {
            "node": "Discord: Post-Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Check: AI": {
      "main": [
        [
          {
            "node": "Filter: AI Fehler?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: AI Fehler?": {
      "main": [
        [
          {
            "node": "Discord: Fehler melden",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "Europe/Berlin",
    "saveManualExecutions": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "tags": [
    {
      "name": "revenue"
    },
    {
      "name": "marketing"
    },
    {
      "name": "google-business"
    }
  ]
}