Google trends data and keyword research
This commit is contained in:
425
lib/alwrity_ui/google_trends_ui.py
Normal file
425
lib/alwrity_ui/google_trends_ui.py
Normal file
@@ -0,0 +1,425 @@
|
||||
"""
|
||||
Module for displaying Google Trends data in the Streamlit UI.
|
||||
|
||||
This module provides functions for visualizing Google Trends data, including:
|
||||
- Interest over time
|
||||
- Regional interest
|
||||
- Related queries
|
||||
- Related topics
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import plotly.express as px
|
||||
import plotly.graph_objects as go
|
||||
import logging
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def display_google_trends_data(trends_data, search_keyword):
|
||||
"""
|
||||
Display Google Trends data in a structured format with tabs for different sections.
|
||||
|
||||
Args:
|
||||
trends_data (dict): Dictionary containing Google Trends data
|
||||
search_keyword (str): The search keyword used for the analysis
|
||||
"""
|
||||
if not trends_data:
|
||||
st.warning("No Google Trends data available for this search.")
|
||||
return
|
||||
|
||||
st.subheader(f"Google Trends Analysis for '{search_keyword}'")
|
||||
|
||||
# Add an informative message about Google Trends
|
||||
with st.expander("ℹ️ About Google Trends Data", expanded=False):
|
||||
st.markdown("""
|
||||
**What is Google Trends?**
|
||||
|
||||
Google Trends is a public web facility that shows how often a particular search-term is entered relative to the total search-volume across various regions of the world, and in various languages.
|
||||
|
||||
**What data is shown here?**
|
||||
|
||||
- **Related Keywords**: Terms that are frequently searched together with your keyword
|
||||
- **Interest Over Time**: How interest in your keyword has changed over the past 12 months
|
||||
- **Regional Interest**: Where in the world your keyword is most popular
|
||||
- **Related Queries**: What people search for before and after searching for your keyword
|
||||
- **Related Topics**: Topics that are closely related to your keyword
|
||||
|
||||
**How to interpret the data:**
|
||||
|
||||
- Interest values range from 0 to 100, where 100 is the peak popularity for the term
|
||||
- A value of 50 means the term is half as popular as the peak
|
||||
- A value of 0 means there was not enough data for this term
|
||||
""")
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
||||
"Related Keywords",
|
||||
"Interest Over Time",
|
||||
"Regional Interest",
|
||||
"Related Queries",
|
||||
"Related Topics"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
display_keywords_section(trends_data.get('related_keywords', []))
|
||||
|
||||
with tab2:
|
||||
display_interest_over_time(trends_data.get('interest_over_time', pd.DataFrame()))
|
||||
|
||||
with tab3:
|
||||
display_regional_interest(trends_data.get('regional_interest', pd.DataFrame()))
|
||||
|
||||
with tab4:
|
||||
display_related_queries(trends_data.get('related_queries', pd.DataFrame()))
|
||||
|
||||
with tab5:
|
||||
display_related_topics(trends_data.get('related_topics', pd.DataFrame()))
|
||||
|
||||
# Add a footer with data source information
|
||||
st.markdown("---")
|
||||
st.caption("Data source: Google Trends | Last updated: " + pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||||
|
||||
def display_keywords_section(keywords):
|
||||
"""Display related keywords from Google Trends in a table format."""
|
||||
if not keywords:
|
||||
st.info("No related keywords data available.")
|
||||
return
|
||||
|
||||
st.subheader("Related Keywords")
|
||||
st.write("Keywords related to your search:")
|
||||
|
||||
# Add explanation about related keywords
|
||||
with st.expander("ℹ️ About Related Keywords", expanded=False):
|
||||
st.markdown("""
|
||||
**What are Related Keywords?**
|
||||
|
||||
Related keywords are terms that are frequently searched together with your main keyword.
|
||||
These keywords can help you understand what topics are associated with your search term
|
||||
and can be valuable for content planning and SEO strategies.
|
||||
|
||||
**How to use this data:**
|
||||
|
||||
- Use these keywords to expand your content strategy
|
||||
- Identify gaps in your content that you could fill
|
||||
- Understand what your audience is interested in
|
||||
- Improve your SEO by incorporating these terms naturally in your content
|
||||
""")
|
||||
|
||||
# Create a DataFrame for better display
|
||||
df = pd.DataFrame(keywords, columns=['Keyword'])
|
||||
st.dataframe(df, use_container_width=True)
|
||||
|
||||
# Add a note about the number of keywords
|
||||
st.caption(f"Found {len(keywords)} related keywords")
|
||||
|
||||
def display_interest_over_time(interest_df):
|
||||
"""Display a chart showing interest over time for a given search keyword."""
|
||||
if interest_df.empty:
|
||||
st.info("No interest over time data available.")
|
||||
return
|
||||
|
||||
st.subheader("Interest Over Time")
|
||||
|
||||
# Add explanation about interest over time
|
||||
with st.expander("ℹ️ About Interest Over Time", expanded=False):
|
||||
st.markdown("""
|
||||
**What is Interest Over Time?**
|
||||
|
||||
Interest Over Time shows how interest in your search term has changed over the past 12 months.
|
||||
The data is normalized and presented on a scale from 0 to 100, where 100 is the peak popularity
|
||||
for the term, 50 means the term is half as popular, and 0 means there was not enough data.
|
||||
|
||||
**How to interpret this chart:**
|
||||
|
||||
- Look for peaks and valleys to identify trends
|
||||
- Compare with seasonal patterns or events
|
||||
- Identify if interest is growing, declining, or stable
|
||||
- Use this data to time your content releases for maximum impact
|
||||
""")
|
||||
|
||||
try:
|
||||
# Ensure we have the required columns
|
||||
if 'date' not in interest_df.columns:
|
||||
st.error("Interest over time data is missing the 'date' column.")
|
||||
return
|
||||
|
||||
if 'interest' not in interest_df.columns:
|
||||
st.error("Interest over time data is missing the 'interest' column.")
|
||||
return
|
||||
|
||||
# Create the chart
|
||||
fig = px.line(
|
||||
interest_df,
|
||||
x='date',
|
||||
y='interest',
|
||||
title='Interest Over Time',
|
||||
labels={'date': 'Date', 'interest': 'Interest'},
|
||||
line_shape='spline'
|
||||
)
|
||||
|
||||
fig.update_layout(
|
||||
xaxis_title="Date",
|
||||
yaxis_title="Interest",
|
||||
hovermode='x unified'
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Add summary statistics
|
||||
if not interest_df.empty:
|
||||
col1, col2, col3 = st.columns(3)
|
||||
with col1:
|
||||
st.metric("Average Interest", f"{interest_df['interest'].mean():.1f}")
|
||||
with col2:
|
||||
st.metric("Peak Interest", f"{interest_df['interest'].max():.1f}")
|
||||
with col3:
|
||||
st.metric("Lowest Interest", f"{interest_df['interest'].min():.1f}")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error displaying interest over time chart: {str(e)}")
|
||||
logger.error(f"Error in display_interest_over_time: {e}")
|
||||
|
||||
def display_regional_interest(regional_df):
|
||||
"""Display a chart showing interest by region for the search keyword."""
|
||||
if regional_df.empty:
|
||||
st.info("No regional interest data available.")
|
||||
return
|
||||
|
||||
st.subheader("Regional Interest")
|
||||
|
||||
# Add explanation about regional interest
|
||||
with st.expander("ℹ️ About Regional Interest", expanded=False):
|
||||
st.markdown("""
|
||||
**What is Regional Interest?**
|
||||
|
||||
Regional Interest shows how interest in your search term varies across different countries.
|
||||
The data is normalized and presented on a scale from 0 to 100, where 100 is the peak popularity
|
||||
for the term in that region, 50 means the term is half as popular, and 0 means there was not enough data.
|
||||
|
||||
**How to interpret this map:**
|
||||
|
||||
- Darker colors indicate higher interest in that region
|
||||
- Lighter colors indicate lower interest
|
||||
- Hover over a country to see the exact interest value
|
||||
- Use this data to target your content to specific regions
|
||||
""")
|
||||
|
||||
try:
|
||||
# Ensure we have the required columns
|
||||
if 'country_code' not in regional_df.columns:
|
||||
st.error("Regional interest data is missing the 'country_code' column.")
|
||||
return
|
||||
|
||||
if 'interest' not in regional_df.columns:
|
||||
st.error("Regional interest data is missing the 'interest' column.")
|
||||
return
|
||||
|
||||
# Create the choropleth map
|
||||
fig = go.Figure(data=go.Choropleth(
|
||||
locations=regional_df['country_code'],
|
||||
z=regional_df['interest'],
|
||||
text=regional_df['country_code'], # This will show in the hover text
|
||||
colorscale='Viridis',
|
||||
colorbar_title="Interest Level",
|
||||
zmin=0,
|
||||
zmax=100,
|
||||
marker_line_color='darkgray',
|
||||
marker_line_width=0.5,
|
||||
showscale=True,
|
||||
colorbar=dict(
|
||||
title="Interest Level",
|
||||
tickformat=".0f",
|
||||
tickmode="linear",
|
||||
tick0=0,
|
||||
dtick=20
|
||||
)
|
||||
))
|
||||
|
||||
# Update the layout for better visualization
|
||||
fig.update_layout(
|
||||
title=dict(
|
||||
text='Regional Interest Distribution',
|
||||
x=0.5,
|
||||
xanchor='center'
|
||||
),
|
||||
geo=dict(
|
||||
showframe=False,
|
||||
showcoastlines=True,
|
||||
projection_type='equirectangular',
|
||||
showland=True,
|
||||
landcolor='lightgray',
|
||||
showocean=True,
|
||||
oceancolor='aliceblue',
|
||||
showcountries=True,
|
||||
countrycolor='darkgray'
|
||||
),
|
||||
width=800,
|
||||
height=500,
|
||||
margin=dict(l=0, r=0, t=30, b=0)
|
||||
)
|
||||
|
||||
# Display the map
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Display top 5 countries with highest interest
|
||||
if not regional_df.empty:
|
||||
st.subheader("Top Regions by Interest")
|
||||
top_regions = regional_df.sort_values('interest', ascending=False).head(5)
|
||||
|
||||
# Create a more visually appealing bar chart for top regions
|
||||
fig_bar = go.Figure(data=[
|
||||
go.Bar(
|
||||
x=top_regions['country_code'],
|
||||
y=top_regions['interest'],
|
||||
text=top_regions['interest'].round(1),
|
||||
textposition='auto',
|
||||
marker_color='rgb(55, 83, 109)'
|
||||
)
|
||||
])
|
||||
|
||||
fig_bar.update_layout(
|
||||
title='Top 5 Regions by Interest Level',
|
||||
xaxis_title='Region',
|
||||
yaxis_title='Interest Level',
|
||||
yaxis_range=[0, 100],
|
||||
showlegend=False
|
||||
)
|
||||
|
||||
st.plotly_chart(fig_bar, use_container_width=True)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error displaying regional interest chart: {str(e)}")
|
||||
logger.error(f"Error in display_regional_interest: {e}")
|
||||
|
||||
def display_related_queries(queries_df):
|
||||
"""Display related queries in a structured format."""
|
||||
if queries_df.empty:
|
||||
st.info("No related queries data available.")
|
||||
return
|
||||
|
||||
st.subheader("Related Queries")
|
||||
|
||||
# Add explanation about related queries
|
||||
with st.expander("ℹ️ About Related Queries", expanded=False):
|
||||
st.markdown("""
|
||||
**What are Related Queries?**
|
||||
|
||||
Related Queries show what people search for before and after searching for your keyword.
|
||||
These queries can help you understand the search intent and context around your keyword.
|
||||
|
||||
**How to interpret this data:**
|
||||
|
||||
- The 'value' column shows the relative interest compared to your main keyword
|
||||
- Higher values indicate stronger association with your keyword
|
||||
- Use these queries to expand your content strategy
|
||||
- Identify what questions your audience is trying to answer
|
||||
""")
|
||||
|
||||
try:
|
||||
# Ensure we have the required columns
|
||||
if 'query' not in queries_df.columns:
|
||||
st.error("Related queries data is missing the 'query' column.")
|
||||
return
|
||||
|
||||
if 'value' not in queries_df.columns:
|
||||
st.error("Related queries data is missing the 'value' column.")
|
||||
return
|
||||
|
||||
# Sort by value in descending order
|
||||
queries_df = queries_df.sort_values('value', ascending=False)
|
||||
|
||||
# Display as a table
|
||||
st.dataframe(queries_df, use_container_width=True)
|
||||
|
||||
# Add a note about the number of queries
|
||||
st.caption(f"Found {len(queries_df)} related queries")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error displaying related queries: {str(e)}")
|
||||
logger.error(f"Error in display_related_queries: {e}")
|
||||
|
||||
def display_related_topics(topics_df):
|
||||
"""Display related topics in a structured format."""
|
||||
if topics_df.empty:
|
||||
st.info("No related topics data available.")
|
||||
return
|
||||
|
||||
st.subheader("Related Topics")
|
||||
|
||||
# Add explanation about related topics
|
||||
with st.expander("ℹ️ About Related Topics", expanded=False):
|
||||
st.markdown("""
|
||||
**What are Related Topics?**
|
||||
|
||||
Related Topics show broader topics that are associated with your search term.
|
||||
These topics can help you understand the broader context and themes related to your keyword.
|
||||
|
||||
**How to interpret this data:**
|
||||
|
||||
- The 'value' column shows the relative interest compared to your main keyword
|
||||
- Higher values indicate stronger association with your keyword
|
||||
- Use these topics to understand the broader context of your keyword
|
||||
- Identify themes that might be relevant to your content strategy
|
||||
""")
|
||||
|
||||
try:
|
||||
# Ensure we have the required columns
|
||||
if 'topic' not in topics_df.columns:
|
||||
st.error("Related topics data is missing the 'topic' column.")
|
||||
return
|
||||
|
||||
if 'value' not in topics_df.columns:
|
||||
st.error("Related topics data is missing the 'value' column.")
|
||||
return
|
||||
|
||||
# Sort by value in descending order
|
||||
topics_df = topics_df.sort_values('value', ascending=False)
|
||||
|
||||
# Display as a table
|
||||
st.dataframe(topics_df, use_container_width=True)
|
||||
|
||||
# Add a note about the number of topics
|
||||
st.caption(f"Found {len(topics_df)} related topics")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error displaying related topics: {str(e)}")
|
||||
logger.error(f"Error in display_related_topics: {e}")
|
||||
|
||||
def process_trends_data(trends_data):
|
||||
"""
|
||||
Process and format Google Trends data for display.
|
||||
|
||||
Args:
|
||||
trends_data (dict): Raw Google Trends data
|
||||
|
||||
Returns:
|
||||
dict: Formatted data ready for display
|
||||
"""
|
||||
if not trends_data:
|
||||
return {}
|
||||
|
||||
processed_data = {}
|
||||
|
||||
# Process related keywords
|
||||
if 'related_keywords' in trends_data:
|
||||
processed_data['related_keywords'] = trends_data['related_keywords']
|
||||
|
||||
# Process interest over time
|
||||
if 'interest_over_time' in trends_data and not trends_data['interest_over_time'].empty:
|
||||
processed_data['interest_over_time'] = trends_data['interest_over_time']
|
||||
|
||||
# Process regional interest
|
||||
if 'regional_interest' in trends_data and not trends_data['regional_interest'].empty:
|
||||
processed_data['regional_interest'] = trends_data['regional_interest']
|
||||
|
||||
# Process related queries
|
||||
if 'related_queries' in trends_data and not trends_data['related_queries'].empty:
|
||||
processed_data['related_queries'] = trends_data['related_queries']
|
||||
|
||||
# Process related topics
|
||||
if 'related_topics' in trends_data and not trends_data['related_topics'].empty:
|
||||
processed_data['related_topics'] = trends_data['related_topics']
|
||||
|
||||
return processed_data
|
||||
@@ -102,7 +102,12 @@ def validate_api_keys():
|
||||
return api_keys
|
||||
|
||||
def do_web_research():
|
||||
"""Input keywords and do web research with advanced options."""
|
||||
"""Main function to perform web research based on user input."""
|
||||
|
||||
# Reset session state variables for this research operation
|
||||
if 'metaphor_results_displayed' in st.session_state:
|
||||
del st.session_state.metaphor_results_displayed
|
||||
|
||||
logger.info("Starting do_web_research function")
|
||||
|
||||
try:
|
||||
@@ -509,7 +514,7 @@ def do_web_research():
|
||||
status_display.success("✨ Research completed!")
|
||||
|
||||
# Display results in an organized way
|
||||
with st.expander("📊 Research Results", expanded=True):
|
||||
with st.expander("📊 Research Results", expanded=False):
|
||||
st.write(web_research_result)
|
||||
else:
|
||||
st.warning("No results found for your search")
|
||||
|
||||
Reference in New Issue
Block a user