ALwrity Chatbot, SEO, Social media, Settings, Dashboard UI styling changes
This commit is contained in:
787
lib/ai_seo_tools/content_gap_analysis/enhanced_ui.py
Normal file
787
lib/ai_seo_tools/content_gap_analysis/enhanced_ui.py
Normal file
@@ -0,0 +1,787 @@
|
||||
"""
|
||||
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()
|
||||
Reference in New Issue
Block a user