Generación automática semanal de copias de presentaciones de resumen de marketing con Claude AI, GoMarble MCP y Google Slides

Intermedio

Este es unDocument Extraction, Multimodal AIflujo de automatización del dominio deautomatización que contiene 15 nodos.Utiliza principalmente nodos como Set, Code, Gmail, GoogleDrive, HttpRequest. Automatizar informes semanales de anuncios de Meta con Claude AI, GoMarble MCP y Google Slides

Requisitos previos
  • Cuenta de Google y credenciales de API de Gmail
  • Credenciales de API de Google Drive
  • Pueden requerirse credenciales de autenticación para la API de destino
  • Clave de API de Anthropic
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "AmaZWuAXZJlrGq5l",
  "meta": {
    "instanceId": "07ccff49d71cc6b20dddb867ba4ad10dc1f2bd4ad81c28a9330420f0a4ac0b51",
    "templateCredsSetupCompleted": true
  },
  "name": "Copy ofAutomate Weekly Marketing Summary Deck with Claude AI, GoMarble MCP & Google Slides",
  "tags": [],
  "nodes": [
    {
      "id": "4bf29e91-9786-4035-9cae-c795795aded5",
      "name": "Agente de IA",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        580,
        -40
      ],
      "parameters": {
        "text": "={{ $json['Report Prompt'] }}",
        "options": {
          "systemMessage": "You are a senior digital marketing professional. You MUST always return exactly 5 slides in your JSON response. There should be no made up data or hallucination, but if insufficient data exists for a slide, use placeholder text like 'Data pending analysis' or 'No significant changes this period'."
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "97d9bdf1-4758-4222-b05f-4544e8e64fcc",
      "name": "Activador por programación",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": ":alarm_clock: Runs every Monday at 8 AM - adjust schedule as needed",
      "position": [
        100,
        -40
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ed8dddf4-fe74-49b4-922e-a390c53a03d4",
      "name": "GoMarble MCP",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "notes": ":closed_lock_with_key: Add your GoMarble Bearer token - get it from https://www.gomarble.ai/docs/connect-to-n8n",
      "position": [
        800,
        160
      ],
      "parameters": {
        "sseEndpoint": "https://apps.gomarble.ai/mcp-api/sse",
        "authentication": "bearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "6F65J7hlA4wzSeid",
          "name": "Bearer Auth account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "21fa31be-5754-4917-bd6b-20862d3ea4bc",
      "name": "Descargar archivo",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1780,
        -40
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$json.presentationId}}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "daPp0U6XEYaYQnlD",
          "name": "Google Drive account 2"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "5a805b50-3ae4-4488-9536-e3a569602fd4",
      "name": "Anthropic Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        520,
        160
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-20250514",
          "cachedResultName": "Claude 4 Sonnet"
        },
        "options": {}
      },
      "credentials": {
        "anthropicApi": {
          "id": "XMYEac7S3M6Hi7I5",
          "name": "Anthropic account"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "381eafea-79d6-46ed-b0cb-8d0802f83e9a",
      "name": "Enviar correo",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1940,
        -40
      ],
      "webhookId": "be82cd6b-8d18-4459-9b02-9ad01db01d38",
      "parameters": {
        "sendTo": "amancliff1@gmail.com",
        "message": "=Here is the Weekly Ad Performance Summary Deck - {{ $now.format('MM-DD') }}\".",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Weekly Summary Deck - {{ $now.format('MM-DD') }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "NMqbcdXNnH8EIv8G",
          "name": "Gmail account 7"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "13fde168-5855-4509-8490-2dac61abd7f1",
      "name": "Prompt de informe",
      "type": "n8n-nodes-base.set",
      "notes": "🔧 EDIT THIS NODE to change:\n• Account Name & ID\n• Email Recipients\n• Report Settings",
      "position": [
        420,
        -40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f2864549-d51c-4aad-b1cf-9a731e86b816",
              "name": "=Report Prompt",
              "type": "string",
              "value": "=You are a **senior performance‑marketing analyst**.\n\nVoice: sharp, concise, insight‑driven (no fluff, no marketing hype).  \nGoal: craft a weekly digest that a busy CMO can scan in < 3 min and act on immediately.  \n\nAd Account: {{ $json.accountName }}.\nTime Period: last 7 days  \n\n---\n\nCALL TOOL  \nUse **GoMarble MCP** with:  \n{\n  \"period\": \"last_7_days\"\n}  \nIt returns JSON metrics for Meta Ads.\n\n---\n\nAFTER the tool result is returned, you MUST output exactly ONE valid JSON object with EXACTLY 5 slides—nothing else:\n\n{\n  \"slides\": [\n    {\n      \"title\": \"Executive Snapshot\",\n      \"body\": \"<3‑line paragraph>  ▸ One‑sentence topline: combined spend, revenue, ROAS, and WoW % change.\\n▸ One‑sentence highlight of the biggest win.\\n▸ One‑sentence note on the main risk / action gap.\"\n    },\n    {\n      \"title\": \"Channel KPIs\",\n      \"tableData\": {\n        \"Spend\": \"$X,XXX\",\n        \"Impressions\": \"XXX,XXX\",\n        \"Clicks\": \"X,XXX\",\n        \"CTR\": \"X.XX%\",\n        \"CPC\": \"$X.XX\",\n        \"Conversions\": \"XX\",\n        \"CPA\": \"$XXX\",\n        \"Revenue\": \"$X,XXX\",\n        \"ROAS\": \"X.XX\",\n        \"WoW Change\": \"+/-XX%\"\n      }\n    },\n    {\n      \"title\": \"Top Campaigns\",\n      \"body\": \"<bullet list of the single best campaign per platform with why it won (1‑sentence each)>\"\n    },\n    {\n      \"title\": \"Under‑performers\",\n      \"body\": \"<bullet list of key weak campaigns with brief reason & WoW drop (1‑sentence each)>\"\n    },\n    {\n      \"title\": \"Action Recos\",\n      \"body\": \"<2‑3 crisp, prioritised recommendations the team should execute next week>\"\n    }\n  ]\n}\n\nCRITICAL RULES  \n– Return ONLY JSON (no Markdown fences, no explanations).  \n– EXACTLY 5 slide objects - NO MORE, NO LESS. This is mandatory.\n– For Channel KPIs: Use \"tableData\" object with key-value pairs for metrics (no pipe separators)\n– Use \\n for line breaks and keep sections tight and scannable\n– Keep each \"body\" < 120 words; use \\n for line breaks.  \n– Do NOT include any keys other than \"slides\".\n– The JSON must be valid and parseable.\n– Count your slides before responding - there must be exactly 5."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8ca128ec-4f51-4d38-9c3e-bbcff815e765",
      "name": "Crear presentación",
      "type": "n8n-nodes-base.httpRequest",
      "notes": ":bar_chart: Creates empty presentation",
      "position": [
        1080,
        -40
      ],
      "parameters": {
        "url": "https://slides.googleapis.com/v1/presentations",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"title\": \"Weekly Ad Report – {{ $now.format('MM-DD') }}\"\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "credentials": {
        "googleSlidesOAuth2Api": {
          "id": "gSaMa5Jnq7KRBH8v",
          "name": "Google Slides account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8f85ce4e-ac53-45b3-9b59-0052787abebd",
      "name": "Cuenta de anuncios",
      "type": "n8n-nodes-base.set",
      "notes": "🔧 EDIT THIS NODE to change:\n• Account Name & ID\n• Email Recipients\n• Report Settings",
      "position": [
        260,
        -40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "account-name",
              "name": "accountName",
              "type": "string",
              "value": "Long Surf"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ed8739ef-8efb-466b-8ca6-99548c809e66",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        -180
      ],
      "parameters": {
        "width": 220,
        "height": 100,
        "content": "Please add the name of the Facebook ad account in the node below for which you need the summary deck."
      },
      "typeVersion": 1
    },
    {
      "id": "632111c0-3c1e-42cb-b605-83f39d55bb0d",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        -180
      ],
      "parameters": {
        "width": 200,
        "height": 100,
        "content": "Please add the email ID in the node below to which you want the summary deck sent."
      },
      "typeVersion": 1
    },
    {
      "id": "7319e6ac-e678-4bcb-b0ab-6648490e5cf0",
      "name": "Validar salida de diapositivas",
      "type": "n8n-nodes-base.code",
      "notes": ":lock: GUARANTEES exactly 5 slides - no more, no less",
      "position": [
        900,
        -40
      ],
      "parameters": {
        "jsCode": "console.log('Raw AI output:', $json.output);\n\ntry {\n  let jsonString = $json.output;\n  \n  // Remove markdown code fences if present\n  if (jsonString.includes('```json')) {\n    console.log('Removing markdown fences');\n    jsonString = jsonString.replace(/```json\\n?/g, '').replace(/```\\n?$/g, '');\n  }\n  \n  // Remove any leading \"json\\n\" or similar\n  jsonString = jsonString.replace(/^json\\n/g, '');\n  \n  // Clean up any extra whitespace\n  jsonString = jsonString.trim();\n  \n  console.log('Cleaned JSON string:', jsonString.substring(0, 200) + '...');\n  \n  const output = JSON.parse(jsonString);\n  console.log(`Successfully parsed! Found ${output.slides.length} slides`);\n  \n  // Return the slides directly from AI (now with tableData support)\n  return [{ json: { slides: output.slides } }];\n  \n} catch (e) {\n  console.error('JSON parsing failed:', e.message);\n  console.log('Attempting manual extraction...');\n  \n  // Try to extract JSON from between { and }\n  const match = $json.output.match(/\\{[\\s\\S]*\\}/);\n  if (match) {\n    try {\n      const output = JSON.parse(match[0]);\n      console.log('Manual extraction successful!');\n      return [{ json: { slides: output.slides } }];\n    } catch (e2) {\n      console.log('Manual extraction also failed');\n    }\n  }\n  \n  // Last resort: return fallback with table structure for Channel KPIs\n  const fallbackSlides = [\n    { \n      title: \"Executive Snapshot\", \n      body: \"Weekly performance data is currently being processed. Report will be available shortly.\" \n    },\n    { \n      title: \"Channel KPIs\", \n      tableData: {\n        \"Spend\": \"Data pending\",\n        \"Impressions\": \"Data pending\",\n        \"Clicks\": \"Data pending\",\n        \"CTR\": \"Data pending\",\n        \"CPC\": \"Data pending\",\n        \"Conversions\": \"Data pending\",\n        \"CPA\": \"Data pending\",\n        \"Revenue\": \"Data pending\",\n        \"ROAS\": \"Data pending\",\n        \"WoW Change\": \"Data pending\"\n      }\n    },\n    { \n      title: \"Top Campaigns\", \n      body: \"Campaign performance analysis is in progress. Top-performing campaigns will be highlighted once data processing is complete.\" \n    },\n    { \n      title: \"Under-performers\", \n      body: \"Performance analysis not available at this time. Underperforming campaigns will be identified in the next report.\" \n    },\n    { \n      title: \"Action Recos\", \n      body: \"Strategic recommendations will be provided once performance data analysis is complete. Please check the next scheduled report.\" \n    }\n  ];\n  \n  return [{ json: { slides: fallbackSlides } }];\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "7a17068d-a6ae-46e5-9b37-3c5157291bf1",
      "name": "Formatear datos de diapositivas",
      "type": "n8n-nodes-base.code",
      "notes": ":wrench: Prepares the batch request with slide data",
      "position": [
        1440,
        -40
      ],
      "parameters": {
        "jsCode": "// Get the data from the Combine Data node\nconst presentationId = $json.presentationId;\nconst slides = $json.slides;\n\nconst requests = [\n  // Delete the default slide first\n  {\n    deleteObject: { objectId: 'p' }\n  }\n];\n\n// Create exactly 5 slides with content\nslides.forEach((slide, index) => {\n  const slideId = `slide_${index + 1}`;\n  const titleId = `${slideId}_title`;\n  \n  // Create slide\n  requests.push({\n    createSlide: {\n      objectId: slideId,\n      slideLayoutReference: { predefinedLayout: 'TITLE_AND_BODY' },\n      placeholderIdMappings: [\n        { layoutPlaceholder: { type: 'TITLE', index: 0 }, objectId: titleId },\n        { layoutPlaceholder: { type: 'BODY', index: 0 }, objectId: `${slideId}_body` }\n      ]\n    }\n  });\n  \n  // Add title\n  requests.push({\n    insertText: { objectId: titleId, insertionIndex: 0, text: slide.title }\n  });\n  \n  // Handle Channel KPIs slide with table\n  if (slide.title === \"Channel KPIs\" && slide.tableData) {\n    const tableId = `${slideId}_table`;\n    \n    // Create table (2 columns, 10 rows for the metrics)\n    requests.push({\n      createTable: {\n  objectId: tableId,\n  elementProperties: {\n    pageObjectId: slideId,\n    size: { width: { magnitude: 350, unit: 'PT' }, height: { magnitude: 200, unit: 'PT' } },\n    transform: {\n      scaleX: 1, scaleY: 1, translateX: 185, translateY: 80, unit: 'PT'\n    }\n  },\n  rows: 10,\n  columns: 2\n}\n    });\n    \n    // Populate table with data\n    const metrics = Object.entries(slide.tableData);\n    metrics.forEach(([metric, value], rowIndex) => {\n      // Insert metric name in first column\n      requests.push({\n        insertText: {\n          objectId: tableId,\n          cellLocation: { rowIndex: rowIndex, columnIndex: 0 },\n          insertionIndex: 0,\n          text: metric\n        }\n      });\n      \n      // Insert metric value in second column\n      requests.push({\n        insertText: {\n          objectId: tableId,\n          cellLocation: { rowIndex: rowIndex, columnIndex: 1 },\n          insertionIndex: 0,\n          text: value\n        }\n      });\n    });\n    \n  } else {\n    // For all other slides, use regular text insertion\n    const bodyId = `${slideId}_body`;\n    requests.push({\n      insertText: { objectId: bodyId, insertionIndex: 0, text: slide.body }\n    });\n  }\n});\n\nreturn [{\n  json: {\n    presentationId: presentationId,\n    batchUpdateBody: { requests: requests }\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "cd89420c-20be-4d70-b4b3-2b7fc0a80315",
      "name": "Construir presentación",
      "type": "n8n-nodes-base.httpRequest",
      "notes": ":page_facing_up: Executes the batch update to create all slides",
      "position": [
        1600,
        -40
      ],
      "parameters": {
        "url": "=https://slides.googleapis.com/v1/presentations/{{$json.presentationId}}:batchUpdate",
        "method": "POST",
        "options": {},
        "jsonBody": "={{JSON.stringify($json.batchUpdateBody)}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "credentials": {
        "googleSlidesOAuth2Api": {
          "id": "gSaMa5Jnq7KRBH8v",
          "name": "Google Slides account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "27755c4f-b75f-45c8-a674-21b3826082e9",
      "name": "Fusionar información de presentación",
      "type": "n8n-nodes-base.set",
      "notes": ":link: Combines presentation ID with slide data",
      "position": [
        1260,
        -40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "presentation-id",
              "name": "presentationId",
              "type": "string",
              "value": "={{$json.presentationId}}"
            },
            {
              "id": "slides-data",
              "name": "slides",
              "type": "array",
              "value": "={{$items('Validate slide output')[0].json.slides}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6f834adc-d3d9-466e-8f9b-36668904af1f",
  "connections": {
    "4bf29e91-9786-4035-9cae-c795795aded5": {
      "main": [
        [
          {
            "node": "7319e6ac-e678-4bcb-b0ab-6648490e5cf0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8f85ce4e-ac53-45b3-9b59-0052787abebd": {
      "main": [
        [
          {
            "node": "13fde168-5855-4509-8490-2dac61abd7f1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ed8dddf4-fe74-49b4-922e-a390c53a03d4": {
      "ai_tool": [
        [
          {
            "node": "4bf29e91-9786-4035-9cae-c795795aded5",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "21fa31be-5754-4917-bd6b-20862d3ea4bc": {
      "main": [
        [
          {
            "node": "381eafea-79d6-46ed-b0cb-8d0802f83e9a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "13fde168-5855-4509-8490-2dac61abd7f1": {
      "main": [
        [
          {
            "node": "4bf29e91-9786-4035-9cae-c795795aded5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "97d9bdf1-4758-4222-b05f-4544e8e64fcc": {
      "main": [
        [
          {
            "node": "8f85ce4e-ac53-45b3-9b59-0052787abebd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7a17068d-a6ae-46e5-9b37-3c5157291bf1": {
      "main": [
        [
          {
            "node": "cd89420c-20be-4d70-b4b3-2b7fc0a80315",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "cd89420c-20be-4d70-b4b3-2b7fc0a80315": {
      "main": [
        [
          {
            "node": "21fa31be-5754-4917-bd6b-20862d3ea4bc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8ca128ec-4f51-4d38-9c3e-bbcff815e765": {
      "main": [
        [
          {
            "node": "27755c4f-b75f-45c8-a674-21b3826082e9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5a805b50-3ae4-4488-9536-e3a569602fd4": {
      "ai_languageModel": [
        [
          {
            "node": "4bf29e91-9786-4035-9cae-c795795aded5",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "7319e6ac-e678-4bcb-b0ab-6648490e5cf0": {
      "main": [
        [
          {
            "node": "8ca128ec-4f51-4d38-9c3e-bbcff815e765",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "27755c4f-b75f-45c8-a674-21b3826082e9": {
      "main": [
        [
          {
            "node": "7a17068d-a6ae-46e5-9b37-3c5157291bf1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Intermedio - Extracción de documentos, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Intermedio
Número de nodos15
Categoría2
Tipos de nodos10
Descripción de la dificultad

Adecuado para usuarios con experiencia intermedia, flujos de trabajo de complejidad media con 6-15 nodos

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34