This workflow follows the Agent → Google Sheets 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 →
{
"name": "Marketing-Automation",
"nodes": [
{
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 10
}
]
}
},
"name": "Cron Trigger",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
-100,
-1180
],
"id": "fc19477b-7fe7-4b61-875d-8e338e8ed5c2",
"disabled": true
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-100,
-1000
],
"id": "fbfa821d-9406-4a74-8a5b-7669cae98736",
"name": "When clicking \u2018Test workflow\u2019"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM",
"mode": "list",
"cachedResultName": "Social Networks scraps",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "fb",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"postId": "={{ $json.postId }}",
"pageName": "={{ $json.pageName }}",
"facebookUrl": "={{ $json.facebookUrl }}",
"comments": "={{ $json.comments }}",
"topReactionsCount": "={{ $json.topReactionsCount }}",
"likes": "={{ $json.likes }}",
"text": "={{ $json.text }}",
"isVideo": "={{ $json.isVideo }}",
"previewDescription": "={{ $json.previewDescription }}",
"time": "={{ $json.time }}",
"previewTitle": "={{ $json.previewTitle }}",
"viewsCount": "={{ $json.viewsCount }}",
"shares": "={{ $json.shares }}"
},
"matchingColumns": [],
"schema": [
{
"id": "postId",
"displayName": "postId",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "pageName",
"displayName": "pageName",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "facebookUrl",
"displayName": "facebookUrl",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "time",
"displayName": "time",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "text",
"displayName": "text",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "previewTitle",
"displayName": "previewTitle",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "previewDescription",
"displayName": "previewDescription",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "isVideo",
"displayName": "isVideo",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "viewsCount",
"displayName": "viewsCount",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "likes",
"displayName": "likes",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "topReactionsCount",
"displayName": "topReactionsCount",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "comments",
"displayName": "comments",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "shares",
"displayName": "shares",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
360,
-1000
],
"id": "fa2c3422-5ea5-49e6-be18-05b164a3a6ab",
"name": "Google Sheets",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/apify~facebook-posts-scraper/run-sync-get-dataset-items?token=apify_api_fiOL6Limd4wsvbUXyretySTdCgBtaS3xx7IJ",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"captionText\": false,\n \"onlyPostsNewerThan\": \"2025-01-01\",\n \"resultsLimit\": 20,\n \"startUrls\": [\n {\n \"url\": \"https://www.facebook.com/ufhbci/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/etudiantmagazine/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/letudiantafricain/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/Plate-forme-nationale-Des-%C3%89tudiants-Boursiers-De-C%C3%B4te-DIvoire-100057331694608/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/Collectif-des-Etudiants-Solidaires-C%C3%B4te-dIvoire-100082264729957/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/100035421711973/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/UniversiteNanguiAbrogoua/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/univaobouake/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/inphb.polytech/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/uvciv/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/orangecotedivoire/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/TECNOMobileCotedIvoire/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/InfinixCotedIvoire/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/MagicSystemOfficiel/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/YvideroOfficiel/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/RTIOfficiel/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/abidjan.net/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/MTNCotedIvoire/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/apoutchounational/\",\n \"method\": \"GET\"\n },\n {\n \"url\": \"https://www.facebook.com/p/Laetitia-Ky--100044368242170/\",\n \"method\": \"GET\"\n }\n ]\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
120,
-1000
],
"id": "322e3cfa-2097-4113-a5df-9e41d4564df9",
"name": "HTTP Request"
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"documentId": {
"__rl": true,
"value": "1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM",
"mode": "list",
"cachedResultName": "Social Networks scraps",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "fb",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit#gid=0"
},
"event": "rowAdded",
"options": {}
},
"type": "n8n-nodes-base.googleSheetsTrigger",
"typeVersion": 1,
"position": [
-140,
-780
],
"id": "ada34650-5caf-47dd-a136-24152376ccea",
"name": "Google Sheets Trigger",
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://language.googleapis.com/v2/documents:analyzeSentiment",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleCloudNaturalLanguageOAuth2Api",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "document.type",
"value": "PLAIN_TEXT"
},
{
"name": "document.content",
"value": "={{ $json.text.trim() }}"
},
{
"name": "encodingType",
"value": "UTF8"
},
{
"name": "document.languageCode",
"value": "fr"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
20,
-780
],
"id": "dc06a671-db85-484d-8347-6efd05b08244",
"name": "Sentiment analysis",
"credentials": {
"googleCloudNaturalLanguageOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://language.googleapis.com/v2/documents:classifyText",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleCloudNaturalLanguageOAuth2Api",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "document.type",
"value": "PLAIN_TEXT"
},
{
"name": "document.content",
"value": "={{ $('Google Sheets Trigger').item.json.text.trim() }}"
},
{
"name": "document.languageCode",
"value": "fr"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
180,
-780
],
"id": "3c493f83-6eef-4e5e-89ba-f9a9084b3bce",
"name": "classify text",
"credentials": {
"googleCloudNaturalLanguageOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"promptType": "define",
"text": "=Vous \u00eates un agent IA expert en marketing et prompt engineering. Votre mission : \n\u00e0 partir de deux jeux de donn\u00e9es :\n\n1. **Analyse de sentiment** \n Un \"documentSentiment\" repr\u00e9sentant la note globale, est produit avec une magnitude de : {{ $('Sentiment analysis').first().json.documentSentiment.magnitude }} et un score de {{ $('Sentiment analysis').first().json.documentSentiment.score }}: . Ensuite chaque sentence (phrase) a ete analys\u00e9e; une magnitude et un score ont \u00e9t\u00e9 aussi calcul\u00e9s. \n - Exemple pour la premi\u00e8re phrase (sentence [0]), voici les r\u00e9sultats:\n - `Texte` -> {{ $('Sentiment analysis').first().json.sentences[0].text.content }}\n - `sentimentScore` -> {{ $('Sentiment analysis').first().json.sentences[0].sentiment.score }}\n - `sentimentMagnitude` -> {{ $('Sentiment analysis').first().json.sentences[0].sentiment.magnitude }}\n\n2. **Cat\u00e9gorisation (ClassifyText)** \n Des cat\u00e9gories ont \u00e9t\u00e9 identifi\u00e9es avec un nom (name) et un niveau de confiance (confidence)\nExemple pour la 1ere cat\u00e9gorie :\n - `name` -> {{ $('classify text').first().json.categories[0].name }}\n - `confidence` -> {{ $('classify text').first().json.categories[0].confidence }}\n\n**Objectif :** \nG\u00e9n\u00e9rer {{$json.toGenerate}} personas B2C ou B2B au format JSON ** coh\u00e9rents, repr\u00e9sentatifs des comportements et \u00e9motions d\u00e9tect\u00e9s, en vous appuyant sur :\n- Les **scores** et **magnitudes** pour \u00e9valuer l\u2019intensit\u00e9 \u00e9motionnelle \n- Les **cat\u00e9gories** les plus fr\u00e9quentes ou saillantes \n\n**Chaque persona** doit comporter :\n- `Nom Personae` : un pr\u00e9nom + nom fictif \n- `Tranche d\u2019\u00e2ge` : ex. \u201c25\u201334 ans\u201d \n- `Centres d\u2019int\u00e9r\u00eat cl\u00e9s` : 3 \u00e0 5 centres d\u2019int\u00e9r\u00eat issus des cat\u00e9gories \n- `Principaux besoins` : 3 besoins concrets (motivations d\u2019achat) \n- `Principales frustrations` : 3 points de douleur / objections potentielles \n\nVous devez utiliser des noms et pr\u00e9noms d'Afrique de l'Ouest (mixer des noms musulmans et chr\u00e9tiens) en guise de pr\u00e9nom et nom fictifs.\n\nToujours utiliser \u00e0 la fois les r\u00e9sultats de l'Analyse de sentiment et les r\u00e9sultats de la cat\u00e9gorisation (ClassifyTexte), avant de produire les personae.\n\nSoyez pertinent et fiable en vous basant sur les donn\u00e9es receuillies.\n\nQuand vous avez atteint le r\u00e9sultat de {{$json.toGenerate}} personas g\u00e9n\u00e9r\u00e9s, appelez la fonction generate_personas() \nen lui passant STRICTEMENT un objet { \"personas\": [ \u2026 ] } \net ne renvoyez **aucun** texte libre.\n\n",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.9,
"position": [
880,
-800
],
"id": "4ea19cf0-510a-4abb-857d-b4e0a1158ca8",
"name": "AI Agent",
"alwaysOutputData": true
},
{
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
920,
-580
],
"id": "bbd1aa62-bc2a-469e-9003-62965395166a",
"name": "OpenAI Chat Model",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "20898c16-d845-4c80-bffb-80c50046fb7e",
"leftValue": "={{ $json.toGenerate }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "gt"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
660,
-780
],
"id": "8cc5373c-db3d-4f8e-a75c-82c869bfb9f7",
"name": "If"
},
{
"parameters": {
"url": "https://n8n.srv778906.hstgr.cloud/webhook/get_persona_count",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
340,
-780
],
"id": "362a4ed3-4acf-4dce-854a-42d238e80415",
"name": "get_persona_count"
},
{
"parameters": {
"jsCode": "const count = parseInt($input.first().json.count) ;\nconst toGenerate = Math.max(0, 5 - count);\nreturn [{ json: { toGenerate } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
500,
-780
],
"id": "3ef047ff-bd8e-4c1d-9242-f4dab448ce1c",
"name": "Code"
},
{
"parameters": {
"errorMessage": "5 personas sont d\u00e9j\u00e0 pr\u00e9sents dans la base"
},
"type": "n8n-nodes-base.stopAndError",
"typeVersion": 1,
"position": [
660,
-560
],
"id": "4c249158-fd60-4372-9ddc-e63359d0f0d7",
"name": "Stop and Error"
},
{
"parameters": {
"jsCode": "return \"query\" ;"
},
"type": "@n8n/n8n-nodes-langchain.toolCode",
"typeVersion": 1.2,
"position": [
1100,
-580
],
"id": "88b4e2b6-ac92-4edd-8728-36d69147c225",
"name": "generate_personas"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM",
"mode": "list",
"cachedResultName": "Social Networks scraps",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": 873907131,
"mode": "list",
"cachedResultName": "Personae",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1seUgVf56OLRRDpWEdk-6lbNh4wxJ_vAhrZOb6iDb7jM/edit#gid=873907131"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {
"Nom Personae": "={{ $json.nomPersonae }}",
"Tranche d\u2019\u00e2ge": "={{ $json.trancheAge }}",
"Centres d\u2019int\u00e9r\u00eat cl\u00e9s": "={{ $json.centresInteretCles }}",
"Principaux besoins": "={{ $json.principauxBesoins }}",
" Principales frustrations": "={{ $json.principalesFrustrations }}"
},
"matchingColumns": [],
"schema": [
{
"id": "Nom Personae",
"displayName": "Nom Personae",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tranche d\u2019\u00e2ge",
"displayName": "Tranche d\u2019\u00e2ge",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Centres d\u2019int\u00e9r\u00eat cl\u00e9s",
"displayName": "Centres d\u2019int\u00e9r\u00eat cl\u00e9s",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Principaux besoins",
"displayName": "Principaux besoins",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": " Principales frustrations",
"displayName": " Principales frustrations",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1360,
-800
],
"id": "ca3b9557-3999-41fc-8cfc-446e465fc973",
"name": "Google Sheets1",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// 1. R\u00e9cup\u00e8re la sortie brute de l'agent\nconst raw = items[0].json.output;\n\n// 2. Parse en JSON si n\u00e9cessaire\nlet data;\ntry {\n data = (typeof raw === 'string') ? JSON.parse(raw) : raw;\n} catch (err) {\n throw new Error('Impossible de parser le JSON de sortie : ' + err.message);\n}\n\n// 3. Extrait et s\u00e9curise le tableau personas\nconst personas = Array.isArray(data.personas) ? data.personas : [];\n\n// 4. Tronque \u00e0 5\nconst limited = personas.slice(0, 5);\n\n// 5. Retourne chaque objet comme item n8n\nreturn limited.map(persona => ({ json: persona }));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1200,
-800
],
"id": "99c109b0-85ec-4f83-9048-e005c0d0d291",
"name": "limit"
}
],
"connections": {
"Cron Trigger": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Test workflow\u2019": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets Trigger": {
"main": [
[
{
"node": "Sentiment analysis",
"type": "main",
"index": 0
}
]
]
},
"Sentiment analysis": {
"main": [
[
{
"node": "classify text",
"type": "main",
"index": 0
}
]
]
},
"classify text": {
"main": [
[
{
"node": "get_persona_count",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "limit",
"type": "main",
"index": 0
}
]
]
},
"get_persona_count": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "Stop and Error",
"type": "main",
"index": 0
}
]
]
},
"generate_personas": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"limit": {
"main": [
[
{
"node": "Google Sheets1",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "87837795-c7e8-4f21-bd0b-c33d30bac7f0",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "pPF0mk2F49eHIRMA",
"tags": []
}
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.
googleCloudNaturalLanguageOAuth2ApigoogleSheetsOAuth2ApigoogleSheetsTriggerOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Marketing-Automation. Uses googleSheets, httpRequest, googleSheetsTrigger, agent. Scheduled trigger; 16 nodes.
Source: https://github.com/mlaminecamara/Fb_scrapper/blob/3009924246dd686a3e56faeb87f3b19c58963ccd/fb_scrapper_agent — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p
This workflow automates the process of generating, reviewing, and publishing blog posts across multiple platforms, now enhanced with support for RSS Feeds as a content source. It streamlines the manag
This workflow automates end-to-end ESG (Environmental, Social, and Governance) sustainability reporting for enterprise sustainability teams, compliance officers, and green governance leads. It solves
Every time a new invoice lands in your inbox, this workflow reads it, extracts all the relevant data using AI, and logs everything into a Google Sheets spreadsheet automatically. No copy-pasting, no f
Automated daily scraping of competitor websites, pricing pages, job postings, and press releases feeds into an AI analyzer powered by OpenAI or Claude to extract trends, insights, and key metrics. The