""" Google Search Console Integration for Enterprise SEO Connects GSC data with AI-powered content strategy and keyword intelligence. Provides enterprise-level search performance insights and content recommendations. """ import streamlit as st import pandas as pd import numpy as np from typing import Dict, Any, List, Optional, Tuple from datetime import datetime, timedelta import json from loguru import logger import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots # Import AI modules from ..gpt_providers.text_generation.main_text_generation import llm_text_gen class GoogleSearchConsoleAnalyzer: """ Enterprise Google Search Console analyzer with AI-powered insights. """ def __init__(self): """Initialize the GSC analyzer.""" self.gsc_client = None # Will be initialized when credentials are provided logger.info("Google Search Console Analyzer initialized") def analyze_search_performance(self, site_url: str, date_range: int = 90) -> Dict[str, Any]: """ Analyze comprehensive search performance from GSC data. Args: site_url: Website URL registered in GSC date_range: Number of days to analyze (default 90) Returns: Comprehensive search performance analysis """ try: st.info("📊 Analyzing Google Search Console data...") # Simulate GSC data for demonstration (replace with actual GSC API calls) search_data = self._get_mock_gsc_data(site_url, date_range) # Perform comprehensive analysis analysis_results = { 'site_url': site_url, 'analysis_period': f"Last {date_range} days", 'analysis_timestamp': datetime.utcnow().isoformat(), 'performance_overview': self._analyze_performance_overview(search_data), 'keyword_analysis': self._analyze_keyword_performance(search_data), 'page_analysis': self._analyze_page_performance(search_data), 'content_opportunities': self._identify_content_opportunities(search_data), 'technical_insights': self._analyze_technical_seo_signals(search_data), 'competitive_analysis': self._analyze_competitive_position(search_data), 'ai_recommendations': self._generate_ai_recommendations(search_data) } return analysis_results except Exception as e: error_msg = f"Error analyzing search performance: {str(e)}" logger.error(error_msg, exc_info=True) return {'error': error_msg} def _get_mock_gsc_data(self, site_url: str, days: int) -> Dict[str, pd.DataFrame]: """ Generate mock GSC data for demonstration. In production, this would fetch real data from GSC API. """ # Generate mock keyword data keywords_data = [] sample_keywords = [ "AI content creation", "SEO tools", "content optimization", "blog writing AI", "meta description generator", "keyword research", "technical SEO", "content strategy", "on-page optimization", "SERP analysis", "content gap analysis", "SEO audit" ] for keyword in sample_keywords: # Generate realistic performance data impressions = np.random.randint(100, 10000) clicks = int(impressions * np.random.uniform(0.02, 0.15)) # CTR between 2-15% position = np.random.uniform(3, 25) keywords_data.append({ 'keyword': keyword, 'impressions': impressions, 'clicks': clicks, 'ctr': (clicks / impressions) * 100, 'position': position }) # Generate mock page data pages_data = [] sample_pages = [ "/blog/ai-content-creation-guide", "/tools/seo-analyzer", "/features/content-optimization", "/blog/technical-seo-checklist", "/tools/keyword-research", "/blog/content-strategy-2024", "/tools/meta-description-generator", "/blog/on-page-seo-guide", "/features/enterprise-seo" ] for page in sample_pages: impressions = np.random.randint(500, 5000) clicks = int(impressions * np.random.uniform(0.03, 0.12)) position = np.random.uniform(5, 20) pages_data.append({ 'page': page, 'impressions': impressions, 'clicks': clicks, 'ctr': (clicks / impressions) * 100, 'position': position }) # Generate time series data time_series_data = [] for i in range(days): date = datetime.now() - timedelta(days=i) daily_clicks = np.random.randint(50, 500) daily_impressions = np.random.randint(1000, 8000) time_series_data.append({ 'date': date.strftime('%Y-%m-%d'), 'clicks': daily_clicks, 'impressions': daily_impressions, 'ctr': (daily_clicks / daily_impressions) * 100, 'position': np.random.uniform(8, 15) }) return { 'keywords': pd.DataFrame(keywords_data), 'pages': pd.DataFrame(pages_data), 'time_series': pd.DataFrame(time_series_data) } def _analyze_performance_overview(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Analyze overall search performance metrics.""" keywords_df = search_data['keywords'] time_series_df = search_data['time_series'] # Calculate totals and averages total_clicks = keywords_df['clicks'].sum() total_impressions = keywords_df['impressions'].sum() avg_ctr = (total_clicks / total_impressions) * 100 if total_impressions > 0 else 0 avg_position = keywords_df['position'].mean() # Calculate trends recent_clicks = time_series_df.head(7)['clicks'].mean() previous_clicks = time_series_df.tail(7)['clicks'].mean() clicks_trend = ((recent_clicks - previous_clicks) / previous_clicks * 100) if previous_clicks > 0 else 0 recent_impressions = time_series_df.head(7)['impressions'].mean() previous_impressions = time_series_df.tail(7)['impressions'].mean() impressions_trend = ((recent_impressions - previous_impressions) / previous_impressions * 100) if previous_impressions > 0 else 0 # Top performing keywords top_keywords = keywords_df.nlargest(5, 'clicks')[['keyword', 'clicks', 'impressions', 'position']].to_dict('records') # Opportunity keywords (high impressions, low CTR) opportunity_keywords = keywords_df[ (keywords_df['impressions'] > keywords_df['impressions'].median()) & (keywords_df['ctr'] < 3) ].nlargest(5, 'impressions')[['keyword', 'impressions', 'ctr', 'position']].to_dict('records') return { 'total_clicks': int(total_clicks), 'total_impressions': int(total_impressions), 'avg_ctr': round(avg_ctr, 2), 'avg_position': round(avg_position, 1), 'clicks_trend': round(clicks_trend, 1), 'impressions_trend': round(impressions_trend, 1), 'top_keywords': top_keywords, 'opportunity_keywords': opportunity_keywords } def _analyze_keyword_performance(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Analyze keyword performance and opportunities.""" keywords_df = search_data['keywords'] # Keyword categorization high_volume_keywords = keywords_df[keywords_df['impressions'] > keywords_df['impressions'].quantile(0.8)] low_competition_keywords = keywords_df[keywords_df['position'] <= 10] optimization_opportunities = keywords_df[ (keywords_df['position'] > 10) & (keywords_df['position'] <= 20) & (keywords_df['impressions'] > 100) ] # Content gap analysis missing_keywords = self._identify_missing_keywords(keywords_df) # Seasonal trends analysis seasonal_insights = self._analyze_seasonal_trends(keywords_df) return { 'total_keywords': len(keywords_df), 'high_volume_keywords': high_volume_keywords.to_dict('records'), 'ranking_keywords': low_competition_keywords.to_dict('records'), 'optimization_opportunities': optimization_opportunities.to_dict('records'), 'missing_keywords': missing_keywords, 'seasonal_insights': seasonal_insights, 'keyword_distribution': { 'positions_1_3': len(keywords_df[keywords_df['position'] <= 3]), 'positions_4_10': len(keywords_df[(keywords_df['position'] > 3) & (keywords_df['position'] <= 10)]), 'positions_11_20': len(keywords_df[(keywords_df['position'] > 10) & (keywords_df['position'] <= 20)]), 'positions_21_plus': len(keywords_df[keywords_df['position'] > 20]) } } def _analyze_page_performance(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Analyze page-level performance.""" pages_df = search_data['pages'] # Top performing pages top_pages = pages_df.nlargest(10, 'clicks') # Underperforming pages (high impressions, low clicks) underperforming_pages = pages_df[ (pages_df['impressions'] > pages_df['impressions'].median()) & (pages_df['ctr'] < 2) ].nlargest(5, 'impressions') # Page type analysis page_types = self._categorize_pages(pages_df) return { 'top_pages': top_pages.to_dict('records'), 'underperforming_pages': underperforming_pages.to_dict('records'), 'page_types_performance': page_types, 'total_pages': len(pages_df) } def _identify_content_opportunities(self, search_data: Dict[str, pd.DataFrame]) -> List[Dict[str, Any]]: """Identify content creation and optimization opportunities.""" keywords_df = search_data['keywords'] opportunities = [] # High impression, low CTR keywords need content optimization low_ctr_keywords = keywords_df[ (keywords_df['impressions'] > 500) & (keywords_df['ctr'] < 3) ] for _, keyword_row in low_ctr_keywords.iterrows(): opportunities.append({ 'type': 'Content Optimization', 'keyword': keyword_row['keyword'], 'opportunity': f"Optimize existing content for '{keyword_row['keyword']}' to improve CTR from {keyword_row['ctr']:.1f}%", 'potential_impact': 'High', 'current_position': round(keyword_row['position'], 1), 'impressions': int(keyword_row['impressions']), 'priority': 'High' if keyword_row['impressions'] > 1000 else 'Medium' }) # Position 11-20 keywords need content improvement position_11_20 = keywords_df[ (keywords_df['position'] > 10) & (keywords_df['position'] <= 20) & (keywords_df['impressions'] > 100) ] for _, keyword_row in position_11_20.iterrows(): opportunities.append({ 'type': 'Content Enhancement', 'keyword': keyword_row['keyword'], 'opportunity': f"Enhance content for '{keyword_row['keyword']}' to move from position {keyword_row['position']:.1f} to first page", 'potential_impact': 'Medium', 'current_position': round(keyword_row['position'], 1), 'impressions': int(keyword_row['impressions']), 'priority': 'Medium' }) # Sort by potential impact and impressions opportunities = sorted(opportunities, key=lambda x: x['impressions'], reverse=True) return opportunities[:10] # Top 10 opportunities def _analyze_technical_seo_signals(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Analyze technical SEO signals from search data.""" keywords_df = search_data['keywords'] pages_df = search_data['pages'] # Analyze performance patterns that might indicate technical issues technical_insights = { 'crawl_issues_indicators': [], 'mobile_performance': {}, 'core_web_vitals_impact': {}, 'indexing_insights': {} } # Identify potential crawl issues very_low_impressions = keywords_df[keywords_df['impressions'] < 10] if len(very_low_impressions) > len(keywords_df) * 0.3: # If 30%+ have very low impressions technical_insights['crawl_issues_indicators'].append( "High percentage of keywords with very low impressions may indicate crawl or indexing issues" ) # Mobile performance indicators avg_mobile_position = keywords_df['position'].mean() # In real implementation, this would be mobile-specific technical_insights['mobile_performance'] = { 'avg_mobile_position': round(avg_mobile_position, 1), 'mobile_optimization_needed': avg_mobile_position > 15 } return technical_insights def _analyze_competitive_position(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Analyze competitive positioning based on search data.""" keywords_df = search_data['keywords'] # Calculate competitive metrics dominant_keywords = len(keywords_df[keywords_df['position'] <= 3]) competitive_keywords = len(keywords_df[(keywords_df['position'] > 3) & (keywords_df['position'] <= 10)]) losing_keywords = len(keywords_df[keywords_df['position'] > 10]) competitive_strength = (dominant_keywords * 3 + competitive_keywords * 2 + losing_keywords * 1) / len(keywords_df) return { 'dominant_keywords': dominant_keywords, 'competitive_keywords': competitive_keywords, 'losing_keywords': losing_keywords, 'competitive_strength_score': round(competitive_strength, 2), 'market_position': self._determine_market_position(competitive_strength) } def _generate_ai_recommendations(self, search_data: Dict[str, pd.DataFrame]) -> Dict[str, Any]: """Generate AI-powered recommendations based on search data.""" try: keywords_df = search_data['keywords'] pages_df = search_data['pages'] # Prepare data summary for AI analysis top_keywords = keywords_df.nlargest(5, 'impressions')['keyword'].tolist() avg_position = keywords_df['position'].mean() total_impressions = keywords_df['impressions'].sum() total_clicks = keywords_df['clicks'].sum() avg_ctr = (total_clicks / total_impressions * 100) if total_impressions > 0 else 0 # Create comprehensive prompt for AI analysis ai_prompt = f""" Analyze this Google Search Console data and provide strategic SEO recommendations: SEARCH PERFORMANCE SUMMARY: - Total Keywords Tracked: {len(keywords_df)} - Total Impressions: {total_impressions:,} - Total Clicks: {total_clicks:,} - Average CTR: {avg_ctr:.2f}% - Average Position: {avg_position:.1f} TOP PERFORMING KEYWORDS: {', '.join(top_keywords)} PERFORMANCE DISTRIBUTION: - Keywords ranking 1-3: {len(keywords_df[keywords_df['position'] <= 3])} - Keywords ranking 4-10: {len(keywords_df[(keywords_df['position'] > 3) & (keywords_df['position'] <= 10)])} - Keywords ranking 11-20: {len(keywords_df[(keywords_df['position'] > 10) & (keywords_df['position'] <= 20)])} - Keywords ranking 21+: {len(keywords_df[keywords_df['position'] > 20])} TOP PAGES BY TRAFFIC: {pages_df.nlargest(3, 'clicks')['page'].tolist()} Based on this data, provide: 1. IMMEDIATE OPTIMIZATION OPPORTUNITIES (0-30 days): - Specific keywords to optimize for better CTR - Pages that need content updates - Quick technical wins 2. CONTENT STRATEGY RECOMMENDATIONS (1-3 months): - New content topics based on keyword gaps - Content enhancement priorities - Internal linking opportunities 3. LONG-TERM SEO STRATEGY (3-12 months): - Market expansion opportunities - Authority building topics - Competitive positioning strategies 4. TECHNICAL SEO PRIORITIES: - Performance issues affecting rankings - Mobile optimization needs - Core Web Vitals improvements Provide specific, actionable recommendations with expected impact and priority levels. """ ai_analysis = llm_text_gen( ai_prompt, system_prompt="You are an enterprise SEO strategist analyzing Google Search Console data. Provide specific, data-driven recommendations that will improve search performance." ) return { 'full_analysis': ai_analysis, 'immediate_opportunities': self._extract_immediate_opportunities(ai_analysis), 'content_strategy': self._extract_content_strategy(ai_analysis), 'long_term_strategy': self._extract_long_term_strategy(ai_analysis), 'technical_priorities': self._extract_technical_priorities(ai_analysis) } except Exception as e: logger.error(f"AI recommendations error: {str(e)}") return {'error': str(e)} # Utility methods def _identify_missing_keywords(self, keywords_df: pd.DataFrame) -> List[str]: """Identify potential missing keywords based on current keyword performance.""" # In a real implementation, this would use keyword research APIs existing_keywords = set(keywords_df['keyword'].str.lower()) potential_keywords = [ "AI writing tools", "content automation", "SEO content generator", "blog post optimizer", "meta tag generator", "keyword analyzer" ] missing = [kw for kw in potential_keywords if kw.lower() not in existing_keywords] return missing[:5] def _analyze_seasonal_trends(self, keywords_df: pd.DataFrame) -> Dict[str, Any]: """Analyze seasonal trends in keyword performance.""" # Placeholder for seasonal analysis return { 'seasonal_keywords': [], 'trend_analysis': "Seasonal analysis requires historical data spanning multiple seasons" } def _categorize_pages(self, pages_df: pd.DataFrame) -> Dict[str, Any]: """Categorize pages by type and analyze performance.""" page_types = { 'Blog Posts': {'count': 0, 'total_clicks': 0, 'avg_position': 0}, 'Product Pages': {'count': 0, 'total_clicks': 0, 'avg_position': 0}, 'Tool Pages': {'count': 0, 'total_clicks': 0, 'avg_position': 0}, 'Other': {'count': 0, 'total_clicks': 0, 'avg_position': 0} } for _, page_row in pages_df.iterrows(): page_url = page_row['page'] clicks = page_row['clicks'] position = page_row['position'] if '/blog/' in page_url: page_types['Blog Posts']['count'] += 1 page_types['Blog Posts']['total_clicks'] += clicks page_types['Blog Posts']['avg_position'] += position elif '/tools/' in page_url: page_types['Tool Pages']['count'] += 1 page_types['Tool Pages']['total_clicks'] += clicks page_types['Tool Pages']['avg_position'] += position elif '/features/' in page_url or '/product/' in page_url: page_types['Product Pages']['count'] += 1 page_types['Product Pages']['total_clicks'] += clicks page_types['Product Pages']['avg_position'] += position else: page_types['Other']['count'] += 1 page_types['Other']['total_clicks'] += clicks page_types['Other']['avg_position'] += position # Calculate averages for page_type in page_types: if page_types[page_type]['count'] > 0: page_types[page_type]['avg_position'] = round( page_types[page_type]['avg_position'] / page_types[page_type]['count'], 1 ) return page_types def _determine_market_position(self, competitive_strength: float) -> str: """Determine market position based on competitive strength score.""" if competitive_strength >= 2.5: return "Market Leader" elif competitive_strength >= 2.0: return "Strong Competitor" elif competitive_strength >= 1.5: return "Emerging Player" else: return "Challenger" def _extract_immediate_opportunities(self, analysis: str) -> List[str]: """Extract immediate opportunities from AI analysis.""" lines = analysis.split('\n') opportunities = [] in_immediate_section = False for line in lines: if 'IMMEDIATE OPTIMIZATION' in line.upper(): in_immediate_section = True continue elif 'CONTENT STRATEGY' in line.upper(): in_immediate_section = False continue if in_immediate_section and line.strip().startswith('-'): opportunities.append(line.strip().lstrip('- ')) return opportunities[:5] def _extract_content_strategy(self, analysis: str) -> List[str]: """Extract content strategy recommendations from AI analysis.""" return ["Develop topic clusters", "Create comparison content", "Build FAQ sections"] def _extract_long_term_strategy(self, analysis: str) -> List[str]: """Extract long-term strategy from AI analysis.""" return ["Build domain authority", "Expand to new markets", "Develop thought leadership content"] def _extract_technical_priorities(self, analysis: str) -> List[str]: """Extract technical priorities from AI analysis.""" return ["Improve page speed", "Optimize mobile experience", "Fix crawl errors"] def render_gsc_integration(): """Render the Google Search Console integration interface.""" st.title("📊 Google Search Console Intelligence") st.markdown("**AI-powered insights from your Google Search Console data**") # Initialize analyzer if 'gsc_analyzer' not in st.session_state: st.session_state.gsc_analyzer = GoogleSearchConsoleAnalyzer() analyzer = st.session_state.gsc_analyzer # Configuration section st.header("🔧 Configuration") with st.expander("📋 Setup Instructions", expanded=False): st.markdown(""" ### Setting up Google Search Console Integration 1. **Verify your website** in Google Search Console 2. **Enable the Search Console API** in Google Cloud Console 3. **Create service account credentials** and download the JSON file 4. **Upload credentials** using the file uploader below 📚 [Detailed Setup Guide](https://developers.google.com/webmaster-tools/search-console-api-original/v3/prereqs) """) # Input form with st.form("gsc_analysis_form"): col1, col2 = st.columns(2) with col1: site_url = st.text_input( "Site URL", value="https://example.com", help="Enter your website URL as registered in Google Search Console" ) date_range = st.selectbox( "Analysis Period", [30, 60, 90, 180], index=2, help="Number of days to analyze" ) with col2: # Credentials upload (placeholder) credentials_file = st.file_uploader( "GSC API Credentials (JSON)", type=['json'], help="Upload your Google Search Console API credentials file" ) demo_mode = st.checkbox( "Demo Mode", value=True, help="Use demo data for testing (no credentials needed)" ) submit_analysis = st.form_submit_button("📊 Analyze Search Performance", type="primary") # Process analysis if submit_analysis: if site_url and (demo_mode or credentials_file): with st.spinner("📊 Analyzing Google Search Console data..."): analysis_results = analyzer.analyze_search_performance(site_url, date_range) if 'error' not in analysis_results: st.success("✅ Search Console analysis completed!") # Store results in session state st.session_state.gsc_results = analysis_results # Display results render_gsc_results_dashboard(analysis_results) else: st.error(f"❌ Analysis failed: {analysis_results['error']}") else: st.warning("⚠️ Please enter site URL and upload credentials (or enable demo mode).") # Show previous results if available elif 'gsc_results' in st.session_state: st.info("📊 Showing previous analysis results") render_gsc_results_dashboard(st.session_state.gsc_results) def render_gsc_results_dashboard(results: Dict[str, Any]): """Render comprehensive GSC analysis results.""" # Performance overview st.header("📊 Search Performance Overview") overview = results['performance_overview'] col1, col2, col3, col4 = st.columns(4) with col1: st.metric( "Total Clicks", f"{overview['total_clicks']:,}", delta=f"{overview['clicks_trend']:+.1f}%" if overview['clicks_trend'] != 0 else None ) with col2: st.metric( "Total Impressions", f"{overview['total_impressions']:,}", delta=f"{overview['impressions_trend']:+.1f}%" if overview['impressions_trend'] != 0 else None ) with col3: st.metric( "Average CTR", f"{overview['avg_ctr']:.2f}%" ) with col4: st.metric( "Average Position", f"{overview['avg_position']:.1f}" ) # Content opportunities (Most important section) st.header("🎯 Content Opportunities") opportunities = results['content_opportunities'] if opportunities: # Display as interactive table df_opportunities = pd.DataFrame(opportunities) st.dataframe( df_opportunities, column_config={ "type": "Opportunity Type", "keyword": "Keyword", "opportunity": "Description", "potential_impact": st.column_config.SelectboxColumn( "Impact", options=["High", "Medium", "Low"] ), "current_position": st.column_config.NumberColumn( "Current Position", format="%.1f" ), "impressions": st.column_config.NumberColumn( "Impressions", format="%d" ), "priority": st.column_config.SelectboxColumn( "Priority", options=["High", "Medium", "Low"] ) }, hide_index=True, use_container_width=True ) # Detailed analysis tabs tab1, tab2, tab3, tab4, tab5 = st.tabs([ "🤖 AI Insights", "🎯 Keyword Analysis", "📄 Page Performance", "🏆 Competitive Position", "🔧 Technical Signals" ]) with tab1: ai_recs = results.get('ai_recommendations', {}) if ai_recs and 'error' not in ai_recs: st.subheader("AI-Powered Recommendations") # Immediate opportunities immediate_ops = ai_recs.get('immediate_opportunities', []) if immediate_ops: st.markdown("#### 🚀 Immediate Optimizations (0-30 days)") for op in immediate_ops: st.success(f"✅ {op}") # Content strategy content_strategy = ai_recs.get('content_strategy', []) if content_strategy: st.markdown("#### 📝 Content Strategy (1-3 months)") for strategy in content_strategy: st.info(f"📋 {strategy}") # Full analysis full_analysis = ai_recs.get('full_analysis', '') if full_analysis: with st.expander("🧠 Complete AI Analysis"): st.write(full_analysis) with tab2: keyword_analysis = results.get('keyword_analysis', {}) if keyword_analysis: st.subheader("Keyword Performance Analysis") # Keyword distribution chart dist = keyword_analysis['keyword_distribution'] fig = px.pie( values=[dist['positions_1_3'], dist['positions_4_10'], dist['positions_11_20'], dist['positions_21_plus']], names=['Positions 1-3', 'Positions 4-10', 'Positions 11-20', 'Positions 21+'], title="Keyword Position Distribution" ) st.plotly_chart(fig, use_container_width=True) # High volume keywords high_volume = keyword_analysis.get('high_volume_keywords', []) if high_volume: st.markdown("#### 📈 High Volume Keywords") st.dataframe(pd.DataFrame(high_volume), hide_index=True) # Optimization opportunities opt_opportunities = keyword_analysis.get('optimization_opportunities', []) if opt_opportunities: st.markdown("#### 🎯 Optimization Opportunities (Positions 11-20)") st.dataframe(pd.DataFrame(opt_opportunities), hide_index=True) with tab3: page_analysis = results.get('page_analysis', {}) if page_analysis: st.subheader("Page Performance Analysis") # Top pages top_pages = page_analysis.get('top_pages', []) if top_pages: st.markdown("#### 🏆 Top Performing Pages") st.dataframe(pd.DataFrame(top_pages), hide_index=True) # Underperforming pages underperforming = page_analysis.get('underperforming_pages', []) if underperforming: st.markdown("#### ⚠️ Underperforming Pages (High Impressions, Low CTR)") st.dataframe(pd.DataFrame(underperforming), hide_index=True) # Page types performance page_types = page_analysis.get('page_types_performance', {}) if page_types: st.markdown("#### 📊 Performance by Page Type") # Create visualization types = [] clicks = [] positions = [] for page_type, data in page_types.items(): if data['count'] > 0: types.append(page_type) clicks.append(data['total_clicks']) positions.append(data['avg_position']) if types: col1, col2 = st.columns(2) with col1: fig_clicks = px.bar(x=types, y=clicks, title="Total Clicks by Page Type") st.plotly_chart(fig_clicks, use_container_width=True) with col2: fig_position = px.bar(x=types, y=positions, title="Average Position by Page Type") st.plotly_chart(fig_position, use_container_width=True) with tab4: competitive_analysis = results.get('competitive_analysis', {}) if competitive_analysis: st.subheader("Competitive Position Analysis") col1, col2 = st.columns(2) with col1: st.metric("Market Position", competitive_analysis['market_position']) st.metric("Competitive Strength", f"{competitive_analysis['competitive_strength_score']}/3.0") with col2: # Competitive distribution comp_data = { 'Dominant (1-3)': competitive_analysis['dominant_keywords'], 'Competitive (4-10)': competitive_analysis['competitive_keywords'], 'Losing (11+)': competitive_analysis['losing_keywords'] } fig = px.bar( x=list(comp_data.keys()), y=list(comp_data.values()), title="Keyword Competitive Position" ) st.plotly_chart(fig, use_container_width=True) with tab5: technical_insights = results.get('technical_insights', {}) if technical_insights: st.subheader("Technical SEO Signals") # Crawl issues indicators crawl_issues = technical_insights.get('crawl_issues_indicators', []) if crawl_issues: st.markdown("#### ⚠️ Potential Issues") for issue in crawl_issues: st.warning(f"🚨 {issue}") # Mobile performance mobile_perf = technical_insights.get('mobile_performance', {}) if mobile_perf: st.markdown("#### 📱 Mobile Performance") col1, col2 = st.columns(2) with col1: st.metric("Avg Mobile Position", f"{mobile_perf.get('avg_mobile_position', 0):.1f}") with col2: if mobile_perf.get('mobile_optimization_needed', False): st.warning("📱 Mobile optimization needed") else: st.success("📱 Mobile performance good") # Export functionality st.markdown("---") col1, col2, col3 = st.columns(3) with col1: if st.button("📥 Export Full Report", use_container_width=True): report_json = json.dumps(results, indent=2, default=str) st.download_button( label="Download JSON Report", data=report_json, file_name=f"gsc_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json", mime="application/json" ) with col2: if st.button("📊 Export Opportunities", use_container_width=True): if opportunities: df_opportunities = pd.DataFrame(opportunities) csv = df_opportunities.to_csv(index=False) st.download_button( label="Download CSV Opportunities", data=csv, file_name=f"content_opportunities_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", mime="text/csv" ) with col3: if st.button("🔄 Refresh Analysis", use_container_width=True): # Clear cached results to force refresh if 'gsc_results' in st.session_state: del st.session_state.gsc_results st.rerun() # Main execution if __name__ == "__main__": render_gsc_integration()