Sentiment Analysis on X
On this page
Understand what your audience really thinks
Sentiment analysis transforms thousands of posts into a clear read on how your brand, competitors, or industry are perceived. With X Search and Grok’s reasoning capabilities, you can go beyond simple positive/negative classification to understand emotional nuances, latent frustrations, and warning signals.
Sentiment dimensions in marketing
Marketing sentiment analysis goes beyond the positive/negative binary. Here are the relevant dimensions:
5-level sentiment scale
- Very positive: enthusiasm, active recommendation, brand love
- Positive: satisfaction, approval, interest
- Neutral: factual mention, information sharing
- Negative: disappointment, criticism, frustration
- Very negative: anger, call for boycott, crisis
Additional dimensions
- Purchase intention: Does the post indicate an intention to buy or unsubscribe?
- Influence: Does the post come from an influential account or an average consumer?
- Virality: Does the post have propagation potential?
- Urgency: Does the signal require a quick reaction?
Analyze sentiment with X Search and Grok
Sentiment analysis for your brand
def analyser_sentiment_marque(marque, periode_jours=7):
from datetime import datetime, timedelta
today = datetime.now().strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(days=periode_jours)).strftime("%Y-%m-%d")
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Analyze the sentiment of conversations on X
about {marque} between {start} and {today}.
For each conversation theme identified, provide:
1. The theme (e.g., "customer service", "product quality")
2. The dominant sentiment (1-5 scale)
3. The estimated conversation volume
4. The most representative verbatims
5. The most influential accounts in the discussion
6. Sentiment evolution over the period
Final summary:
- Global sentiment score (1-5)
- Top 3 positive points
- Top 3 negative points
- Any alerts""",
tools=[{
"type": "x_search",
"from_date": start,
"to_date": today
}]
)
return response.output_text
Comparative sentiment analysis
Compare your brand’s perception with that of your competitors:
def sentiment_comparatif(marques, periode_jours=30):
from datetime import datetime, timedelta
today = datetime.now().strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(days=periode_jours)).strftime("%Y-%m-%d")
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Compare sentiment on X for these brands:
{', '.join(marques)}
Period: {start} to {today}
For each brand, evaluate:
- Global sentiment score (1-5, with decimal)
- Dominant positive themes
- Dominant negative themes
- Strengths perceived by the public
- Weaknesses perceived by the public
Final comparison table ranked by sentiment.
Identify positioning opportunities for the
first brand in the list.""",
tools=[{"type": "x_search", "from_date": start, "to_date": today}]
)
return response.output_text
Get structured results in JSON
To integrate sentiment analysis into a data pipeline, request a JSON output:
def sentiment_structure(marque, periode_jours=7):
from datetime import datetime, timedelta
today = datetime.now().strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(days=periode_jours)).strftime("%Y-%m-%d")
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Analyze sentiment on X about {marque}.
Period: {start} to {today}.
Respond ONLY in valid JSON with this structure:
{{
"brand": "{marque}",
"period": "{start} - {today}",
"global_score": 3.7,
"distribution": {{
"very_positive": 15,
"positive": 35,
"neutral": 30,
"negative": 15,
"very_negative": 5
}},
"themes": [
{{
"name": "customer service",
"score": 2.1,
"volume": "high",
"trend": "stable"
}}
],
"alerts": ["alert description if applicable"],
"recommendations": ["recommended action"]
}}""",
tools=[{"type": "x_search", "from_date": start, "to_date": today}]
)
return response.output_text
Track sentiment evolution over time
One-off analysis is useful, but tracking over time reveals trends. Compare results week after week:
def evolution_sentiment(marque, nb_semaines=4):
from datetime import datetime, timedelta
import json
historique = []
for i in range(nb_semaines, 0, -1):
end = (datetime.now() - timedelta(weeks=i-1)).strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(weeks=i)).strftime("%Y-%m-%d")
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Sentiment score on X for {marque}
from {start} to {end}.
Respond with a JSON: {{"week": "{start}",
"score": X.X, "volume": N, "dominant_theme": "..."}}""",
tools=[{
"type": "x_search",
"from_date": start,
"to_date": end
}]
)
historique.append(response.output_text)
return historique
Detect reputation crises
Sentiment analysis is your first alert system in case of a crisis:
def detecter_crise(marque, seuil_negatif=40):
resultat = sentiment_structure(marque, periode_jours=1)
# Parse the JSON
import json
data = json.loads(resultat)
pct_negatif = (data["distribution"]["negative"] +
data["distribution"]["very_negative"])
if pct_negatif > seuil_negatif:
return {
"alert": True,
"level": "CRITICAL" if pct_negatif > 60 else "IMPORTANT",
"score": data["global_score"],
"negative_themes": [t for t in data["themes"] if t["score"] < 2.5],
"recommendation": "Crisis meeting recommended"
}
return {"alert": False, "score": data["global_score"]}
Key takeaways
- Sentiment analysis goes beyond positive/negative: evaluate intention, influence, and urgency
- Use a 5-level scale to capture nuances
- Request structured JSON outputs to feed your dashboards
- Track sentiment evolution over time, not just one-off snapshots
- Systematically compare your sentiment with that of your competitors
- Configure alert thresholds to detect reputation crises as they emerge