Automated Competitive Reports
On this page
Automate competitive intelligence
A one-off competitive report becomes obsolete within days. The real value lies in automation: regularly generated reports, structured identically, allowing you to compare periods and track your competitors’ strategic shifts.
This lesson shows you how to build an automated competitive reporting system that combines X data and web data.
Architecture of a complete competitive report
An effective marketing competitive report covers five axes, and their value comes from how they intersect: a product launch (axis 3) also shows up in publication volume (axis 1) and public sentiment (axis 4). This cross-referencing distinguishes intelligence from simple collection—a signal confirmed by two axes deserves attention, an isolated signal mostly deserves verification:
1. Social media activity
Publication volume, formats used, engagement, audience growth.
2. Content strategy
Topics covered, tone, positioning, observed editorial calendar.
3. Launches and announcements
New products, features, partnerships, events.
4. Public perception
Sentiment, complaints, praise, spontaneous comparisons with other brands.
5. Pricing and offer positioning
Price changes, promotions, packaging, special offers.
Build the reporting system
Competitive report class
from datetime import datetime, timedelta
import json
class RapportConcurrentiel:
def __init__(self, client, marque_propre, concurrents):
self.client = client
self.marque = marque_propre
self.concurrents = concurrents
def collecter_donnees_x(self, handles, start, end):
response = self.client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Collect and analyze posts
from these accounts from {start} to {end}.
Provide for each account:
- Estimated number of posts
- Content types (text, image, video, thread)
- Most engaging posts
- Main themes covered
- Observed tone and positioning
- Detected announcements or launches""",
tools=[{
"type": "x_search",
"allowed_x_handles": handles,
"from_date": start,
"to_date": end,
"enable_image_understanding": True
}]
)
return response.output_text
def collecter_donnees_web(self, concurrent, start, end):
response = self.client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Search for recent news regarding
{concurrent} between {start} and {end}.
Focus on:
- Press releases and news articles
- Product or service updates
- Leadership team changes
- Fundraising or financial results
- Strategic partnerships""",
tools=[{
"type": "web_search",
"allowed_domains": [
"techcrunch.com", "lesechos.fr",
"usine-digitale.fr"
]
}]
)
return response.output_text
Generate the compiled report
def generer_rapport(self, periode_jours=30):
end = datetime.now().strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(
days=periode_jours)).strftime("%Y-%m-%d")
sections = {}
# Collect data for each competitor
for concurrent in self.concurrents:
handles = concurrent.get("handles", [])
nom = concurrent["nom"]
donnees_x = self.collecter_donnees_x(
handles, start, end
) if handles else "No X data"
donnees_web = self.collecter_donnees_web(
nom, start, end
)
sections[nom] = {
"x": donnees_x,
"web": donnees_web
}
# Comparative summary
rapport_final = self.client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Compile this monthly competitive report.
Our brand: {self.marque}
Period: {start} to {end}
DATA PER COMPETITOR:
{json.dumps(sections, ensure_ascii=False, indent=2)}
Report structure:
1. EXECUTIVE SUMMARY (5 bullet points max)
2. COMPARATIVE TABLE (activity, sentiment, innovation)
3. ANALYSIS PER COMPETITOR (strengths, weaknesses, moves)
4. IDENTIFIED THREATS (ranked by urgency)
5. OPPORTUNITIES FOR {self.marque}
6. STRATEGIC RECOMMENDATIONS (3-5 priority actions)"""
).output_text
return rapport_final
Structure the report in usable JSON
To feed a dashboard or database, request a structured format:
def rapport_json(self, periode_jours=30):
end = datetime.now().strftime("%Y-%m-%d")
start = (datetime.now() - timedelta(
days=periode_jours)).strftime("%Y-%m-%d")
response = self.client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Generate a competitive report in JSON.
Competitors: {json.dumps([c['nom'] for c in self.concurrents])}
Period: {start} to {end}
Expected format:
{{
"period": "{start} - {end}",
"competitors": [
{{
"name": "Competitor A",
"social_activity": {{
"post_volume": 45,
"average_engagement": "high",
"dominant_formats": ["image", "thread"]
}},
"public_sentiment": 3.8,
"innovations": ["description"],
"threats": ["description"],
"main_strength": "description",
"main_weakness": "description"
}}
],
"recommendations": ["action 1", "action 2"]
}}""",
tools=[
{"type": "x_search", "from_date": start, "to_date": end},
{"type": "web_search"}
]
)
return response.output_text
Compare periods to detect changes
The value of an automated system lies in temporal comparison:
def comparer_rapports(rapport_actuel, rapport_precedent):
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input=f"""Compare these two consecutive
competitive reports and identify significant changes:
PREVIOUS REPORT: {rapport_precedent}
CURRENT REPORT: {rapport_actuel}
Analysis:
1. Which competitors changed strategy?
2. What new threats appeared?
3. What opportunities opened or closed?
4. What trends are confirmed or reversing?
5. Recommended immediate actions."""
)
return response.output_text
Schedule recurring execution
Integrate your report into a cron job or Python scheduler:
# Weekly execution
rapport = RapportConcurrentiel(
client=client,
marque_propre="Your Brand",
concurrents=[
{
"nom": "Competitor A",
"handles": ["competitor_a", "competitor_a_fr"]
},
{
"nom": "Competitor B",
"handles": ["competitor_b"]
},
{
"nom": "Competitor C",
"handles": ["competitor_c"]
}
]
)
# Weekly report
resultat = rapport.generer_rapport(periode_jours=7)
# Archive the report
with open(f"reports/competitor_{datetime.now().strftime('%Y-%m-%d')}.md",
"w") as f:
f.write(resultat)
Best practices for usable reports
- Consistency: always use the same structure to facilitate comparison
- Prioritization: rank insights by business impact, not volume
- Actionability: every section must lead to a recommendation
- Distribution: adapt the format to the recipient (executive = summary, operational = detail)
- Archiving: keep all reports for long-term trend analysis
Key takeaways
- An automated competitive report covers 5 axes: social, content, launches, perception, pricing
- Combine X Search and Web Search for a complete view of each competitor
- Structure results in JSON to feed your dashboards
- Comparison between periods reveals strategic changes
- Every insight must lead to an actionable recommendation
- Systematically archive your reports for long-term tracking