Twitter Sentiment Analysis ETL with Slack Notifications
Automate a daily ETL process: extract tweets, analyze sentiment with Google Cloud Natural Language, store results in MongoDB and Postgres, and send Slack notifications.
Overview
Build a daily automated ETL pipeline to extract tweets, perform sentiment analysis with Google NLP, load the data into PostgreSQL and MongoDB, and alert your team on Slack for positive-sentiment tweets.
🧠 Description & Use Case
This workflow demonstrates a complete ETL (Extract, Transform, Load) pipeline that automates social media sentiment analysis. It fetches tweets based on a specific hashtag, analyzes their sentiment using AI, stores the data in two different types of databases (MongoDB and PostgreSQL), and sends conditional notifications to a Slack channel.
This is a powerful tool for brand monitoring, campaign tracking, and market research, allowing you to automatically gauge public opinion and act on it.
🔄 How It Works:
-
Trigger
- The
Cronnode initiates the workflow every day at 6 AM.
- The
-
Extract: Fetch Tweets
- The
Twitternode searches for recent tweets containing the hashtag#OnThisDay.
- The
-
Load (Stage 1): Store Raw Data
- The
MongoDBnode immediately saves the raw text of each tweet into atweetscollection. This creates a simple, unstructured data archive.
- The
-
Transform: Analyze Sentiment
- The
Google Cloud Natural Languagenode processes the tweet text to determine its emotional tone, generating a sentimentscoreandmagnitude.
- The
-
Transform: Structure Data
- The
Setnode combines the original tweet text with its new sentiment score and magnitude into a clean, structured format.
- The
-
Load (Stage 2): Store Enriched Data
- The
Postgresnode inserts the structured, enriched data (tweet text, score, and magnitude) into a relational database table namedtweetsfor easy querying and reporting.
- The
-
Filter & Notify
- The
IFnode checks if the sentiment score is positive (greater than 0). - If true, the
Slacknode sends a formatted message to a designated channel, highlighting the positive tweet. - If false, the
NoOpnode ends the process for that tweet, taking no further action.
- The
✅ Real-World Use Cases:
- Brand Monitoring: Track public perception of your brand by analyzing tweets mentioning your company name or products.
- Campaign Analysis: Measure the real-time sentiment of a marketing campaign by tracking its official hashtag.
- Proactive Customer Support: Modify the workflow to flag negative tweets for immediate follow-up by your support team.
- Market Research: Gather public opinion on a specific topic, event, or competitor to inform business strategy.
- Data Warehousing: Build a robust data pipeline that collects data from an unstructured source (Twitter), enriches it with AI, and stores it in both a NoSQL (MongoDB) and a relational (PostgreSQL) database for different analytical needs.
Instructions
Basic steps
- Download workflow JSON
- Import into n8n
- Configure node parameters as needed
- Test and enable the workflow
💡 Tips
After importing, verify all connectors and credentials match your environment.
Preview
Workflow Visualization
Nodes
Postgres
postgres
MongoDB
mongoDb
Slack
slack
IF
if
NoOp
noOp
Google Cloud Natural Language
googleCloudNaturalLanguage
Set
set
Cron
cron
Statistics
View full JSON structure
{
"nodes": [
{
"name": "Twitter",
"type": "n8n-nodes-base.twitter",
"position": [
300,
300
],
"parameters": {
"limit": 3,
"operation": "search",
"searchText": "=#OnThisDay",
"additionalFields": {}
},
"credentials": {
"twitterOAuth1Api": "twitter_api"
},
"typeVersion": 1
},
{
"name": "Postgres",
"type": "n8n-nodes-base.postgres",
"position": [
1100,
300
],
"parameters": {
"table": "tweets",
"columns": "text, score, magnitude",
"returnFields": "=*"
},
"credentials": {
"postgres": "postgres"
},
"typeVersion": 1
},
{
"name": "MongoDB",
"type": "n8n-nodes-base.mongoDb",
"position": [
500,
300
],
"parameters": {
"fields": "text",
"options": {},
"operation": "insert",
"collection": "tweets"
},
"credentials": {
"mongoDb": "mongodb"
},
"typeVersion": 1
},
{
"name": "Slack",
"type": "n8n-nodes-base.slack",
"position": [
1500,
200
],
"parameters": {
"text": "=🐦 NEW TWEET with sentiment score {{$json[\"score\"]}} and magnitude {{$json[\"magnitude\"]}} ⬇️\n{{$json[\"text\"]}}",
"channel": "tweets",
"attachments": [],
"otherOptions": {}
},
"credentials": {
"slackApi": "slack"
},
"typeVersion": 1
},
{
"name": "IF",
"type": "n8n-nodes-base.if",
"position": [
1300,
300
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{$json[\"score\"]}}",
"operation": "larger"
}
]
}
},
"typeVersion": 1
},
{
"name": "NoOp",
"type": "n8n-nodes-base.noOp",
"position": [
1500,
400
],
"parameters": {},
"typeVersion": 1
},
{
"name": "Google Cloud Natural Language",
"type": "n8n-nodes-base.googleCloudNaturalLanguage",
"position": [
700,
300
],
"parameters": {
"content": "={{$node[\"MongoDB\"].json[\"text\"]}}",
"options": {}
},
"credentials": {
"googleCloudNaturalLanguageOAuth2Api": "google_nlp"
},
"typeVersion": 1
},
{
"name": "Set",
"type": "n8n-nodes-base.set",
"position": [
900,
300
],
"parameters": {
"values": {
"number": [
{
"name": "score",
"value": "={{$json[\"documentSentiment\"][\"score\"]}}"
},
{
"name": "magnitude",
"value": "={{$json[\"documentSentiment\"][\"magnitude\"]}}"
}
],
"string": [
{
"name": "text",
"value": "={{$node[\"Twitter\"].json[\"text\"]}}"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"name": "Cron",
"type": "n8n-nodes-base.cron",
"position": [
100,
300
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 6
}
]
}
},
"typeVersion": 1
}
],
"connections": {
"IF": {
"main": [
[
{
"node": "Slack",
"type": "main",
"index": 0
}
],
[
{
"node": "NoOp",
"type": "main",
"index": 0
}
]
]
},
"Set": {
"main": [
[
{
"node": "Postgres",
"type": "main",
"index": 0
}
]
]
},
"Cron": {
"main": [
[
{
"node": "Twitter",
"type": "main",
"index": 0
}
]
]
},
"MongoDB": {
"main": [
[
{
"node": "Google Cloud Natural Language",
"type": "main",
"index": 0
}
]
]
},
"Twitter": {
"main": [
[
{
"node": "MongoDB",
"type": "main",
"index": 0
}
]
]
},
"Postgres": {
"main": [
[
{
"node": "IF",
"type": "main",
"index": 0
}
]
]
},
"Google Cloud Natural Language": {
"main": [
[
{
"node": "Set",
"type": "main",
"index": 0
}
]
]
}
}
}Actions
Technical Specs
Compatibility
License
This workflow template follows MIT license, you can freely use, modify and distribute.
Please comply with relevant third-party service terms when using.