974 lines
42 KiB
Python
974 lines
42 KiB
Python
"""
|
|
AI Analytics Service
|
|
Advanced AI-powered analytics for content planning and performance prediction.
|
|
"""
|
|
|
|
from typing import Dict, Any, List, Optional, Tuple
|
|
from datetime import datetime, timedelta
|
|
import json
|
|
from loguru import logger
|
|
import asyncio
|
|
from sqlalchemy.orm import Session
|
|
|
|
from services.database import get_db_session
|
|
from models.content_planning import ContentAnalytics, ContentStrategy, CalendarEvent
|
|
from services.content_gap_analyzer.ai_engine_service import AIEngineService
|
|
|
|
class AIAnalyticsService:
|
|
"""Advanced AI analytics service for content planning."""
|
|
|
|
def __init__(self):
|
|
self.ai_engine = AIEngineService()
|
|
self.db_session = None
|
|
|
|
def _get_db_session(self) -> Session:
|
|
"""Get database session."""
|
|
if not self.db_session:
|
|
self.db_session = get_db_session()
|
|
return self.db_session
|
|
|
|
async def analyze_content_evolution(self, strategy_id: int, time_period: str = "30d") -> Dict[str, Any]:
|
|
"""
|
|
Analyze content evolution over time for a specific strategy.
|
|
|
|
Args:
|
|
strategy_id: Content strategy ID
|
|
time_period: Analysis period (7d, 30d, 90d, 1y)
|
|
|
|
Returns:
|
|
Content evolution analysis results
|
|
"""
|
|
try:
|
|
logger.info(f"Analyzing content evolution for strategy {strategy_id}")
|
|
|
|
# Get analytics data for the strategy
|
|
analytics_data = await self._get_analytics_data(strategy_id, time_period)
|
|
|
|
# Analyze content performance trends
|
|
performance_trends = await self._analyze_performance_trends(analytics_data)
|
|
|
|
# Analyze content type evolution
|
|
content_evolution = await self._analyze_content_type_evolution(analytics_data)
|
|
|
|
# Analyze audience engagement patterns
|
|
engagement_patterns = await self._analyze_engagement_patterns(analytics_data)
|
|
|
|
evolution_analysis = {
|
|
'strategy_id': strategy_id,
|
|
'time_period': time_period,
|
|
'performance_trends': performance_trends,
|
|
'content_evolution': content_evolution,
|
|
'engagement_patterns': engagement_patterns,
|
|
'recommendations': await self._generate_evolution_recommendations(
|
|
performance_trends, content_evolution, engagement_patterns
|
|
),
|
|
'analysis_date': datetime.utcnow().isoformat()
|
|
}
|
|
|
|
logger.info(f"Content evolution analysis completed for strategy {strategy_id}")
|
|
return evolution_analysis
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing content evolution: {str(e)}")
|
|
raise
|
|
|
|
async def analyze_performance_trends(self, strategy_id: int, metrics: List[str] = None) -> Dict[str, Any]:
|
|
"""
|
|
Analyze performance trends for content strategy.
|
|
|
|
Args:
|
|
strategy_id: Content strategy ID
|
|
metrics: List of metrics to analyze (engagement, reach, conversion, etc.)
|
|
|
|
Returns:
|
|
Performance trend analysis results
|
|
"""
|
|
try:
|
|
logger.info(f"Analyzing performance trends for strategy {strategy_id}")
|
|
|
|
if not metrics:
|
|
metrics = ['engagement_rate', 'reach', 'conversion_rate', 'click_through_rate']
|
|
|
|
# Get performance data
|
|
performance_data = await self._get_performance_data(strategy_id, metrics)
|
|
|
|
# Analyze trends for each metric
|
|
trend_analysis = {}
|
|
for metric in metrics:
|
|
trend_analysis[metric] = await self._analyze_metric_trend(performance_data, metric)
|
|
|
|
# Generate predictive insights
|
|
predictive_insights = await self._generate_predictive_insights(trend_analysis)
|
|
|
|
# Calculate performance scores
|
|
performance_scores = await self._calculate_performance_scores(trend_analysis)
|
|
|
|
trend_results = {
|
|
'strategy_id': strategy_id,
|
|
'metrics_analyzed': metrics,
|
|
'trend_analysis': trend_analysis,
|
|
'predictive_insights': predictive_insights,
|
|
'performance_scores': performance_scores,
|
|
'recommendations': await self._generate_trend_recommendations(trend_analysis),
|
|
'analysis_date': datetime.utcnow().isoformat()
|
|
}
|
|
|
|
logger.info(f"Performance trend analysis completed for strategy {strategy_id}")
|
|
return trend_results
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing performance trends: {str(e)}")
|
|
raise
|
|
|
|
async def predict_content_performance(self, content_data: Dict[str, Any],
|
|
strategy_id: int) -> Dict[str, Any]:
|
|
"""
|
|
Predict content performance using AI models.
|
|
|
|
Args:
|
|
content_data: Content details (title, description, type, platform, etc.)
|
|
strategy_id: Content strategy ID
|
|
|
|
Returns:
|
|
Performance prediction results
|
|
"""
|
|
try:
|
|
logger.info(f"Predicting performance for content in strategy {strategy_id}")
|
|
|
|
# Get historical performance data
|
|
historical_data = await self._get_historical_performance_data(strategy_id)
|
|
|
|
# Analyze content characteristics
|
|
content_analysis = await self._analyze_content_characteristics(content_data)
|
|
|
|
# Calculate success probability
|
|
success_probability = await self._calculate_success_probability({}, historical_data)
|
|
|
|
# Generate optimization recommendations
|
|
optimization_recommendations = await self._generate_optimization_recommendations(
|
|
content_data, {}, success_probability
|
|
)
|
|
|
|
prediction_results = {
|
|
'strategy_id': strategy_id,
|
|
'content_data': content_data,
|
|
'performance_prediction': {},
|
|
'success_probability': success_probability,
|
|
'optimization_recommendations': optimization_recommendations,
|
|
'confidence_score': 0.7,
|
|
'prediction_date': datetime.utcnow().isoformat()
|
|
}
|
|
|
|
logger.info(f"Content performance prediction completed")
|
|
return prediction_results
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error predicting content performance: {str(e)}")
|
|
raise
|
|
|
|
async def generate_strategic_intelligence(self, strategy_id: int,
|
|
market_data: Dict[str, Any] = None) -> Dict[str, Any]:
|
|
"""
|
|
Generate strategic intelligence for content planning.
|
|
|
|
Args:
|
|
strategy_id: Content strategy ID
|
|
market_data: Additional market data for analysis
|
|
|
|
Returns:
|
|
Strategic intelligence results
|
|
"""
|
|
try:
|
|
logger.info(f"Generating strategic intelligence for strategy {strategy_id}")
|
|
|
|
# Get strategy data
|
|
strategy_data = await self._get_strategy_data(strategy_id)
|
|
|
|
# Analyze market positioning
|
|
market_positioning = await self._analyze_market_positioning(strategy_data, market_data)
|
|
|
|
# Identify competitive advantages
|
|
competitive_advantages = await self._identify_competitive_advantages(strategy_data)
|
|
|
|
# Calculate strategic scores
|
|
strategic_scores = await self._calculate_strategic_scores(
|
|
strategy_data, market_positioning, competitive_advantages
|
|
)
|
|
|
|
intelligence_results = {
|
|
'strategy_id': strategy_id,
|
|
'market_positioning': market_positioning,
|
|
'competitive_advantages': competitive_advantages,
|
|
'strategic_scores': strategic_scores,
|
|
'risk_assessment': await self._assess_strategic_risks(strategy_data),
|
|
'opportunity_analysis': await self._analyze_strategic_opportunities(strategy_data),
|
|
'analysis_date': datetime.utcnow().isoformat()
|
|
}
|
|
|
|
logger.info(f"Strategic intelligence generation completed")
|
|
return intelligence_results
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating strategic intelligence: {str(e)}")
|
|
raise
|
|
|
|
# Helper methods for data retrieval and analysis
|
|
async def _get_analytics_data(self, strategy_id: int, time_period: str) -> List[Dict[str, Any]]:
|
|
"""Get analytics data for the specified strategy and time period."""
|
|
try:
|
|
session = self._get_db_session()
|
|
|
|
# Calculate date range
|
|
end_date = datetime.utcnow()
|
|
if time_period == "7d":
|
|
start_date = end_date - timedelta(days=7)
|
|
elif time_period == "30d":
|
|
start_date = end_date - timedelta(days=30)
|
|
elif time_period == "90d":
|
|
start_date = end_date - timedelta(days=90)
|
|
elif time_period == "1y":
|
|
start_date = end_date - timedelta(days=365)
|
|
else:
|
|
start_date = end_date - timedelta(days=30)
|
|
|
|
# Query analytics data
|
|
analytics = session.query(ContentAnalytics).filter(
|
|
ContentAnalytics.strategy_id == strategy_id,
|
|
ContentAnalytics.recorded_at >= start_date,
|
|
ContentAnalytics.recorded_at <= end_date
|
|
).all()
|
|
|
|
return [analytics.to_dict() for analytics in analytics]
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting analytics data: {str(e)}")
|
|
return []
|
|
|
|
async def _analyze_performance_trends(self, analytics_data: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Analyze performance trends from analytics data."""
|
|
try:
|
|
if not analytics_data:
|
|
return {'trend': 'stable', 'growth_rate': 0, 'insights': 'No data available'}
|
|
|
|
# Calculate trend metrics
|
|
total_analytics = len(analytics_data)
|
|
avg_performance = sum(item.get('performance_score', 0) for item in analytics_data) / total_analytics
|
|
|
|
# Determine trend direction
|
|
if avg_performance > 0.7:
|
|
trend = 'increasing'
|
|
elif avg_performance < 0.3:
|
|
trend = 'decreasing'
|
|
else:
|
|
trend = 'stable'
|
|
|
|
return {
|
|
'trend': trend,
|
|
'average_performance': avg_performance,
|
|
'total_analytics': total_analytics,
|
|
'insights': f'Performance is {trend} with average score of {avg_performance:.2f}'
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing performance trends: {str(e)}")
|
|
return {'trend': 'unknown', 'error': str(e)}
|
|
|
|
async def _analyze_content_type_evolution(self, analytics_data: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Analyze how content types have evolved over time."""
|
|
try:
|
|
content_types = {}
|
|
for data in analytics_data:
|
|
content_type = data.get('content_type', 'unknown')
|
|
if content_type not in content_types:
|
|
content_types[content_type] = {
|
|
'count': 0,
|
|
'total_performance': 0,
|
|
'avg_performance': 0
|
|
}
|
|
|
|
content_types[content_type]['count'] += 1
|
|
content_types[content_type]['total_performance'] += data.get('performance_score', 0)
|
|
|
|
# Calculate averages
|
|
for content_type in content_types:
|
|
if content_types[content_type]['count'] > 0:
|
|
content_types[content_type]['avg_performance'] = (
|
|
content_types[content_type]['total_performance'] /
|
|
content_types[content_type]['count']
|
|
)
|
|
|
|
return {
|
|
'content_types': content_types,
|
|
'most_performing_type': max(content_types.items(), key=lambda x: x[1]['avg_performance'])[0] if content_types else None,
|
|
'evolution_insights': 'Content type performance analysis completed'
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing content type evolution: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _analyze_engagement_patterns(self, analytics_data: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Analyze audience engagement patterns."""
|
|
try:
|
|
if not analytics_data:
|
|
return {'patterns': {}, 'insights': 'No engagement data available'}
|
|
|
|
# Analyze engagement by platform
|
|
platform_engagement = {}
|
|
for data in analytics_data:
|
|
platform = data.get('platform', 'unknown')
|
|
if platform not in platform_engagement:
|
|
platform_engagement[platform] = {
|
|
'total_engagement': 0,
|
|
'count': 0,
|
|
'avg_engagement': 0
|
|
}
|
|
|
|
metrics = data.get('metrics', {})
|
|
engagement = metrics.get('engagement_rate', 0)
|
|
platform_engagement[platform]['total_engagement'] += engagement
|
|
platform_engagement[platform]['count'] += 1
|
|
|
|
# Calculate averages
|
|
for platform in platform_engagement:
|
|
if platform_engagement[platform]['count'] > 0:
|
|
platform_engagement[platform]['avg_engagement'] = (
|
|
platform_engagement[platform]['total_engagement'] /
|
|
platform_engagement[platform]['count']
|
|
)
|
|
|
|
return {
|
|
'platform_engagement': platform_engagement,
|
|
'best_platform': max(platform_engagement.items(), key=lambda x: x[1]['avg_engagement'])[0] if platform_engagement else None,
|
|
'insights': 'Platform engagement analysis completed'
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing engagement patterns: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _generate_evolution_recommendations(self, performance_trends: Dict[str, Any],
|
|
content_evolution: Dict[str, Any],
|
|
engagement_patterns: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Generate recommendations based on evolution analysis."""
|
|
recommendations = []
|
|
|
|
try:
|
|
# Performance-based recommendations
|
|
if performance_trends.get('trend') == 'decreasing':
|
|
recommendations.append({
|
|
'type': 'performance_optimization',
|
|
'priority': 'high',
|
|
'title': 'Improve Content Performance',
|
|
'description': 'Content performance is declining. Focus on quality and engagement.',
|
|
'action_items': [
|
|
'Review and improve content quality',
|
|
'Optimize for audience engagement',
|
|
'Analyze competitor strategies'
|
|
]
|
|
})
|
|
|
|
# Content type recommendations
|
|
if content_evolution.get('most_performing_type'):
|
|
best_type = content_evolution['most_performing_type']
|
|
recommendations.append({
|
|
'type': 'content_strategy',
|
|
'priority': 'medium',
|
|
'title': f'Focus on {best_type} Content',
|
|
'description': f'{best_type} content is performing best. Increase focus on this type.',
|
|
'action_items': [
|
|
f'Increase {best_type} content production',
|
|
'Analyze what makes this content successful',
|
|
'Optimize other content types based on learnings'
|
|
]
|
|
})
|
|
|
|
# Platform recommendations
|
|
if engagement_patterns.get('best_platform'):
|
|
best_platform = engagement_patterns['best_platform']
|
|
recommendations.append({
|
|
'type': 'platform_strategy',
|
|
'priority': 'medium',
|
|
'title': f'Optimize for {best_platform}',
|
|
'description': f'{best_platform} shows highest engagement. Focus optimization efforts here.',
|
|
'action_items': [
|
|
f'Increase content for {best_platform}',
|
|
f'Optimize content format for platform',
|
|
'Use platform-specific features'
|
|
]
|
|
})
|
|
|
|
return recommendations
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating evolution recommendations: {str(e)}")
|
|
return [{'error': str(e)}]
|
|
|
|
async def _get_performance_data(self, strategy_id: int, metrics: List[str]) -> List[Dict[str, Any]]:
|
|
"""Get performance data for specified metrics."""
|
|
try:
|
|
session = self._get_db_session()
|
|
|
|
# Get analytics data for the strategy
|
|
analytics = session.query(ContentAnalytics).filter(
|
|
ContentAnalytics.strategy_id == strategy_id
|
|
).all()
|
|
|
|
return [analytics.to_dict() for analytics in analytics]
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting performance data: {str(e)}")
|
|
return []
|
|
|
|
async def _analyze_metric_trend(self, performance_data: List[Dict[str, Any]], metric: str) -> Dict[str, Any]:
|
|
"""Analyze trend for a specific metric."""
|
|
try:
|
|
if not performance_data:
|
|
return {'trend': 'no_data', 'value': 0, 'change': 0}
|
|
|
|
# Extract metric values
|
|
metric_values = []
|
|
for data in performance_data:
|
|
metrics = data.get('metrics', {})
|
|
if metric in metrics:
|
|
metric_values.append(metrics[metric])
|
|
|
|
if not metric_values:
|
|
return {'trend': 'no_data', 'value': 0, 'change': 0}
|
|
|
|
# Calculate trend
|
|
avg_value = sum(metric_values) / len(metric_values)
|
|
|
|
# Simple trend calculation
|
|
if len(metric_values) >= 2:
|
|
recent_avg = sum(metric_values[-len(metric_values)//2:]) / (len(metric_values)//2)
|
|
older_avg = sum(metric_values[:len(metric_values)//2]) / (len(metric_values)//2)
|
|
change = ((recent_avg - older_avg) / older_avg * 100) if older_avg > 0 else 0
|
|
else:
|
|
change = 0
|
|
|
|
# Determine trend direction
|
|
if change > 5:
|
|
trend = 'increasing'
|
|
elif change < -5:
|
|
trend = 'decreasing'
|
|
else:
|
|
trend = 'stable'
|
|
|
|
return {
|
|
'trend': trend,
|
|
'value': avg_value,
|
|
'change_percent': change,
|
|
'data_points': len(metric_values)
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing metric trend: {str(e)}")
|
|
return {'trend': 'error', 'error': str(e)}
|
|
|
|
async def _generate_predictive_insights(self, trend_analysis: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Generate predictive insights based on trend analysis."""
|
|
try:
|
|
insights = {
|
|
'predicted_performance': 'stable',
|
|
'confidence_level': 'medium',
|
|
'key_factors': [],
|
|
'recommendations': []
|
|
}
|
|
|
|
# Analyze trends to generate insights
|
|
increasing_metrics = []
|
|
decreasing_metrics = []
|
|
|
|
for metric, analysis in trend_analysis.items():
|
|
if analysis.get('trend') == 'increasing':
|
|
increasing_metrics.append(metric)
|
|
elif analysis.get('trend') == 'decreasing':
|
|
decreasing_metrics.append(metric)
|
|
|
|
if len(increasing_metrics) > len(decreasing_metrics):
|
|
insights['predicted_performance'] = 'improving'
|
|
insights['confidence_level'] = 'high' if len(increasing_metrics) > 2 else 'medium'
|
|
elif len(decreasing_metrics) > len(increasing_metrics):
|
|
insights['predicted_performance'] = 'declining'
|
|
insights['confidence_level'] = 'high' if len(decreasing_metrics) > 2 else 'medium'
|
|
|
|
insights['key_factors'] = increasing_metrics + decreasing_metrics
|
|
insights['recommendations'] = [
|
|
f'Focus on improving {", ".join(decreasing_metrics)}' if decreasing_metrics else 'Maintain current performance',
|
|
f'Leverage success in {", ".join(increasing_metrics)}' if increasing_metrics else 'Identify new growth opportunities'
|
|
]
|
|
|
|
return insights
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating predictive insights: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _calculate_performance_scores(self, trend_analysis: Dict[str, Any]) -> Dict[str, float]:
|
|
"""Calculate performance scores based on trend analysis."""
|
|
try:
|
|
scores = {}
|
|
|
|
for metric, analysis in trend_analysis.items():
|
|
base_score = analysis.get('value', 0)
|
|
change = analysis.get('change_percent', 0)
|
|
|
|
# Adjust score based on trend
|
|
if analysis.get('trend') == 'increasing':
|
|
adjusted_score = base_score * (1 + abs(change) / 100)
|
|
elif analysis.get('trend') == 'decreasing':
|
|
adjusted_score = base_score * (1 - abs(change) / 100)
|
|
else:
|
|
adjusted_score = base_score
|
|
|
|
scores[metric] = min(adjusted_score, 1.0) # Cap at 1.0
|
|
|
|
return scores
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error calculating performance scores: {str(e)}")
|
|
return {}
|
|
|
|
async def _generate_trend_recommendations(self, trend_analysis: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Generate recommendations based on trend analysis."""
|
|
recommendations = []
|
|
|
|
try:
|
|
for metric, analysis in trend_analysis.items():
|
|
if analysis.get('trend') == 'decreasing':
|
|
recommendations.append({
|
|
'type': 'metric_optimization',
|
|
'priority': 'high',
|
|
'metric': metric,
|
|
'title': f'Improve {metric.replace("_", " ").title()}',
|
|
'description': f'{metric} is declining. Focus on optimization.',
|
|
'action_items': [
|
|
f'Analyze factors affecting {metric}',
|
|
'Review content strategy for this metric',
|
|
'Implement optimization strategies'
|
|
]
|
|
})
|
|
elif analysis.get('trend') == 'increasing':
|
|
recommendations.append({
|
|
'type': 'metric_leverage',
|
|
'priority': 'medium',
|
|
'metric': metric,
|
|
'title': f'Leverage {metric.replace("_", " ").title()} Success',
|
|
'description': f'{metric} is improving. Build on this success.',
|
|
'action_items': [
|
|
f'Identify what\'s driving {metric} improvement',
|
|
'Apply successful strategies to other metrics',
|
|
'Scale successful approaches'
|
|
]
|
|
})
|
|
|
|
return recommendations
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating trend recommendations: {str(e)}")
|
|
return [{'error': str(e)}]
|
|
|
|
async def _analyze_single_competitor(self, url: str, analysis_period: str) -> Dict[str, Any]:
|
|
"""Analyze a single competitor's content strategy."""
|
|
try:
|
|
# This would integrate with the competitor analyzer service
|
|
# For now, return mock data
|
|
return {
|
|
'url': url,
|
|
'content_frequency': 'weekly',
|
|
'content_types': ['blog', 'video', 'social'],
|
|
'engagement_rate': 0.75,
|
|
'top_performing_content': ['How-to guides', 'Industry insights'],
|
|
'publishing_schedule': ['Tuesday', 'Thursday'],
|
|
'content_themes': ['Educational', 'Thought leadership', 'Engagement']
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing competitor {url}: {str(e)}")
|
|
return {'url': url, 'error': str(e)}
|
|
|
|
async def _compare_competitor_strategies(self, competitor_analyses: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Compare strategies across competitors."""
|
|
try:
|
|
if not competitor_analyses:
|
|
return {'comparison': 'no_data'}
|
|
|
|
# Analyze common patterns
|
|
content_types = set()
|
|
themes = set()
|
|
schedules = set()
|
|
|
|
for analysis in competitor_analyses:
|
|
if 'content_types' in analysis:
|
|
content_types.update(analysis['content_types'])
|
|
if 'content_themes' in analysis:
|
|
themes.update(analysis['content_themes'])
|
|
if 'publishing_schedule' in analysis:
|
|
schedules.update(analysis['publishing_schedule'])
|
|
|
|
return {
|
|
'common_content_types': list(content_types),
|
|
'common_themes': list(themes),
|
|
'common_schedules': list(schedules),
|
|
'competitive_landscape': 'analyzed',
|
|
'insights': f'Found {len(content_types)} content types, {len(themes)} themes across competitors'
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error comparing competitor strategies: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _identify_market_trends(self, competitor_analyses: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Identify market trends from competitor analysis."""
|
|
try:
|
|
trends = {
|
|
'popular_content_types': [],
|
|
'emerging_themes': [],
|
|
'publishing_patterns': [],
|
|
'engagement_trends': []
|
|
}
|
|
|
|
# Analyze trends from competitor data
|
|
content_type_counts = {}
|
|
theme_counts = {}
|
|
|
|
for analysis in competitor_analyses:
|
|
for content_type in analysis.get('content_types', []):
|
|
content_type_counts[content_type] = content_type_counts.get(content_type, 0) + 1
|
|
|
|
for theme in analysis.get('content_themes', []):
|
|
theme_counts[theme] = theme_counts.get(theme, 0) + 1
|
|
|
|
trends['popular_content_types'] = sorted(content_type_counts.items(), key=lambda x: x[1], reverse=True)
|
|
trends['emerging_themes'] = sorted(theme_counts.items(), key=lambda x: x[1], reverse=True)
|
|
|
|
return trends
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error identifying market trends: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _generate_competitor_recommendations(self, competitor_analyses: List[Dict[str, Any]],
|
|
strategy_comparison: Dict[str, Any],
|
|
market_trends: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Generate recommendations based on competitor analysis."""
|
|
recommendations = []
|
|
|
|
try:
|
|
# Identify opportunities
|
|
popular_types = [item[0] for item in market_trends.get('popular_content_types', [])]
|
|
if popular_types:
|
|
recommendations.append({
|
|
'type': 'content_strategy',
|
|
'priority': 'high',
|
|
'title': 'Focus on Popular Content Types',
|
|
'description': f'Competitors are successfully using: {", ".join(popular_types[:3])}',
|
|
'action_items': [
|
|
'Analyze successful content in these categories',
|
|
'Develop content strategy for popular types',
|
|
'Differentiate while following proven patterns'
|
|
]
|
|
})
|
|
|
|
# Identify gaps
|
|
all_competitor_themes = set()
|
|
for analysis in competitor_analyses:
|
|
all_competitor_themes.update(analysis.get('content_themes', []))
|
|
|
|
if all_competitor_themes:
|
|
recommendations.append({
|
|
'type': 'competitive_advantage',
|
|
'priority': 'medium',
|
|
'title': 'Identify Content Gaps',
|
|
'description': 'Look for opportunities competitors are missing',
|
|
'action_items': [
|
|
'Analyze underserved content areas',
|
|
'Identify unique positioning opportunities',
|
|
'Develop differentiated content strategy'
|
|
]
|
|
})
|
|
|
|
return recommendations
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating competitor recommendations: {str(e)}")
|
|
return [{'error': str(e)}]
|
|
|
|
async def _get_historical_performance_data(self, strategy_id: int) -> List[Dict[str, Any]]:
|
|
"""Get historical performance data for the strategy."""
|
|
try:
|
|
session = self._get_db_session()
|
|
|
|
analytics = session.query(ContentAnalytics).filter(
|
|
ContentAnalytics.strategy_id == strategy_id
|
|
).all()
|
|
|
|
return [analytics.to_dict() for analytics in analytics]
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting historical performance data: {str(e)}")
|
|
return []
|
|
|
|
async def _analyze_content_characteristics(self, content_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Analyze content characteristics for performance prediction."""
|
|
try:
|
|
characteristics = {
|
|
'content_type': content_data.get('content_type', 'unknown'),
|
|
'platform': content_data.get('platform', 'unknown'),
|
|
'estimated_length': content_data.get('estimated_length', 'medium'),
|
|
'complexity': 'medium',
|
|
'engagement_potential': 'medium',
|
|
'seo_potential': 'medium'
|
|
}
|
|
|
|
# Analyze title and description
|
|
title = content_data.get('title', '')
|
|
description = content_data.get('description', '')
|
|
|
|
if title and description:
|
|
characteristics['content_richness'] = 'high' if len(description) > 200 else 'medium'
|
|
characteristics['title_optimization'] = 'good' if len(title) > 20 and len(title) < 60 else 'needs_improvement'
|
|
|
|
return characteristics
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing content characteristics: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _calculate_success_probability(self, performance_prediction: Dict[str, Any],
|
|
historical_data: List[Dict[str, Any]]) -> float:
|
|
"""Calculate success probability based on prediction and historical data."""
|
|
try:
|
|
base_probability = 0.5
|
|
|
|
# Adjust based on historical performance
|
|
if historical_data:
|
|
avg_historical_performance = sum(
|
|
data.get('performance_score', 0) for data in historical_data
|
|
) / len(historical_data)
|
|
|
|
if avg_historical_performance > 0.7:
|
|
base_probability += 0.1
|
|
elif avg_historical_performance < 0.3:
|
|
base_probability -= 0.1
|
|
|
|
return min(max(base_probability, 0.0), 1.0)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error calculating success probability: {str(e)}")
|
|
return 0.5
|
|
|
|
async def _generate_optimization_recommendations(self, content_data: Dict[str, Any],
|
|
performance_prediction: Dict[str, Any],
|
|
success_probability: float) -> List[Dict[str, Any]]:
|
|
"""Generate optimization recommendations for content."""
|
|
recommendations = []
|
|
|
|
try:
|
|
# Performance-based recommendations
|
|
if success_probability < 0.5:
|
|
recommendations.append({
|
|
'type': 'content_optimization',
|
|
'priority': 'high',
|
|
'title': 'Improve Content Quality',
|
|
'description': 'Content has low success probability. Focus on quality improvements.',
|
|
'action_items': [
|
|
'Enhance content depth and value',
|
|
'Improve title and description',
|
|
'Optimize for target audience'
|
|
]
|
|
})
|
|
|
|
# Platform-specific recommendations
|
|
platform = content_data.get('platform', '')
|
|
if platform:
|
|
recommendations.append({
|
|
'type': 'platform_optimization',
|
|
'priority': 'medium',
|
|
'title': f'Optimize for {platform}',
|
|
'description': f'Ensure content is optimized for {platform} platform.',
|
|
'action_items': [
|
|
f'Follow {platform} best practices',
|
|
'Optimize content format for platform',
|
|
'Use platform-specific features'
|
|
]
|
|
})
|
|
|
|
return recommendations
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating optimization recommendations: {str(e)}")
|
|
return [{'error': str(e)}]
|
|
|
|
async def _get_strategy_data(self, strategy_id: int) -> Dict[str, Any]:
|
|
"""Get strategy data for analysis."""
|
|
try:
|
|
session = self._get_db_session()
|
|
|
|
strategy = session.query(ContentStrategy).filter(
|
|
ContentStrategy.id == strategy_id
|
|
).first()
|
|
|
|
if strategy:
|
|
return strategy.to_dict()
|
|
else:
|
|
return {}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting strategy data: {str(e)}")
|
|
return {}
|
|
|
|
async def _analyze_market_positioning(self, strategy_data: Dict[str, Any],
|
|
market_data: Dict[str, Any] = None) -> Dict[str, Any]:
|
|
"""Analyze market positioning for the strategy."""
|
|
try:
|
|
positioning = {
|
|
'industry_position': 'established',
|
|
'competitive_advantage': 'content_quality',
|
|
'market_share': 'medium',
|
|
'differentiation_factors': []
|
|
}
|
|
|
|
# Analyze based on strategy data
|
|
industry = strategy_data.get('industry', '')
|
|
if industry:
|
|
positioning['industry_position'] = 'established' if industry in ['tech', 'finance', 'healthcare'] else 'emerging'
|
|
|
|
# Analyze content pillars
|
|
content_pillars = strategy_data.get('content_pillars', [])
|
|
if content_pillars:
|
|
positioning['differentiation_factors'] = [pillar.get('name', '') for pillar in content_pillars]
|
|
|
|
return positioning
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing market positioning: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _identify_competitive_advantages(self, strategy_data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Identify competitive advantages for the strategy."""
|
|
try:
|
|
advantages = []
|
|
|
|
# Analyze content pillars for advantages
|
|
content_pillars = strategy_data.get('content_pillars', [])
|
|
for pillar in content_pillars:
|
|
advantages.append({
|
|
'type': 'content_pillar',
|
|
'name': pillar.get('name', ''),
|
|
'description': pillar.get('description', ''),
|
|
'strength': 'high' if pillar.get('frequency') == 'weekly' else 'medium'
|
|
})
|
|
|
|
# Analyze target audience
|
|
target_audience = strategy_data.get('target_audience', {})
|
|
if target_audience:
|
|
advantages.append({
|
|
'type': 'audience_focus',
|
|
'name': 'Targeted Audience',
|
|
'description': 'Well-defined target audience',
|
|
'strength': 'high'
|
|
})
|
|
|
|
return advantages
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error identifying competitive advantages: {str(e)}")
|
|
return []
|
|
|
|
async def _calculate_strategic_scores(self, strategy_data: Dict[str, Any],
|
|
market_positioning: Dict[str, Any],
|
|
competitive_advantages: List[Dict[str, Any]]) -> Dict[str, float]:
|
|
"""Calculate strategic scores for the strategy."""
|
|
try:
|
|
scores = {
|
|
'market_positioning_score': 0.7,
|
|
'competitive_advantage_score': 0.8,
|
|
'content_strategy_score': 0.75,
|
|
'overall_strategic_score': 0.75
|
|
}
|
|
|
|
# Adjust scores based on analysis
|
|
if market_positioning.get('industry_position') == 'established':
|
|
scores['market_positioning_score'] += 0.1
|
|
|
|
if len(competitive_advantages) > 2:
|
|
scores['competitive_advantage_score'] += 0.1
|
|
|
|
# Calculate overall score
|
|
scores['overall_strategic_score'] = sum(scores.values()) / len(scores)
|
|
|
|
return scores
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error calculating strategic scores: {str(e)}")
|
|
return {'error': str(e)}
|
|
|
|
async def _assess_strategic_risks(self, strategy_data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Assess strategic risks for the strategy."""
|
|
try:
|
|
risks = []
|
|
|
|
# Analyze potential risks
|
|
content_pillars = strategy_data.get('content_pillars', [])
|
|
if len(content_pillars) < 2:
|
|
risks.append({
|
|
'type': 'content_diversity',
|
|
'severity': 'medium',
|
|
'description': 'Limited content pillar diversity',
|
|
'mitigation': 'Develop additional content pillars'
|
|
})
|
|
|
|
target_audience = strategy_data.get('target_audience', {})
|
|
if not target_audience:
|
|
risks.append({
|
|
'type': 'audience_definition',
|
|
'severity': 'high',
|
|
'description': 'Unclear target audience definition',
|
|
'mitigation': 'Define detailed audience personas'
|
|
})
|
|
|
|
return risks
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error assessing strategic risks: {str(e)}")
|
|
return []
|
|
|
|
async def _analyze_strategic_opportunities(self, strategy_data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Analyze strategic opportunities for the strategy."""
|
|
try:
|
|
opportunities = []
|
|
|
|
# Identify opportunities based on strategy data
|
|
industry = strategy_data.get('industry', '')
|
|
if industry:
|
|
opportunities.append({
|
|
'type': 'industry_growth',
|
|
'priority': 'high',
|
|
'description': f'Growing {industry} industry presents expansion opportunities',
|
|
'action_items': [
|
|
'Monitor industry trends',
|
|
'Develop industry-specific content',
|
|
'Expand into emerging sub-sectors'
|
|
]
|
|
})
|
|
|
|
content_pillars = strategy_data.get('content_pillars', [])
|
|
if content_pillars:
|
|
opportunities.append({
|
|
'type': 'content_expansion',
|
|
'priority': 'medium',
|
|
'description': 'Opportunity to expand content pillar coverage',
|
|
'action_items': [
|
|
'Identify underserved content areas',
|
|
'Develop new content pillars',
|
|
'Expand into new content formats'
|
|
]
|
|
})
|
|
|
|
return opportunities
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing strategic opportunities: {str(e)}")
|
|
return [] |