787 lines
31 KiB
Python
787 lines
31 KiB
Python
"""
|
|
Enhanced UI for Content Gap Analysis with Advertools Integration.
|
|
|
|
This module provides a comprehensive Streamlit interface for content gap analysis
|
|
using the EnhancedContentGapAnalyzer with advertools and AI insights.
|
|
"""
|
|
|
|
import streamlit as st
|
|
import pandas as pd
|
|
from typing import Dict, Any, List
|
|
import json
|
|
from datetime import datetime
|
|
import io
|
|
import base64
|
|
|
|
from .enhanced_analyzer import EnhancedContentGapAnalyzer
|
|
from lib.alwrity_ui.dashboard_styles import apply_dashboard_style, render_dashboard_header
|
|
|
|
class EnhancedContentGapAnalysisUI:
|
|
"""Enhanced UI for content gap analysis."""
|
|
|
|
def __init__(self):
|
|
"""Initialize the enhanced UI."""
|
|
self.analyzer = EnhancedContentGapAnalyzer()
|
|
|
|
# Apply dashboard styling
|
|
apply_dashboard_style()
|
|
|
|
def render(self):
|
|
"""Render the enhanced content gap analysis interface."""
|
|
|
|
# Enhanced dashboard header
|
|
render_dashboard_header(
|
|
"🎯 Enhanced Content Gap Analysis",
|
|
"Discover content opportunities with AI-powered insights using advertools, SERP analysis, competitor crawling, and strategic recommendations."
|
|
)
|
|
|
|
# Main content area
|
|
with st.container():
|
|
# Analysis input form
|
|
self._render_analysis_form()
|
|
|
|
# Session state for results
|
|
if 'gap_analysis_results' in st.session_state and st.session_state.gap_analysis_results:
|
|
st.markdown("---")
|
|
self._render_results_dashboard(st.session_state.gap_analysis_results)
|
|
|
|
def _render_analysis_form(self):
|
|
"""Render the analysis input form."""
|
|
st.markdown("## 🚀 Setup Your Content Gap Analysis")
|
|
|
|
with st.form("enhanced_gap_analysis_form"):
|
|
# Target website input
|
|
col1, col2 = st.columns([2, 1])
|
|
|
|
with col1:
|
|
target_url = st.text_input(
|
|
"🎯 Your Website URL",
|
|
placeholder="https://yourwebsite.com",
|
|
help="Enter your website URL to analyze"
|
|
)
|
|
|
|
with col2:
|
|
industry = st.selectbox(
|
|
"🏭 Industry",
|
|
options=[
|
|
"general", "technology", "healthcare", "finance",
|
|
"ecommerce", "education", "real estate", "travel",
|
|
"food", "fitness", "marketing", "consulting"
|
|
],
|
|
help="Select your industry for better analysis context"
|
|
)
|
|
|
|
# Competitor URLs
|
|
st.markdown("### 🏆 Competitor Analysis")
|
|
competitor_urls_text = st.text_area(
|
|
"Competitor URLs (one per line, max 5)",
|
|
placeholder="https://competitor1.com\nhttps://competitor2.com\nhttps://competitor3.com",
|
|
height=120,
|
|
help="Enter up to 5 competitor URLs for comprehensive analysis"
|
|
)
|
|
|
|
# Target keywords
|
|
st.markdown("### 🎯 Keyword Focus")
|
|
target_keywords_text = st.text_input(
|
|
"Primary Keywords (comma-separated)",
|
|
placeholder="seo, content marketing, digital marketing",
|
|
help="Enter your main keywords to analyze and expand"
|
|
)
|
|
|
|
# Analysis options
|
|
st.markdown("### ⚙️ Analysis Options")
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
enable_serp = st.checkbox(
|
|
"🔍 SERP Analysis",
|
|
value=True,
|
|
help="Analyze competitor positions in search results"
|
|
)
|
|
|
|
with col2:
|
|
enable_crawling = st.checkbox(
|
|
"🕷️ Deep Crawling",
|
|
value=True,
|
|
help="Perform comprehensive competitor content crawling"
|
|
)
|
|
|
|
with col3:
|
|
enable_ai_insights = st.checkbox(
|
|
"🤖 AI Insights",
|
|
value=True,
|
|
help="Generate AI-powered strategic recommendations"
|
|
)
|
|
|
|
# Submit button
|
|
submitted = st.form_submit_button(
|
|
"🚀 Start Enhanced Analysis",
|
|
use_container_width=True,
|
|
type="primary"
|
|
)
|
|
|
|
if submitted:
|
|
# Validate inputs
|
|
if not target_url or not target_url.startswith(('http://', 'https://')):
|
|
st.error("❌ Please enter a valid target URL starting with http:// or https://")
|
|
return
|
|
|
|
if not target_keywords_text.strip():
|
|
st.error("❌ Please enter at least one target keyword")
|
|
return
|
|
|
|
# Process inputs
|
|
competitor_urls = [
|
|
url.strip() for url in competitor_urls_text.split('\n')
|
|
if url.strip() and url.strip().startswith(('http://', 'https://'))
|
|
]
|
|
|
|
if not competitor_urls:
|
|
st.error("❌ Please enter at least one valid competitor URL")
|
|
return
|
|
|
|
target_keywords = [
|
|
kw.strip() for kw in target_keywords_text.split(',')
|
|
if kw.strip()
|
|
]
|
|
|
|
# Run analysis
|
|
self._run_enhanced_analysis(
|
|
target_url=target_url,
|
|
competitor_urls=competitor_urls,
|
|
target_keywords=target_keywords,
|
|
industry=industry,
|
|
options={
|
|
'enable_serp': enable_serp,
|
|
'enable_crawling': enable_crawling,
|
|
'enable_ai_insights': enable_ai_insights
|
|
}
|
|
)
|
|
|
|
def _run_enhanced_analysis(self, target_url: str, competitor_urls: List[str],
|
|
target_keywords: List[str], industry: str, options: Dict[str, bool]):
|
|
"""Run the enhanced content gap analysis."""
|
|
|
|
try:
|
|
with st.spinner("🔄 Running Enhanced Content Gap Analysis..."):
|
|
|
|
# Initialize progress tracking
|
|
progress_bar = st.progress(0)
|
|
status_text = st.empty()
|
|
|
|
# Update progress
|
|
progress_bar.progress(10)
|
|
status_text.text("🚀 Initializing analysis...")
|
|
|
|
# Run comprehensive analysis
|
|
results = self.analyzer.analyze_comprehensive_gap(
|
|
target_url=target_url,
|
|
competitor_urls=competitor_urls,
|
|
target_keywords=target_keywords,
|
|
industry=industry
|
|
)
|
|
|
|
progress_bar.progress(100)
|
|
status_text.text("✅ Analysis complete!")
|
|
|
|
# Store results in session state
|
|
st.session_state.gap_analysis_results = results
|
|
|
|
# Clear progress indicators
|
|
progress_bar.empty()
|
|
status_text.empty()
|
|
|
|
if 'error' in results:
|
|
st.error(f"❌ Analysis failed: {results['error']}")
|
|
else:
|
|
st.success("🎉 Enhanced Content Gap Analysis completed successfully!")
|
|
st.balloons()
|
|
|
|
# Rerun to show results
|
|
st.rerun()
|
|
|
|
except Exception as e:
|
|
st.error(f"❌ Error running analysis: {str(e)}")
|
|
|
|
def _render_results_dashboard(self, results: Dict[str, Any]):
|
|
"""Render the comprehensive results dashboard."""
|
|
|
|
if 'error' in results:
|
|
st.error(f"❌ Analysis Error: {results['error']}")
|
|
return
|
|
|
|
# Results header
|
|
st.markdown("## 📊 Enhanced Content Gap Analysis Results")
|
|
|
|
# Key metrics overview
|
|
self._render_metrics_overview(results)
|
|
|
|
# Detailed analysis tabs
|
|
self._render_detailed_analysis(results)
|
|
|
|
# Export functionality
|
|
self._render_export_options(results)
|
|
|
|
def _render_metrics_overview(self, results: Dict[str, Any]):
|
|
"""Render key metrics overview."""
|
|
|
|
st.markdown("### 📈 Analysis Overview")
|
|
|
|
# Create metrics columns
|
|
col1, col2, col3, col4, col5 = st.columns(5)
|
|
|
|
with col1:
|
|
st.metric(
|
|
"🎯 Keywords Analyzed",
|
|
len(results.get('target_keywords', [])),
|
|
help="Number of primary keywords analyzed"
|
|
)
|
|
|
|
with col2:
|
|
st.metric(
|
|
"🏆 Competitors Crawled",
|
|
len(results.get('competitor_urls', [])),
|
|
help="Number of competitor websites analyzed"
|
|
)
|
|
|
|
with col3:
|
|
expanded_keywords = results.get('keyword_expansion', {}).get('expanded_keywords', [])
|
|
st.metric(
|
|
"🔍 Keywords Discovered",
|
|
len(expanded_keywords),
|
|
help="Additional keywords discovered through expansion"
|
|
)
|
|
|
|
with col4:
|
|
ranking_opportunities = results.get('serp_analysis', {}).get('ranking_opportunities', [])
|
|
st.metric(
|
|
"🚀 SERP Opportunities",
|
|
len(ranking_opportunities),
|
|
help="Keywords with ranking opportunities identified"
|
|
)
|
|
|
|
with col5:
|
|
recommendations = results.get('recommendations', [])
|
|
st.metric(
|
|
"💡 AI Recommendations",
|
|
len(recommendations),
|
|
help="AI-generated strategic recommendations"
|
|
)
|
|
|
|
# Analysis timestamp
|
|
if results.get('analysis_timestamp'):
|
|
timestamp = datetime.fromisoformat(results['analysis_timestamp'].replace('Z', '+00:00'))
|
|
st.caption(f"📅 Analysis completed: {timestamp.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
|
|
|
def _render_detailed_analysis(self, results: Dict[str, Any]):
|
|
"""Render detailed analysis in tabs."""
|
|
|
|
# Create main analysis tabs
|
|
tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([
|
|
"🔍 SERP Analysis",
|
|
"🎯 Keyword Research",
|
|
"🕷️ Competitor Intelligence",
|
|
"📊 Content Themes",
|
|
"🤖 AI Strategic Insights",
|
|
"📋 Action Plan"
|
|
])
|
|
|
|
with tab1:
|
|
self._render_serp_analysis(results.get('serp_analysis', {}))
|
|
|
|
with tab2:
|
|
self._render_keyword_research(results.get('keyword_expansion', {}))
|
|
|
|
with tab3:
|
|
self._render_competitor_intelligence(results.get('competitor_content', {}))
|
|
|
|
with tab4:
|
|
self._render_content_themes(results.get('content_themes', {}))
|
|
|
|
with tab5:
|
|
self._render_ai_insights(results.get('ai_insights', {}))
|
|
|
|
with tab6:
|
|
self._render_action_plan(results)
|
|
|
|
def _render_serp_analysis(self, serp_data: Dict[str, Any]):
|
|
"""Render SERP analysis results."""
|
|
|
|
st.markdown("### 🔍 Search Engine Results Analysis")
|
|
|
|
if not serp_data:
|
|
st.info("No SERP analysis data available")
|
|
return
|
|
|
|
# Competitor SERP presence
|
|
if serp_data.get('competitor_presence'):
|
|
st.markdown("#### 🏆 Competitor SERP Dominance")
|
|
|
|
presence_data = serp_data['competitor_presence']
|
|
presence_df = pd.DataFrame(
|
|
list(presence_data.items()),
|
|
columns=['Domain', 'Keywords Ranking']
|
|
)
|
|
|
|
# Display as chart
|
|
st.bar_chart(presence_df.set_index('Domain'))
|
|
|
|
# Top performers
|
|
st.markdown("**🥇 Top Performing Competitors:**")
|
|
for domain, count in list(presence_data.items())[:3]:
|
|
st.write(f"• **{domain}**: Ranking for {count} keywords")
|
|
|
|
# Ranking opportunities
|
|
if serp_data.get('ranking_opportunities'):
|
|
st.markdown("#### 🚀 Ranking Opportunities")
|
|
|
|
opportunities = serp_data['ranking_opportunities']
|
|
|
|
if opportunities:
|
|
opp_df = pd.DataFrame(opportunities)
|
|
st.dataframe(opp_df, use_container_width=True)
|
|
|
|
st.info(f"💡 Found {len(opportunities)} keywords where you're not ranking in top 10!")
|
|
else:
|
|
st.success("🎉 You're already ranking well for your target keywords!")
|
|
|
|
# SERP features analysis
|
|
if serp_data.get('keyword_rankings'):
|
|
st.markdown("#### 🎯 SERP Features Opportunities")
|
|
|
|
all_features = []
|
|
for keyword_data in serp_data['keyword_rankings'].values():
|
|
all_features.extend(keyword_data.get('serp_features', []))
|
|
|
|
if all_features:
|
|
feature_counts = pd.Series(all_features).value_counts()
|
|
st.bar_chart(feature_counts)
|
|
|
|
st.markdown("**🎯 Focus on these SERP features:**")
|
|
for feature, count in feature_counts.head(3).items():
|
|
st.write(f"• **{feature.replace('_', ' ').title()}**: Appears in {count} keyword searches")
|
|
|
|
def _render_keyword_research(self, keyword_data: Dict[str, Any]):
|
|
"""Render keyword research results."""
|
|
|
|
st.markdown("### 🎯 Advanced Keyword Research")
|
|
|
|
if not keyword_data:
|
|
st.info("No keyword expansion data available")
|
|
return
|
|
|
|
# Seed vs expanded keywords
|
|
seed_keywords = keyword_data.get('seed_keywords', [])
|
|
expanded_keywords = keyword_data.get('expanded_keywords', [])
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
st.metric("🌱 Seed Keywords", len(seed_keywords))
|
|
if seed_keywords:
|
|
for kw in seed_keywords:
|
|
st.write(f"• {kw}")
|
|
|
|
with col2:
|
|
st.metric("🔍 Expanded Keywords", len(expanded_keywords))
|
|
st.write(f"**Expansion Factor:** {len(expanded_keywords) / len(seed_keywords) if seed_keywords else 0:.1f}x")
|
|
|
|
# Search intent categorization
|
|
if keyword_data.get('keyword_categories'):
|
|
st.markdown("#### 🧠 Search Intent Analysis")
|
|
|
|
categories = keyword_data['keyword_categories']
|
|
|
|
# Create intent distribution chart
|
|
intent_counts = {intent: len(keywords) for intent, keywords in categories.items() if keywords}
|
|
|
|
if intent_counts:
|
|
intent_df = pd.DataFrame(
|
|
list(intent_counts.items()),
|
|
columns=['Search Intent', 'Keywords']
|
|
)
|
|
st.bar_chart(intent_df.set_index('Search Intent'))
|
|
|
|
# Detailed breakdown
|
|
for intent, keywords in categories.items():
|
|
if keywords:
|
|
with st.expander(f"📂 {intent.title()} Keywords ({len(keywords)})"):
|
|
for kw in keywords[:20]: # Show first 20
|
|
st.write(f"• {kw}")
|
|
|
|
# Long-tail opportunities
|
|
if keyword_data.get('long_tail_opportunities'):
|
|
st.markdown("#### 🎣 Long-tail Keyword Opportunities")
|
|
|
|
long_tail = keyword_data['long_tail_opportunities']
|
|
|
|
if long_tail:
|
|
st.info(f"🎯 Found {len(long_tail)} long-tail opportunities with lower competition!")
|
|
|
|
# Display in expandable format
|
|
with st.expander("View Long-tail Keywords"):
|
|
for i, kw in enumerate(long_tail, 1):
|
|
st.write(f"{i}. {kw}")
|
|
else:
|
|
st.warning("No long-tail opportunities identified")
|
|
|
|
def _render_competitor_intelligence(self, competitor_data: Dict[str, Any]):
|
|
"""Render competitor intelligence results."""
|
|
|
|
st.markdown("### 🕷️ Competitive Intelligence")
|
|
|
|
if not competitor_data.get('crawl_results'):
|
|
st.info("No competitor crawl data available")
|
|
return
|
|
|
|
# Crawl summary
|
|
crawl_results = competitor_data['crawl_results']
|
|
|
|
st.markdown("#### 📊 Competitor Content Overview")
|
|
|
|
# Create summary table
|
|
summary_data = []
|
|
for domain, data in crawl_results.items():
|
|
summary_data.append({
|
|
'Competitor': domain,
|
|
'Pages Crawled': data.get('total_pages', 0),
|
|
'Avg Content Length': f"{data.get('content_length_stats', {}).get('mean', 0):,.0f} chars",
|
|
'Success Rate': f"{data.get('status_codes', {}).get(200, 0) / data.get('total_pages', 1) * 100:.1f}%"
|
|
})
|
|
|
|
if summary_data:
|
|
summary_df = pd.DataFrame(summary_data)
|
|
st.dataframe(summary_df, use_container_width=True)
|
|
|
|
# Page type analysis
|
|
st.markdown("#### 📄 Content Type Distribution")
|
|
|
|
for domain, data in crawl_results.items():
|
|
page_types = data.get('page_types', {})
|
|
|
|
if page_types:
|
|
with st.expander(f"📊 {domain} Content Types"):
|
|
|
|
# Create chart data
|
|
types_df = pd.DataFrame(
|
|
list(page_types.items()),
|
|
columns=['Page Type', 'Count']
|
|
)
|
|
|
|
if not types_df.empty:
|
|
st.bar_chart(types_df.set_index('Page Type'))
|
|
|
|
# Key insights
|
|
total_pages = sum(page_types.values())
|
|
if total_pages > 0:
|
|
blog_ratio = page_types.get('blog_posts', 0) / total_pages * 100
|
|
product_ratio = page_types.get('product_pages', 0) / total_pages * 100
|
|
|
|
st.write("**Content Strategy Insights:**")
|
|
st.write(f"• Blog content: {blog_ratio:.1f}% of pages")
|
|
st.write(f"• Product focus: {product_ratio:.1f}% of pages")
|
|
|
|
# Content structure insights
|
|
if competitor_data.get('content_structure'):
|
|
st.markdown("#### 🏗️ Content Structure Analysis")
|
|
|
|
structure_data = competitor_data['content_structure']
|
|
|
|
for domain, structure in structure_data.items():
|
|
with st.expander(f"🔍 {domain} Structure Analysis"):
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
st.metric("Avg Title Length", f"{structure.get('avg_title_length', 0):.0f} chars")
|
|
st.metric("H1 Usage", f"{structure.get('h1_usage', 0):.1f}%")
|
|
|
|
with col2:
|
|
st.metric("Avg Meta Desc Length", f"{structure.get('avg_meta_desc_length', 0):.0f} chars")
|
|
st.metric("Internal Links", f"{structure.get('internal_links_avg', 0):.1f} avg")
|
|
|
|
def _render_content_themes(self, theme_data: Dict[str, Any]):
|
|
"""Render content theme analysis."""
|
|
|
|
st.markdown("### 📊 Content Theme Intelligence")
|
|
|
|
if not theme_data:
|
|
st.info("No content theme data available")
|
|
return
|
|
|
|
# Dominant themes
|
|
if theme_data.get('dominant_themes'):
|
|
st.markdown("#### 🎯 Dominant Content Themes")
|
|
|
|
themes = theme_data['dominant_themes']
|
|
|
|
if themes:
|
|
themes_df = pd.DataFrame(themes)
|
|
st.dataframe(themes_df, use_container_width=True)
|
|
|
|
# Top themes highlight
|
|
st.markdown("**🔥 Top Content Themes:**")
|
|
for i, theme in enumerate(themes[:5], 1):
|
|
word = theme.get('word', theme.get('text', 'Unknown'))
|
|
freq = theme.get('freq', theme.get('frequency', 0))
|
|
st.write(f"{i}. **{word}** (appears {freq} times)")
|
|
|
|
# Content clusters
|
|
if theme_data.get('content_clusters'):
|
|
st.markdown("#### 🗂️ Topic Cluster Analysis")
|
|
|
|
clusters = theme_data['content_clusters']
|
|
|
|
# Cluster distribution
|
|
cluster_counts = {name: len(themes) for name, themes in clusters.items() if themes}
|
|
|
|
if cluster_counts:
|
|
cluster_df = pd.DataFrame(
|
|
list(cluster_counts.items()),
|
|
columns=['Topic Cluster', 'Theme Count']
|
|
)
|
|
st.bar_chart(cluster_df.set_index('Topic Cluster'))
|
|
|
|
# Detailed cluster view
|
|
for cluster_name, themes in clusters.items():
|
|
if themes:
|
|
with st.expander(f"📂 {cluster_name.replace('_', ' ').title()} ({len(themes)} themes)"):
|
|
for theme in themes[:15]: # Show first 15
|
|
st.write(f"• {theme}")
|
|
|
|
# Content gaps and opportunities
|
|
if theme_data.get('content_opportunities'):
|
|
st.markdown("#### 🎯 Content Gap Opportunities")
|
|
|
|
opportunities = theme_data['content_opportunities']
|
|
|
|
if opportunities:
|
|
for opp in opportunities:
|
|
st.write(f"🎯 **{opp}**")
|
|
else:
|
|
st.info("No specific content opportunities identified in theme analysis")
|
|
|
|
def _render_ai_insights(self, ai_data: Dict[str, Any]):
|
|
"""Render AI-generated strategic insights."""
|
|
|
|
st.markdown("### 🤖 AI-Powered Strategic Insights")
|
|
|
|
if not ai_data:
|
|
st.info("No AI insights available")
|
|
return
|
|
|
|
# Strategic recommendations
|
|
if ai_data.get('recommendations'):
|
|
st.markdown("#### 🎯 Priority Strategic Recommendations")
|
|
|
|
recommendations = ai_data['recommendations']
|
|
|
|
for i, rec in enumerate(recommendations[:5], 1):
|
|
with st.expander(f"🎯 Recommendation {i}"):
|
|
st.markdown(rec)
|
|
|
|
# Competitive positioning
|
|
if ai_data.get('competitive_positioning'):
|
|
st.markdown("#### 🏆 Competitive Positioning Insights")
|
|
st.markdown(ai_data['competitive_positioning'])
|
|
|
|
# Content strategy insights
|
|
if ai_data.get('content_strategy'):
|
|
st.markdown("#### 📝 Content Strategy Recommendations")
|
|
st.markdown(ai_data['content_strategy'])
|
|
|
|
# Implementation timeline
|
|
if ai_data.get('implementation_timeline'):
|
|
st.markdown("#### 📅 Implementation Roadmap")
|
|
|
|
timeline = ai_data['implementation_timeline']
|
|
|
|
for period, tasks in timeline.items():
|
|
with st.expander(f"📅 {period.replace('_', ' ').title()} Plan"):
|
|
for task in tasks:
|
|
st.write(f"• {task}")
|
|
|
|
# Technical SEO opportunities
|
|
if ai_data.get('technical_opportunities'):
|
|
st.markdown("#### ⚙️ Technical SEO Opportunities")
|
|
|
|
tech_opps = ai_data['technical_opportunities']
|
|
|
|
for opp in tech_opps:
|
|
st.write(f"⚙️ {opp}")
|
|
|
|
def _render_action_plan(self, results: Dict[str, Any]):
|
|
"""Render actionable implementation plan."""
|
|
|
|
st.markdown("### 📋 Your Content Gap Action Plan")
|
|
|
|
# Quick wins section
|
|
st.markdown("#### 🚀 Quick Wins (Week 1-2)")
|
|
|
|
quick_wins = []
|
|
|
|
# SERP opportunities
|
|
serp_opportunities = results.get('serp_analysis', {}).get('ranking_opportunities', [])
|
|
if serp_opportunities:
|
|
quick_wins.append(f"🎯 Target {len(serp_opportunities)} keywords where you're not ranking")
|
|
|
|
# Long-tail keywords
|
|
long_tail = results.get('keyword_expansion', {}).get('long_tail_opportunities', [])
|
|
if long_tail:
|
|
quick_wins.append(f"🎣 Create content for {min(5, len(long_tail))} high-potential long-tail keywords")
|
|
|
|
# Content themes
|
|
themes = results.get('content_themes', {}).get('dominant_themes', [])
|
|
if themes:
|
|
top_theme = themes[0].get('word', 'top theme') if themes else 'content optimization'
|
|
quick_wins.append(f"📊 Optimize existing content around '{top_theme}' theme")
|
|
|
|
for i, win in enumerate(quick_wins, 1):
|
|
st.write(f"{i}. {win}")
|
|
|
|
# Medium-term strategy
|
|
st.markdown("#### 📈 Medium-term Strategy (Month 1-3)")
|
|
|
|
medium_term = [
|
|
"🕷️ Conduct regular competitor content audits",
|
|
"🎯 Develop content calendar based on keyword gaps",
|
|
"📊 Implement content theme clusters",
|
|
"🤖 Set up automated SERP monitoring"
|
|
]
|
|
|
|
for i, strategy in enumerate(medium_term, 1):
|
|
st.write(f"{i}. {strategy}")
|
|
|
|
# Long-term vision
|
|
st.markdown("#### 🎯 Long-term Vision (Quarter 2+)")
|
|
|
|
long_term = [
|
|
"🏆 Establish thought leadership in identified content gaps",
|
|
"🌐 Build comprehensive content hub around dominant themes",
|
|
"📈 Scale content production based on proven gaps",
|
|
"🤝 Develop strategic partnerships for content collaboration"
|
|
]
|
|
|
|
for i, vision in enumerate(long_term, 1):
|
|
st.write(f"{i}. {vision}")
|
|
|
|
# Success metrics
|
|
st.markdown("#### 📊 Success Metrics to Track")
|
|
|
|
metrics = [
|
|
"🎯 Keyword ranking improvements for target terms",
|
|
"📈 Organic traffic growth from new content",
|
|
"🔍 SERP feature acquisitions (featured snippets, etc.)",
|
|
"🏆 Competitive ranking gains in content themes",
|
|
"📊 Content engagement metrics and user behavior"
|
|
]
|
|
|
|
for metric in metrics:
|
|
st.write(f"• {metric}")
|
|
|
|
def _render_export_options(self, results: Dict[str, Any]):
|
|
"""Render export options for analysis results."""
|
|
|
|
st.markdown("---")
|
|
st.markdown("### 📥 Export Analysis Results")
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
# JSON export
|
|
if st.button("📄 Export as JSON", use_container_width=True):
|
|
json_data = json.dumps(results, indent=2, default=str)
|
|
|
|
st.download_button(
|
|
label="⬇️ Download JSON Report",
|
|
data=json_data,
|
|
file_name=f"content_gap_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
|
|
mime="application/json",
|
|
use_container_width=True
|
|
)
|
|
|
|
with col2:
|
|
# CSV export for keywords
|
|
if st.button("📊 Export Keywords CSV", use_container_width=True):
|
|
expanded_keywords = results.get('keyword_expansion', {}).get('expanded_keywords', [])
|
|
|
|
if expanded_keywords:
|
|
keywords_df = pd.DataFrame(expanded_keywords, columns=['Keyword'])
|
|
csv_data = keywords_df.to_csv(index=False)
|
|
|
|
st.download_button(
|
|
label="⬇️ Download Keywords CSV",
|
|
data=csv_data,
|
|
file_name=f"discovered_keywords_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
|
|
mime="text/csv",
|
|
use_container_width=True
|
|
)
|
|
else:
|
|
st.warning("No keywords available for export")
|
|
|
|
with col3:
|
|
# Summary report
|
|
if st.button("📋 Generate Summary Report", use_container_width=True):
|
|
summary = self._generate_summary_report(results)
|
|
|
|
st.download_button(
|
|
label="⬇️ Download Summary Report",
|
|
data=summary,
|
|
file_name=f"content_gap_summary_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
|
|
mime="text/plain",
|
|
use_container_width=True
|
|
)
|
|
|
|
def _generate_summary_report(self, results: Dict[str, Any]) -> str:
|
|
"""Generate a text summary report."""
|
|
|
|
target_url = results.get('target_url', 'Unknown')
|
|
timestamp = results.get('analysis_timestamp', datetime.now().isoformat())
|
|
|
|
summary = f"""
|
|
ENHANCED CONTENT GAP ANALYSIS REPORT
|
|
=====================================
|
|
|
|
Target Website: {target_url}
|
|
Analysis Date: {timestamp}
|
|
Industry: {results.get('industry', 'General')}
|
|
|
|
EXECUTIVE SUMMARY
|
|
-----------------
|
|
Keywords Analyzed: {len(results.get('target_keywords', []))}
|
|
Competitors Analyzed: {len(results.get('competitor_urls', []))}
|
|
Keywords Discovered: {len(results.get('keyword_expansion', {}).get('expanded_keywords', []))}
|
|
SERP Opportunities: {len(results.get('serp_analysis', {}).get('ranking_opportunities', []))}
|
|
|
|
RANKING OPPORTUNITIES
|
|
---------------------
|
|
"""
|
|
|
|
# Add ranking opportunities
|
|
opportunities = results.get('serp_analysis', {}).get('ranking_opportunities', [])
|
|
for i, opp in enumerate(opportunities[:10], 1):
|
|
summary += f"{i}. {opp.get('keyword', 'Unknown keyword')}\n"
|
|
|
|
# Add top keywords discovered
|
|
summary += "\nTOP DISCOVERED KEYWORDS\n-----------------------\n"
|
|
expanded_keywords = results.get('keyword_expansion', {}).get('expanded_keywords', [])
|
|
for i, kw in enumerate(expanded_keywords[:20], 1):
|
|
summary += f"{i}. {kw}\n"
|
|
|
|
# Add AI recommendations
|
|
recommendations = results.get('ai_insights', {}).get('recommendations', [])
|
|
if recommendations:
|
|
summary += "\nAI STRATEGIC RECOMMENDATIONS\n----------------------------\n"
|
|
for i, rec in enumerate(recommendations[:5], 1):
|
|
summary += f"{i}. {rec}\n"
|
|
|
|
summary += f"\n\nReport generated by ALwrity Enhanced Content Gap Analysis\nTimestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
|
|
|
return summary
|
|
|
|
# Render function for integration with main dashboard
|
|
def render_enhanced_content_gap_analysis():
|
|
"""Render the enhanced content gap analysis UI."""
|
|
ui = EnhancedContentGapAnalysisUI()
|
|
ui.render() |