AutomationFlowsSocial Media › Promote Calendar Events with Openai Graphics to Linkedin, X, and Facebook

Promote Calendar Events with Openai Graphics to Linkedin, X, and Facebook

ByJitesh Dugar @jiteshdugar on n8n.io

Never let an event go unpromoted. This workflow monitors your Google Calendar, generates branded promotional graphics, and schedules a staggered social media countdown across LinkedIn, Twitter/X, and Facebook.

Event trigger★★★★☆ complexityAI-powered23 nodesGoogle Calendar TriggerHTTP RequestEdit ImageOpenAIGoogle SheetsLinkedInTwitterTelegram
Social Media Trigger: Event Nodes: 23 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #14971 — we link there as the canonical source.

This workflow follows the Editimage → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "nodes": [
    {
      "id": "fd27db75-494d-4e71-9dfd-a0e042a123fb",
      "name": "\ud83d\udccb MAIN \u2014 Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        -1072
      ],
      "parameters": {
        "width": 760,
        "height": 960,
        "content": "## \ud83d\udcc5 Event Promotion \u2014 Auto-Generate Graphic & Schedule Posts Across Social Channels\n\n**What this workflow does:**\nWhen a new event is added to Google Calendar (or Eventbrite via polling), this workflow:\n1. Extracts event details (name, date, time, location, description)\n2. Uses the **Edit Image node** to programmatically compose a branded promotional graphic (overlaying event title + date onto a template image)\n3. Uploads the graphic via **UploadToURL** to get a public CDN URL\n4. Uses a **DateTime node** to calculate the optimal post schedule (48hrs, 24hrs, and 1hr before event)\n5. Loops through 3 scheduled time slots using **Loop Over Items**\n6. At each loop iteration, a **Wait node** pauses until the scheduled time, then fires posts to LinkedIn, Twitter/X, and Facebook simultaneously\n7. Logs every post action to **Google Sheets** (platform, post time, event name, status)\n8. Sends a **Telegram** confirmation message to the admin after all posts are dispatched\n\n**Architecture (fully unique from Templates 1 & 2):**\n- \ud83d\udcc5 Google Calendar Trigger (NOT RSS / Schedule / Webhook)\n- \ud83d\uddbc\ufe0f Edit Image Node \u2014 programmatic graphic composition\n- \u2601\ufe0f UploadToURL \u2014 mandatory CDN hosting of generated graphic\n- \ud83d\udd50 DateTime Node \u2014 calculates 3 staggered post schedules\n- \ud83d\udd01 Loop Over Items \u2014 iterates through each scheduled slot\n- \u23f3 Wait Node \u2014 pauses execution until exact post time\n- \ud83d\udd00 Merge Node \u2014 recombines event data + schedule data\n- \ud83d\udcca Google Sheets \u2014 post audit log\n- \ud83d\udce8 Telegram \u2014 admin notification after completion\n\n**Setup Requirements:**\n1. Google Calendar OAuth2 credentials (watch a specific calendar)\n2. A base event banner image stored at a public URL (used as graphic template)\n3. UploadToURL endpoint configured\n4. LinkedIn OAuth2 credentials\n5. Twitter/X OAuth1 credentials\n6. Facebook Graph API token (pages_manage_posts scope)\n7. Google Sheets OAuth2 \u2014 create a sheet named `EventPostLog` with columns: EventID, EventName, Platform, ScheduledTime, PostedAt, Status, ImageURL\n8. Telegram Bot Token + your Chat ID"
      },
      "typeVersion": 1
    },
    {
      "id": "0ec5b6a5-821f-4ffa-8fe1-ff30bcc481bd",
      "name": "\ud83d\udcdd Note \u2014 Calendar Trigger & Event Parse",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 644,
        "height": 612,
        "content": "### \ud83d\udcc5 Step 1 \u2014 Google Calendar Trigger & Event Data Extraction\n**Google Calendar Trigger:** Fires instantly when any new event is created in your watched calendar. No polling \u2014 uses Google's push notification system.\n**Code Node (Parse Event):** Extracts `eventId`, `summary` (title), `description`, `location`, `startDateTime`, `endDateTime`, and the event organizer. Also derives a clean `eventDate` string and `daysUntilEvent` count used for scheduling logic downstream.\n**IF Node (Future Events Only):** Skips events that start in less than 2 hours \u2014 not enough lead time to schedule meaningful promotional posts."
      },
      "typeVersion": 1
    },
    {
      "id": "417e25e5-70d9-48a6-a0c0-9d927fa92664",
      "name": "\ud83d\udcdd Note \u2014 Edit Image, Upload & Schedule Calc",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 884,
        "height": 612,
        "content": "### \ud83d\uddbc\ufe0f Step 2 \u2014 Graphic Generation & UploadToURL\n**HTTP \u2014 Fetch Banner Template:** Downloads your base event banner image (stored at a fixed public URL) as binary.\n**Edit Image Node:** Overlays the event title, date, and location as text onto the banner image. Uses built-in composite operations \u2014 no external design API needed.\n**UploadToURL:** Uploads the composed graphic binary to your CDN. Returns a permanent public URL used in all social posts across all scheduled slots.\n**DateTime Node:** Calculates exactly 3 post timestamps \u2014 48 hours before, 24 hours before, and 1 hour before the event start time."
      },
      "typeVersion": 1
    },
    {
      "id": "55c3090d-cf83-4c86-afa6-9d5f48ab2a12",
      "name": "\ud83d\udcdd Note \u2014 Merge, Loop, Wait & Post",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2384,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1060,
        "height": 612,
        "content": "### \ud83d\udd01 Step 3 \u2014 Loop, Wait & Scheduled Multi-Platform Posting\n**Merge Node:** Joins the event data (from step 1) with the scheduled timestamps + hosted image URL (from step 2) into a single enriched item before looping.\n**Loop Over Items:** Iterates over the 3 schedule slots one by one (48hr, 24hr, 1hr).\n**Wait Node:** Inside each loop iteration, pauses workflow execution until the exact scheduled timestamp. n8n resumes automatically \u2014 no cron job needed.\n**OpenAI Node:** Generates a time-aware caption (e.g. 'Event tomorrow!' vs 'Starting in 1 hour!') based on which slot is being processed.\n**3 Parallel Posts:** LinkedIn, Twitter/X, and Facebook all post simultaneously within each loop iteration."
      },
      "typeVersion": 1
    },
    {
      "id": "3c381e4b-341c-46f9-ac52-bd9ab269c2f3",
      "name": "\ud83d\udcdd Note \u2014 Sheets Log & Telegram Notify",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3472,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 820,
        "height": 928,
        "content": "### \ud83d\udcca Step 4 \u2014 Google Sheets Log & Telegram Notification\n**Google Sheets \u2014 Append Row:** After each post within the loop, appends a row to `EventPostLog` with EventID, EventName, Platform, ScheduledTime, PostedAt, Status, and ImageURL \u2014 giving a full audit trail of every promotional post.\n**Telegram \u2014 Admin Alert:** After all 3 loop iterations complete (all 9 posts dispatched \u2014 3 slots \u00d7 3 platforms), sends a Telegram message to the admin summarising the event name, how many posts were made, and the hosted graphic URL."
      },
      "typeVersion": 1
    },
    {
      "id": "aeda65f6-4d8a-443b-8dac-aa0d6f361ce3",
      "name": "Google Calendar \u2014 New Event Trigger",
      "type": "n8n-nodes-base.googleCalendarTrigger",
      "position": [
        880,
        240
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "eventCreated",
        "calendarId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c6cfc58d-a2cc-4e28-8aec-099a1cb384b0",
      "name": "Code \u2014 Parse & Enrich Event Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1104,
        240
      ],
      "parameters": {
        "jsCode": "const ev = $input.first().json;\n\n// Parse start time \u2014 handle both dateTime and all-day (date only)\nconst startRaw = ev.start?.dateTime || ev.start?.date || '';\nconst endRaw   = ev.end?.dateTime   || ev.end?.date   || '';\n\nconst startDate = new Date(startRaw);\nconst endDate   = new Date(endRaw);\nconst now       = new Date();\n\nconst msUntil = startDate.getTime() - now.getTime();\nconst hoursUntil = msUntil / (1000 * 60 * 60);\nconst daysUntil  = Math.floor(hoursUntil / 24);\n\n// Format readable date\nconst dateOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };\nconst timeOptions = { hour: '2-digit', minute: '2-digit', timeZoneName: 'short' };\nconst eventDateStr = startDate.toLocaleDateString('en-US', dateOptions);\nconst eventTimeStr = startDate.toLocaleTimeString('en-US', timeOptions);\n\nconst title    = ev.summary || 'Upcoming Event';\nconst desc     = (ev.description || '').replace(/<[^>]+>/g, '').trim().substring(0, 400);\nconst location = ev.location || 'Online / TBD';\nconst eventId  = ev.id || ev.iCalUID || `evt-${Date.now()}`;\nconst organizer = ev.organizer?.displayName || ev.organizer?.email || 'Organizer';\nconst eventUrl  = ev.htmlLink || '';\n\nreturn [{\n  json: {\n    eventId,\n    title,\n    description: desc,\n    location,\n    organizer,\n    eventUrl,\n    startRaw,\n    endRaw,\n    eventDateStr,\n    eventTimeStr,\n    hoursUntil: Math.round(hoursUntil),\n    daysUntil\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "1a86d41e-33d1-4aee-89ea-df64537d0405",
      "name": "IF \u2014 Event Has Enough Lead Time (2h+)",
      "type": "n8n-nodes-base.if",
      "position": [
        1328,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "future-check",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.hoursUntil }}",
              "rightValue": 2
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "aab53c6e-3c39-4ec5-8618-06478501eeb0",
      "name": "HTTP \u2014 Fetch Base Banner Template",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1552,
        240
      ],
      "parameters": {
        "url": "https://your-brand-assets.com/event-banner-template.jpg",
        "options": {
          "timeout": 15000,
          "redirect": {
            "redirect": {
              "maxRedirects": 3
            }
          },
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "048d9a2c-363c-45cd-86ea-98aeb8ef3c0a",
      "name": "Edit Image \u2014 Compose Event Promo Graphic",
      "type": "n8n-nodes-base.editImage",
      "position": [
        1760,
        240
      ],
      "parameters": {
        "options": {},
        "operation": "composite"
      },
      "typeVersion": 1
    },
    {
      "id": "68b5990f-faad-4383-b06b-c14421569e55",
      "name": "DateTime \u2014 Parse Event Start Time",
      "type": "n8n-nodes-base.dateTime",
      "position": [
        2208,
        240
      ],
      "parameters": {
        "operation": "toDate"
      },
      "typeVersion": 2
    },
    {
      "id": "1bddf0b8-6c47-4da8-9380-f4955c17d648",
      "name": "Code \u2014 Build 3 Schedule Slots",
      "type": "n8n-nodes-base.code",
      "position": [
        2432,
        240
      ],
      "parameters": {
        "jsCode": "const eventData = $('Code \u2014 Parse & Enrich Event Data').item.json;\nconst uploadResp = $('UploadToURL \u2014 Host Promo Graphic').item.json;\nconst startRaw   = eventData.startRaw;\n\nconst hostedImageUrl =\n  uploadResp?.url ??\n  uploadResp?.data?.url ??\n  uploadResp?.file?.url ??\n  uploadResp?.link ??\n  'https://placeholder.com/event-graphic.jpg';\n\nconst startMs = new Date(startRaw).getTime();\n\n// Build 3 schedule slots\nconst slots = [\n  {\n    slotIndex: 1,\n    label: '48 Hours Before',\n    urgency: 'early',\n    scheduledAt: new Date(startMs - 48 * 60 * 60 * 1000).toISOString()\n  },\n  {\n    slotIndex: 2,\n    label: '24 Hours Before',\n    urgency: 'reminder',\n    scheduledAt: new Date(startMs - 24 * 60 * 60 * 1000).toISOString()\n  },\n  {\n    slotIndex: 3,\n    label: '1 Hour Before',\n    urgency: 'last_call',\n    scheduledAt: new Date(startMs - 1 * 60 * 60 * 1000).toISOString()\n  }\n];\n\n// Return one item per schedule slot\nreturn slots.map(slot => ({\n  json: {\n    ...eventData,\n    hostedImageUrl,\n    slotIndex:   slot.slotIndex,\n    slotLabel:   slot.label,\n    urgency:     slot.urgency,\n    scheduledAt: slot.scheduledAt\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "ebe7e9cb-9ec6-4607-81af-9e5f7bb06385",
      "name": "Loop Over Items \u2014 Each Schedule Slot",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2640,
        240
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "0beaf14c-95c3-4229-bf00-76505fcbf604",
      "name": "Wait \u2014 Until Scheduled Post Time",
      "type": "n8n-nodes-base.wait",
      "position": [
        2864,
        240
      ],
      "parameters": {
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "6129c959-f975-4c16-a1e9-eacff1b31c22",
      "name": "OpenAI \u2014 Generate Time-Aware Captions",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        3088,
        240
      ],
      "parameters": {
        "resource": "chat"
      },
      "typeVersion": 1.4
    },
    {
      "id": "c2249c43-5c44-4241-9e79-cd0ed599c69f",
      "name": "Code \u2014 Parse Captions with Fallback",
      "type": "n8n-nodes-base.code",
      "position": [
        3312,
        240
      ],
      "parameters": {
        "jsCode": "const aiResp   = $input.first().json;\nconst slotData = $('Wait \u2014 Until Scheduled Post Time').item.json;\n\nlet captions = {};\ntry {\n  const raw     = aiResp?.choices?.[0]?.message?.content || '{}';\n  const cleaned = raw.replace(/```json|```/g, '').trim();\n  captions      = JSON.parse(cleaned);\n} catch(e) {\n  const fallback = `\ud83c\udf89 ${slotData.title} \u2014 ${slotData.eventDateStr} at ${slotData.location}. Don't miss it! ${slotData.eventUrl}`;\n  captions = {\n    linkedin: fallback + ' #Event #MustAttend',\n    twitter:  `\ud83d\udcc5 ${slotData.title} \u2014 ${slotData.eventDateStr} ${slotData.eventUrl} #Event`,\n    facebook: fallback + ' #Community #Event'\n  };\n}\n\nreturn [{\n  json: {\n    ...slotData,\n    linkedinCaption: captions.linkedin  || '',\n    twitterCaption:  captions.twitter   || '',\n    facebookCaption: captions.facebook  || '',\n    postedAt: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "cec16981-538f-4e9f-b532-438fb848ec02",
      "name": "Google Sheets \u2014 Append Post Log Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3632,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "posted",
            "EventID": "={{ $json.eventId }}",
            "ImageURL": "={{ $json.hostedImageUrl }}",
            "Platform": "LinkedIn, Twitter/X, Facebook",
            "PostedAt": "={{ $json.postedAt }}",
            "EventName": "={{ $json.title }}",
            "SlotLabel": "={{ $json.slotLabel }}",
            "ScheduledTime": "={{ $json.scheduledAt }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "EventPostLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "d35ed283-f9d9-44af-8ed2-330593cd39b3",
      "name": "LinkedIn \u2014 Publish Event Post",
      "type": "n8n-nodes-base.linkedIn",
      "position": [
        3632,
        32
      ],
      "parameters": {
        "text": "={{ $json.linkedinCaption }}",
        "additionalFields": {
          "title": "={{ $json.title }}"
        },
        "shareMediaCategory": "IMAGE"
      },
      "typeVersion": 1
    },
    {
      "id": "29d914de-5961-4cb0-84da-94499264bfe9",
      "name": "Twitter/X \u2014 Publish Event Tweet",
      "type": "n8n-nodes-base.twitter",
      "position": [
        3632,
        240
      ],
      "parameters": {
        "text": "={{ $json.twitterCaption }}",
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "31da4939-683c-44d7-8b53-78dd5f332eec",
      "name": "Facebook \u2014 Publish Event Photo Post",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3632,
        432
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_FB_PAGE_ID/photos",
        "method": "POST",
        "options": {
          "timeout": 15000
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.hostedImageUrl }}"
            },
            {
              "name": "message",
              "value": "={{ $json.facebookCaption }}"
            },
            {
              "name": "access_token",
              "value": "=YOUR_FB_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "979f52f6-fe37-46ce-8377-0e0a03584f7a",
      "name": "Merge \u2014 Collect All Platform Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        3904,
        32
      ],
      "parameters": {
        "mode": "passThrough"
      },
      "typeVersion": 3
    },
    {
      "id": "c0e9c7db-9bd3-4da5-af40-d5b075007f8d",
      "name": "Telegram \u2014 Notify Admin of Post Dispatch",
      "type": "n8n-nodes-base.telegram",
      "position": [
        4080,
        32
      ],
      "parameters": {
        "text": "=\u2705 Event promo posts dispatched!\n\n\ud83d\udcc5 *{{ $('Code \u2014 Parse Captions with Fallback').item.json.title }}*\n\ud83d\uddd3 {{ $('Code \u2014 Parse Captions with Fallback').item.json.eventDateStr }}\n\ud83d\udccd {{ $('Code \u2014 Parse Captions with Fallback').item.json.location }}\n\n\ud83d\udd16 Slot: {{ $('Code \u2014 Parse Captions with Fallback').item.json.slotLabel }}\n\ud83d\uddbc Graphic: {{ $('Code \u2014 Parse Captions with Fallback').item.json.hostedImageUrl }}\n\nPosted to: LinkedIn \u2713 | Twitter/X \u2713 | Facebook \u2713",
        "chatId": "=YOUR_TELEGRAM_CHAT_ID",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "282e46b6-5121-4563-abca-bb2a43b7511b",
      "name": "Upload a File",
      "type": "n8n-nodes-uploadtourl.uploadToUrl",
      "position": [
        1968,
        240
      ],
      "parameters": {},
      "credentials": {
        "uploadToUrlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Upload a File": {
      "main": [
        [
          {
            "node": "DateTime \u2014 Parse Event Start Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code \u2014 Build 3 Schedule Slots": {
      "main": [
        [
          {
            "node": "Loop Over Items \u2014 Each Schedule Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LinkedIn \u2014 Publish Event Post": {
      "main": [
        [
          {
            "node": "Merge \u2014 Collect All Platform Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Code \u2014 Parse & Enrich Event Data": {
      "main": [
        [
          {
            "node": "IF \u2014 Event Has Enough Lead Time (2h+)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait \u2014 Until Scheduled Post Time": {
      "main": [
        [
          {
            "node": "OpenAI \u2014 Generate Time-Aware Captions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DateTime \u2014 Parse Event Start Time": {
      "main": [
        [
          {
            "node": "Code \u2014 Build 3 Schedule Slots",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP \u2014 Fetch Base Banner Template": {
      "main": [
        [
          {
            "node": "Edit Image \u2014 Compose Event Promo Graphic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code \u2014 Parse Captions with Fallback": {
      "main": [
        [
          {
            "node": "Google Sheets \u2014 Append Post Log Row",
            "type": "main",
            "index": 0
          },
          {
            "node": "LinkedIn \u2014 Publish Event Post",
            "type": "main",
            "index": 0
          },
          {
            "node": "Twitter/X \u2014 Publish Event Tweet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Facebook \u2014 Publish Event Photo Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Calendar \u2014 New Event Trigger": {
      "main": [
        [
          {
            "node": "Code \u2014 Parse & Enrich Event Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2014 Append Post Log Row": {
      "main": [
        [
          {
            "node": "Merge \u2014 Collect All Platform Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items \u2014 Each Schedule Slot": {
      "main": [
        [
          {
            "node": "Wait \u2014 Until Scheduled Post Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge \u2014 Collect All Platform Results": {
      "main": [
        [
          {
            "node": "Telegram \u2014 Notify Admin of Post Dispatch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF \u2014 Event Has Enough Lead Time (2h+)": {
      "main": [
        [
          {
            "node": "HTTP \u2014 Fetch Base Banner Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2014 Generate Time-Aware Captions": {
      "main": [
        [
          {
            "node": "Code \u2014 Parse Captions with Fallback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Image \u2014 Compose Event Promo Graphic": {
      "main": [
        [
          {
            "node": "Upload a File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Never let an event go unpromoted. This workflow monitors your Google Calendar, generates branded promotional graphics, and schedules a staggered social media countdown across LinkedIn, Twitter/X, and Facebook.

Source: https://n8n.io/workflows/14971/ — original creator credit. Request a take-down →

More Social Media workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Social Media

This workflow is designed for content creators, social media managers, digital marketers, and business owners who want to automate their content creation and distribution process across multiple platf

Google Drive, Google Drive Trigger, WordPress +13
Social Media

This workflow is built for creators, solopreneurs, SaaS founders, and agencies looking to automate their social media content process from idea to publication. It combines the power of OpenAI, Google

OpenAI Chat, Tool Workflow, Agent +15
Social Media

✨🤖Automated AI Powered Social Media Content Factory for X + Facebook + Instagram + LinkedIn. Uses outputParserStructured, lmChatGoogleGemini, lmChatOpenAi, httpRequest. Event-driven trigger; 57 nodes

Output Parser Structured, Google Gemini Chat, OpenAI Chat +11
Social Media

Social Media Managers and Digital Marketers seeking to streamline content production across 7+ platforms (X/Twitter, Instagram, LinkedIn, Facebook, TikTok, Threads, YouTube Shorts) using AI-powered au

Output Parser Structured, Google Gemini Chat, OpenAI Chat +11
Social Media

This n8n workflow is designed for Shopify store owners, e-commerce managers, and digital marketers who want to automate their product promotion across multiple platforms. The workflow automatically cr

WordPress, Edit Image, HTTP Request +10