Facebook AI Writer - Ad Copy Generator, Event Generator, Group Post Generator, Hashtag Generator, Page About Generator, Facebook Carousel Generator, Facebook Reel Generator
This commit is contained in:
@@ -12,17 +12,19 @@ import streamlit as st
|
||||
import importlib
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Union
|
||||
|
||||
from ...gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
from .modules.post_generator import write_fb_post
|
||||
from .modules.story_generator import write_fb_story
|
||||
#from .modules.reel_generator import write_fb_reel
|
||||
#from .modules.carousel_generator import write_fb_carousel
|
||||
#from .modules.event_generator import write_fb_event
|
||||
#from .modules.group_post_generator import write_fb_group_post
|
||||
#from .modules.page_about_generator import write_fb_page_about
|
||||
#from .modules.ad_copy_generator import write_fb_ad_copy
|
||||
#from .modules.hashtag_generator import write_fb_hashtags
|
||||
#from .modules.engagement_analyzer import analyze_fb_engagement
|
||||
from .modules.facebook_reel.reel_generator import write_fb_reel
|
||||
from .modules.facebook_carousel.carousel_generator import write_fb_carousel
|
||||
from .modules.event_generator import write_fb_event
|
||||
from .modules.hashtag_generator import write_fb_hashtags
|
||||
from .modules.engagement_analyzer import analyze_fb_engagement
|
||||
from .modules.group_post_generator import write_fb_group_post
|
||||
from .modules.page_about_generator import write_fb_page_about
|
||||
from .modules.ad_copy_generator import write_fb_ad_copy
|
||||
|
||||
#from streamlit_quill import st_quill
|
||||
|
||||
@@ -191,16 +193,53 @@ def facebook_main_menu():
|
||||
# If a tool is selected, show its input section
|
||||
if st.session_state.selected_tool is not None:
|
||||
with tool_container:
|
||||
# Display the selected tool's input section
|
||||
st.markdown("---")
|
||||
st.markdown(f"# {st.session_state.selected_tool['icon']} {st.session_state.selected_tool['name']}")
|
||||
|
||||
# Add a back button
|
||||
# Add a back button at the top
|
||||
if st.button("← Back to Dashboard", key="back_to_dashboard"):
|
||||
# Clear the selected tool from session state
|
||||
st.session_state.selected_tool = None
|
||||
st.rerun()
|
||||
|
||||
# Display the tool header with card layout
|
||||
st.markdown(f"""
|
||||
<div style='
|
||||
background: linear-gradient(145deg, #ffffff 0%, #f0f7ff 50%, #e6f0ff 100%);
|
||||
padding: 2.5rem;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 25px rgba(24, 119, 242, 0.08);
|
||||
margin: 1rem 0 2.5rem 0;
|
||||
border: 1px solid rgba(24, 119, 242, 0.1);
|
||||
'>
|
||||
<div style='
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1.2rem;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 15px rgba(24, 119, 242, 0.05);
|
||||
'>
|
||||
<div style='
|
||||
font-size: 2.5rem;
|
||||
margin-right: 1rem;
|
||||
color: #1877F2;
|
||||
'>{st.session_state.selected_tool['icon']}</div>
|
||||
<div>
|
||||
<h1 style='
|
||||
margin: 0;
|
||||
color: #1877F2;
|
||||
font-size: 2.2rem;
|
||||
font-weight: 600;
|
||||
'>{st.session_state.selected_tool['name']}</h1>
|
||||
<p style='
|
||||
color: #666;
|
||||
margin: 0.5rem 0 0 0;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.5;
|
||||
'>{st.session_state.selected_tool['description']}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Call the function for the selected tool
|
||||
if st.session_state.selected_tool["function"]:
|
||||
st.session_state.selected_tool["function"]()
|
||||
@@ -208,7 +247,7 @@ def facebook_main_menu():
|
||||
# Display coming soon or future tool information
|
||||
st.info(f"**{st.session_state.selected_tool['status'].replace('_', ' ').title()}!**")
|
||||
st.write(st.session_state.selected_tool["description"])
|
||||
st.image(f"https://via.placeholder.com/600x300?text={st.session_state.selected_tool['name']}+Coming+Soon", use_column_width=True)
|
||||
st.image(f"https://via.placeholder.com/600x300?text={st.session_state.selected_tool['name']}+Coming+Soon", use_container_width=True)
|
||||
else:
|
||||
with dashboard_container:
|
||||
# Display the dashboard
|
||||
@@ -262,5 +301,58 @@ def facebook_main_menu():
|
||||
st.rerun()
|
||||
|
||||
|
||||
class FacebookAIWriter:
|
||||
"""
|
||||
AI-powered content generator for Facebook marketing and communication.
|
||||
|
||||
This class provides various tools for generating Facebook content including:
|
||||
- Posts and updates
|
||||
- Page About sections
|
||||
- Event descriptions
|
||||
- Ad copy
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the Facebook AI Writer."""
|
||||
pass
|
||||
|
||||
def generate_post(self, **kwargs) -> str:
|
||||
"""Generate a Facebook post."""
|
||||
return write_fb_post(**kwargs)
|
||||
|
||||
def generate_page_about(self, **kwargs) -> str:
|
||||
"""Generate a Facebook Page About section."""
|
||||
return write_fb_page_about(**kwargs)
|
||||
|
||||
def generate_event(self, **kwargs) -> str:
|
||||
"""Generate a Facebook Event description."""
|
||||
return write_fb_event(**kwargs)
|
||||
|
||||
def generate_ad_copy(self, **kwargs) -> Dict[str, Union[str, List[str]]]:
|
||||
"""
|
||||
Generate Facebook Ad copy with variations.
|
||||
|
||||
Returns:
|
||||
Dict containing the generated ad copy and its variations.
|
||||
"""
|
||||
return write_fb_ad_copy(**kwargs)
|
||||
|
||||
# List of available tools
|
||||
AVAILABLE_TOOLS = [
|
||||
'Post Generator',
|
||||
'Page About Generator',
|
||||
'Event Generator',
|
||||
'Ad Copy Generator'
|
||||
]
|
||||
|
||||
# Coming soon features
|
||||
COMING_SOON = [
|
||||
'Story Generator',
|
||||
'Poll Generator',
|
||||
'Group Post Generator',
|
||||
'Carousel Post Generator',
|
||||
'Comment Response Generator'
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
facebook_main_menu()
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
# Facebook Ad Copy Generator
|
||||
|
||||
## Overview
|
||||
The Facebook Ad Copy Generator is a powerful tool designed to help marketers and businesses create high-converting ad copy for Facebook Ads. It provides a comprehensive interface for crafting compelling ad content with targeting suggestions and performance optimization features.
|
||||
|
||||
## Features
|
||||
|
||||
### Ad Objective & Format
|
||||
- **Ad Objectives**: Choose from Awareness, Traffic, Engagement, Leads, App Promotion, Sales, Conversions
|
||||
- **Ad Formats**: Single Image, Carousel, Video, Collection, Instant Experience
|
||||
- **Campaign Setup**: Name, budget range, and placement options
|
||||
- **Format Preview**: Visual examples of each ad format
|
||||
|
||||
### Target Audience
|
||||
- **Demographics**: Age, gender, location targeting
|
||||
- **Interest Targeting**: Interest-based audience selection
|
||||
- **Behavior Targeting**: User behavior and activity-based targeting
|
||||
- **Custom Audiences**: Upload and manage custom audience lists
|
||||
- **Lookalike Audiences**: Create similar audience profiles
|
||||
|
||||
### Ad Content
|
||||
- **Headlines**: Primary and secondary headline options
|
||||
- **Description**: Main ad copy with character limits
|
||||
- **Link Description**: URL preview text optimization
|
||||
- **Brand Voice**: Tone and style customization
|
||||
- **Key Points**: Highlight main benefits and features
|
||||
- **USP**: Unique selling proposition emphasis
|
||||
|
||||
### Call-to-Action
|
||||
- **CTA Buttons**: Various pre-defined CTA options
|
||||
- **Custom CTAs**: Create personalized call-to-actions
|
||||
- **Urgency Elements**: Time-sensitive offer integration
|
||||
- **Offer Details**: Special promotion formatting
|
||||
|
||||
### Preview & Export
|
||||
- **Live Preview**: See how your ad will appear
|
||||
- **Mobile/Desktop**: View across different devices
|
||||
- **A/B Testing**: Generate multiple variations
|
||||
- **Export Options**: Various format support
|
||||
|
||||
## How to Use
|
||||
|
||||
1. **Access the Generator**
|
||||
- Navigate to the Ad Copy Generator in the AI Writer dashboard
|
||||
- Select "Create New Ad" to start
|
||||
|
||||
2. **Configure Ad Settings**
|
||||
- Choose your objective and format
|
||||
- Set up campaign details
|
||||
- Select ad placements
|
||||
|
||||
3. **Define Target Audience**
|
||||
- Set demographic parameters
|
||||
- Choose interests and behaviors
|
||||
- Configure custom audiences
|
||||
|
||||
4. **Create Ad Content**
|
||||
- Write or generate headlines
|
||||
- Craft main ad copy
|
||||
- Add call-to-action
|
||||
- Preview and adjust
|
||||
|
||||
5. **Export and Test**
|
||||
- Preview across devices
|
||||
- Generate variations
|
||||
- Export final copy
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Ad Copy Creation
|
||||
- Keep copy clear and concise
|
||||
- Focus on benefits over features
|
||||
- Use strong call-to-actions
|
||||
- Include social proof
|
||||
- Maintain brand voice
|
||||
|
||||
### Targeting
|
||||
- Define specific audience segments
|
||||
- Use relevant interests
|
||||
- Leverage custom audiences
|
||||
- Test different combinations
|
||||
- Monitor performance
|
||||
|
||||
### Format Selection
|
||||
- Match format to objective
|
||||
- Optimize for placements
|
||||
- Use high-quality visuals
|
||||
- Follow Facebook guidelines
|
||||
- Test multiple formats
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- Streamlit
|
||||
- Required Python packages:
|
||||
- streamlit
|
||||
- typing
|
||||
- datetime
|
||||
- json
|
||||
- logging
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Content Generation Fails**
|
||||
- Check internet connection
|
||||
- Verify input parameters
|
||||
- Try reducing complexity
|
||||
|
||||
2. **Preview Issues**
|
||||
- Clear cache
|
||||
- Check format compatibility
|
||||
- Verify character limits
|
||||
|
||||
3. **Export Problems**
|
||||
- Check file permissions
|
||||
- Verify format support
|
||||
- Ensure valid content
|
||||
|
||||
## Future Updates
|
||||
|
||||
- Enhanced AI copy suggestions
|
||||
- Advanced audience insights
|
||||
- Performance prediction
|
||||
- Multi-language support
|
||||
- Dynamic content optimization
|
||||
- Automated A/B testing
|
||||
- ROI calculator
|
||||
- Campaign scheduling
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to improve the Facebook Ad Copy Generator. Please follow these steps:
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
This module is licensed under the MIT License. See the LICENSE file for details.
|
||||
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Facebook Ad Copy Generator Module
|
||||
|
||||
This module provides functionality to generate high-converting ad copy for Facebook Ads.
|
||||
It helps marketers create compelling ad content with targeting suggestions and
|
||||
performance optimization features.
|
||||
"""
|
||||
|
||||
from .ad_copy_generator import write_fb_ad_copy
|
||||
|
||||
__all__ = ['write_fb_ad_copy']
|
||||
@@ -0,0 +1,673 @@
|
||||
"""
|
||||
Facebook Ad Copy Generator Module
|
||||
|
||||
This module provides functionality to generate high-converting ad copy for Facebook Ads.
|
||||
It helps marketers create compelling ad content with targeting suggestions and
|
||||
performance optimization features.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional, Union, Tuple
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def write_fb_ad_copy():
|
||||
"""
|
||||
Generate Facebook Ad copy with various customization options.
|
||||
|
||||
This function provides a comprehensive interface for creating high-converting
|
||||
ad copy for Facebook Ads with features like:
|
||||
- Ad objective and format selection
|
||||
- Target audience configuration
|
||||
- Ad content customization
|
||||
- Call-to-action optimization
|
||||
- Preview and export options
|
||||
"""
|
||||
|
||||
st.title("Facebook Ad Copy Generator")
|
||||
st.markdown("""
|
||||
Create high-converting ad copy for your Facebook Ads with AI-powered suggestions
|
||||
and targeting recommendations.
|
||||
""")
|
||||
|
||||
# Initialize session state for form data
|
||||
if 'ad_copy_data' not in st.session_state:
|
||||
st.session_state.ad_copy_data = {
|
||||
# Ad Objective & Format
|
||||
'objective': 'awareness',
|
||||
'format': 'single_image',
|
||||
'campaign_name': '',
|
||||
'budget_range': (100, 1000),
|
||||
'placements': ['feed'],
|
||||
|
||||
# Target Audience
|
||||
'age_range': (18, 65),
|
||||
'gender': 'all',
|
||||
'location': '',
|
||||
'interests': [],
|
||||
'behaviors': [],
|
||||
'custom_audience': '',
|
||||
'lookalike_source': '',
|
||||
|
||||
# Ad Content
|
||||
'primary_headline': '',
|
||||
'secondary_headline': '',
|
||||
'description': '',
|
||||
'link_description': '',
|
||||
'brand_voice': 'professional',
|
||||
'key_points': [],
|
||||
'usp': '',
|
||||
|
||||
# Call-to-Action
|
||||
'cta_type': 'learn_more',
|
||||
'cta_text': '',
|
||||
'use_urgency': False,
|
||||
'offer_details': '',
|
||||
|
||||
# Content Length
|
||||
'content_length': 'standard',
|
||||
|
||||
# Generated Content
|
||||
'generated_content': '',
|
||||
'show_preview': False,
|
||||
'variations': []
|
||||
}
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
||||
"Ad Objective & Format",
|
||||
"Target Audience",
|
||||
"Ad Content",
|
||||
"Call-to-Action",
|
||||
"Preview & Export"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
render_objective_format_tab()
|
||||
|
||||
with tab2:
|
||||
render_target_audience_tab()
|
||||
|
||||
with tab3:
|
||||
render_ad_content_tab()
|
||||
|
||||
with tab4:
|
||||
render_cta_tab()
|
||||
|
||||
with tab5:
|
||||
render_preview_export_tab()
|
||||
|
||||
# Generate button
|
||||
if st.button("Generate Ad Copy", type="primary"):
|
||||
if validate_ad_copy_fields():
|
||||
with st.spinner("Generating your ad copy..."):
|
||||
ad_content = generate_ad_copy()
|
||||
if ad_content:
|
||||
st.session_state.ad_copy_data['generated_content'] = ad_content
|
||||
st.success("Ad copy generated successfully!")
|
||||
st.session_state.ad_copy_data['show_preview'] = True
|
||||
# Generate variations for A/B testing
|
||||
variations = generate_ad_variations()
|
||||
if variations:
|
||||
st.session_state.ad_copy_data['variations'] = variations
|
||||
st.rerun()
|
||||
|
||||
def render_objective_format_tab():
|
||||
"""Render the ad objective and format selection fields."""
|
||||
|
||||
st.header("Ad Objective & Format")
|
||||
|
||||
# Ad Objective
|
||||
objective = st.selectbox(
|
||||
"Ad Objective",
|
||||
options=['awareness', 'traffic', 'engagement', 'leads', 'app_promotion', 'sales', 'conversions'],
|
||||
index=['awareness', 'traffic', 'engagement', 'leads', 'app_promotion', 'sales', 'conversions'].index(
|
||||
st.session_state.ad_copy_data['objective']
|
||||
),
|
||||
help="Choose the main objective of your ad campaign"
|
||||
)
|
||||
st.session_state.ad_copy_data['objective'] = objective
|
||||
|
||||
# Ad Format
|
||||
format_col1, format_col2 = st.columns(2)
|
||||
|
||||
with format_col1:
|
||||
ad_format = st.selectbox(
|
||||
"Ad Format",
|
||||
options=['single_image', 'carousel', 'video', 'collection', 'instant_experience'],
|
||||
index=['single_image', 'carousel', 'video', 'collection', 'instant_experience'].index(
|
||||
st.session_state.ad_copy_data['format']
|
||||
),
|
||||
help="Choose the format of your ad"
|
||||
)
|
||||
st.session_state.ad_copy_data['format'] = ad_format
|
||||
|
||||
with format_col2:
|
||||
# Show format preview
|
||||
st.image(
|
||||
f"https://via.placeholder.com/600x300?text={ad_format.replace('_', ' ').title()}+Coming+Soon",
|
||||
caption=f"{ad_format.replace('_', ' ').title()} Format Example",
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
# Campaign Setup
|
||||
st.subheader("Campaign Setup")
|
||||
|
||||
campaign_name = st.text_input(
|
||||
"Campaign Name",
|
||||
value=st.session_state.ad_copy_data['campaign_name'],
|
||||
help="Enter a name for your ad campaign"
|
||||
)
|
||||
st.session_state.ad_copy_data['campaign_name'] = campaign_name
|
||||
|
||||
# Budget Range
|
||||
budget_range = st.slider(
|
||||
"Budget Range ($)",
|
||||
min_value=1,
|
||||
max_value=10000,
|
||||
value=st.session_state.ad_copy_data['budget_range'],
|
||||
help="Set your campaign budget range"
|
||||
)
|
||||
st.session_state.ad_copy_data['budget_range'] = budget_range
|
||||
|
||||
# Ad Placements
|
||||
placement_options = [
|
||||
'feed', 'stories', 'messenger', 'marketplace', 'video_feeds',
|
||||
'in_stream', 'search', 'instagram', 'audience_network'
|
||||
]
|
||||
|
||||
placements = st.multiselect(
|
||||
"Ad Placements",
|
||||
options=placement_options,
|
||||
default=st.session_state.ad_copy_data['placements'],
|
||||
help="Choose where your ad will appear"
|
||||
)
|
||||
st.session_state.ad_copy_data['placements'] = placements
|
||||
|
||||
def render_target_audience_tab():
|
||||
"""Render the target audience configuration fields."""
|
||||
|
||||
st.header("Target Audience")
|
||||
|
||||
# Demographics
|
||||
st.subheader("Demographics")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
age_range = st.slider(
|
||||
"Age Range",
|
||||
min_value=13,
|
||||
max_value=65,
|
||||
value=st.session_state.ad_copy_data['age_range'],
|
||||
help="Select target age range"
|
||||
)
|
||||
st.session_state.ad_copy_data['age_range'] = age_range
|
||||
|
||||
with col2:
|
||||
gender = st.selectbox(
|
||||
"Gender",
|
||||
options=['all', 'male', 'female'],
|
||||
index=['all', 'male', 'female'].index(
|
||||
st.session_state.ad_copy_data['gender']
|
||||
),
|
||||
help="Select target gender"
|
||||
)
|
||||
st.session_state.ad_copy_data['gender'] = gender
|
||||
|
||||
location = st.text_input(
|
||||
"Location",
|
||||
value=st.session_state.ad_copy_data['location'],
|
||||
help="Enter target location (city, state, country)"
|
||||
)
|
||||
st.session_state.ad_copy_data['location'] = location
|
||||
|
||||
# Interests
|
||||
st.subheader("Interests")
|
||||
|
||||
# Initialize interests in session state if not present
|
||||
if 'interests' not in st.session_state.ad_copy_data:
|
||||
st.session_state.ad_copy_data['interests'] = []
|
||||
|
||||
# Add new interest
|
||||
new_interest = st.text_input("Add an interest", key="new_interest")
|
||||
if st.button("Add Interest") and new_interest:
|
||||
if new_interest not in st.session_state.ad_copy_data['interests']:
|
||||
st.session_state.ad_copy_data['interests'].append(new_interest)
|
||||
st.rerun()
|
||||
|
||||
# Display and allow removal of existing interests
|
||||
if st.session_state.ad_copy_data['interests']:
|
||||
st.write("Current Interests:")
|
||||
for i, interest in enumerate(st.session_state.ad_copy_data['interests']):
|
||||
col1, col2 = st.columns([4, 1])
|
||||
with col1:
|
||||
st.write(f"{i+1}. {interest}")
|
||||
with col2:
|
||||
if st.button("Remove", key=f"remove_interest_{i}"):
|
||||
st.session_state.ad_copy_data['interests'].pop(i)
|
||||
st.rerun()
|
||||
|
||||
# Behaviors
|
||||
st.subheader("Behaviors")
|
||||
|
||||
behavior_options = [
|
||||
'engaged_shoppers',
|
||||
'frequent_travelers',
|
||||
'technology_early_adopters',
|
||||
'small_business_owners',
|
||||
'mobile_users',
|
||||
'luxury_shoppers'
|
||||
]
|
||||
|
||||
behaviors = st.multiselect(
|
||||
"Select Behaviors",
|
||||
options=behavior_options,
|
||||
default=st.session_state.ad_copy_data['behaviors'],
|
||||
help="Choose relevant user behaviors"
|
||||
)
|
||||
st.session_state.ad_copy_data['behaviors'] = behaviors
|
||||
|
||||
# Custom & Lookalike Audiences
|
||||
st.subheader("Advanced Targeting")
|
||||
|
||||
custom_audience = st.text_area(
|
||||
"Custom Audience Source",
|
||||
value=st.session_state.ad_copy_data['custom_audience'],
|
||||
help="Describe your custom audience source (e.g., email list, website visitors)",
|
||||
height=100
|
||||
)
|
||||
st.session_state.ad_copy_data['custom_audience'] = custom_audience
|
||||
|
||||
lookalike_source = st.text_area(
|
||||
"Lookalike Audience Source",
|
||||
value=st.session_state.ad_copy_data['lookalike_source'],
|
||||
help="Describe your lookalike audience source",
|
||||
height=100
|
||||
)
|
||||
st.session_state.ad_copy_data['lookalike_source'] = lookalike_source
|
||||
|
||||
def render_ad_content_tab():
|
||||
"""Render the ad content configuration fields."""
|
||||
|
||||
st.header("Ad Content")
|
||||
|
||||
# Headlines
|
||||
st.subheader("Headlines")
|
||||
|
||||
primary_headline = st.text_input(
|
||||
"Primary Headline",
|
||||
value=st.session_state.ad_copy_data['primary_headline'],
|
||||
help="Enter your main headline (max 40 characters)",
|
||||
max_chars=40
|
||||
)
|
||||
st.session_state.ad_copy_data['primary_headline'] = primary_headline
|
||||
|
||||
secondary_headline = st.text_input(
|
||||
"Secondary Headline (optional)",
|
||||
value=st.session_state.ad_copy_data['secondary_headline'],
|
||||
help="Enter a secondary headline (max 40 characters)",
|
||||
max_chars=40
|
||||
)
|
||||
st.session_state.ad_copy_data['secondary_headline'] = secondary_headline
|
||||
|
||||
# Description
|
||||
description = st.text_area(
|
||||
"Ad Description",
|
||||
value=st.session_state.ad_copy_data['description'],
|
||||
help="Enter your ad description (max 125 characters)",
|
||||
max_chars=125,
|
||||
height=100
|
||||
)
|
||||
st.session_state.ad_copy_data['description'] = description
|
||||
|
||||
# Link Description
|
||||
link_description = st.text_input(
|
||||
"Link Description",
|
||||
value=st.session_state.ad_copy_data['link_description'],
|
||||
help="Enter your link description (max 30 characters)",
|
||||
max_chars=30
|
||||
)
|
||||
st.session_state.ad_copy_data['link_description'] = link_description
|
||||
|
||||
# Brand Voice
|
||||
brand_voice = st.selectbox(
|
||||
"Brand Voice",
|
||||
options=['professional', 'friendly', 'casual', 'formal', 'humorous'],
|
||||
index=['professional', 'friendly', 'casual', 'formal', 'humorous'].index(
|
||||
st.session_state.ad_copy_data['brand_voice']
|
||||
),
|
||||
help="Choose the tone for your ad copy"
|
||||
)
|
||||
st.session_state.ad_copy_data['brand_voice'] = brand_voice
|
||||
|
||||
# Key Points
|
||||
st.subheader("Key Points")
|
||||
|
||||
# Initialize key_points in session state if not present
|
||||
if 'key_points' not in st.session_state.ad_copy_data:
|
||||
st.session_state.ad_copy_data['key_points'] = []
|
||||
|
||||
# Add new key point
|
||||
new_point = st.text_input("Add a key point", key="new_key_point")
|
||||
if st.button("Add Point") and new_point:
|
||||
if new_point not in st.session_state.ad_copy_data['key_points']:
|
||||
st.session_state.ad_copy_data['key_points'].append(new_point)
|
||||
st.rerun()
|
||||
|
||||
# Display and allow removal of existing key points
|
||||
if st.session_state.ad_copy_data['key_points']:
|
||||
st.write("Current Key Points:")
|
||||
for i, point in enumerate(st.session_state.ad_copy_data['key_points']):
|
||||
col1, col2 = st.columns([4, 1])
|
||||
with col1:
|
||||
st.write(f"{i+1}. {point}")
|
||||
with col2:
|
||||
if st.button("Remove", key=f"remove_point_{i}"):
|
||||
st.session_state.ad_copy_data['key_points'].pop(i)
|
||||
st.rerun()
|
||||
|
||||
# Unique Selling Proposition
|
||||
usp = st.text_area(
|
||||
"Unique Selling Proposition",
|
||||
value=st.session_state.ad_copy_data['usp'],
|
||||
help="What makes your offer unique? (max 80 characters)",
|
||||
max_chars=80,
|
||||
height=100
|
||||
)
|
||||
st.session_state.ad_copy_data['usp'] = usp
|
||||
|
||||
def render_cta_tab():
|
||||
"""Render the call-to-action configuration fields."""
|
||||
|
||||
st.header("Call-to-Action")
|
||||
|
||||
# CTA Type
|
||||
cta_options = {
|
||||
'learn_more': 'Learn More',
|
||||
'shop_now': 'Shop Now',
|
||||
'sign_up': 'Sign Up',
|
||||
'book_now': 'Book Now',
|
||||
'contact_us': 'Contact Us',
|
||||
'download': 'Download',
|
||||
'get_offer': 'Get Offer',
|
||||
'watch_more': 'Watch More',
|
||||
'subscribe': 'Subscribe',
|
||||
'custom': 'Custom'
|
||||
}
|
||||
|
||||
cta_type = st.selectbox(
|
||||
"CTA Button Type",
|
||||
options=list(cta_options.keys()),
|
||||
index=list(cta_options.keys()).index(
|
||||
st.session_state.ad_copy_data['cta_type']
|
||||
),
|
||||
format_func=lambda x: cta_options[x],
|
||||
help="Choose your call-to-action button type"
|
||||
)
|
||||
st.session_state.ad_copy_data['cta_type'] = cta_type
|
||||
|
||||
# Custom CTA Text (if custom selected)
|
||||
if cta_type == 'custom':
|
||||
cta_text = st.text_input(
|
||||
"Custom CTA Text",
|
||||
value=st.session_state.ad_copy_data['cta_text'],
|
||||
help="Enter your custom call-to-action text (max 20 characters)",
|
||||
max_chars=20
|
||||
)
|
||||
st.session_state.ad_copy_data['cta_text'] = cta_text
|
||||
|
||||
# Urgency Elements
|
||||
st.subheader("Urgency Elements")
|
||||
|
||||
use_urgency = st.checkbox(
|
||||
"Add Urgency",
|
||||
value=st.session_state.ad_copy_data['use_urgency'],
|
||||
help="Add time-sensitive elements to your ad"
|
||||
)
|
||||
st.session_state.ad_copy_data['use_urgency'] = use_urgency
|
||||
|
||||
if use_urgency:
|
||||
offer_details = st.text_area(
|
||||
"Offer Details",
|
||||
value=st.session_state.ad_copy_data['offer_details'],
|
||||
help="Enter time-sensitive offer details (e.g., 'Limited time offer - 24 hours only!')",
|
||||
height=100
|
||||
)
|
||||
st.session_state.ad_copy_data['offer_details'] = offer_details
|
||||
|
||||
def render_preview_export_tab():
|
||||
"""Render the preview and export options."""
|
||||
|
||||
st.header("Preview & Export")
|
||||
|
||||
# Show preview if content has been generated
|
||||
if st.session_state.ad_copy_data['show_preview'] and st.session_state.ad_copy_data['generated_content']:
|
||||
st.subheader("Preview")
|
||||
|
||||
# Toggle between mobile and desktop view
|
||||
view_mode = st.radio("View Mode", ["Desktop", "Mobile"])
|
||||
|
||||
if view_mode == "Desktop":
|
||||
st.markdown("""
|
||||
<div style='background-color: #f0f2f6; padding: 20px; border-radius: 10px;'>
|
||||
<h2 style='color: #1877F2;'>Ad Preview</h2>
|
||||
<div style='white-space: pre-wrap;'>
|
||||
""", unsafe_allow_html=True)
|
||||
st.write(st.session_state.ad_copy_data['generated_content'])
|
||||
st.markdown("</div></div>", unsafe_allow_html=True)
|
||||
else:
|
||||
st.markdown("""
|
||||
<div style='max-width: 375px; margin: 0 auto; background-color: #f0f2f6; padding: 15px; border-radius: 10px;'>
|
||||
<h2 style='color: #1877F2; font-size: 18px;'>Ad Preview</h2>
|
||||
<div style='white-space: pre-wrap; font-size: 14px;'>
|
||||
""", unsafe_allow_html=True)
|
||||
st.write(st.session_state.ad_copy_data['generated_content'])
|
||||
st.markdown("</div></div>", unsafe_allow_html=True)
|
||||
|
||||
# A/B Testing Variations
|
||||
if st.session_state.ad_copy_data['variations']:
|
||||
st.subheader("A/B Testing Variations")
|
||||
for i, variation in enumerate(st.session_state.ad_copy_data['variations']):
|
||||
with st.expander(f"Variation {i+1}"):
|
||||
st.write(variation)
|
||||
|
||||
# Export options
|
||||
st.subheader("Export Options")
|
||||
|
||||
col1, col2, col3 = st.columns(3)
|
||||
|
||||
with col1:
|
||||
if st.button("Copy to Clipboard"):
|
||||
st.code(st.session_state.ad_copy_data['generated_content'], language=None)
|
||||
st.success("Content copied to clipboard!")
|
||||
|
||||
with col2:
|
||||
if st.button("Download as Text"):
|
||||
download_ad_copy(st.session_state.ad_copy_data['generated_content'])
|
||||
|
||||
with col3:
|
||||
if st.button("Export as JSON"):
|
||||
export_ad_copy_json()
|
||||
else:
|
||||
st.info("Generate your ad copy to see a preview and export options.")
|
||||
|
||||
def validate_ad_copy_fields() -> bool:
|
||||
"""Validate the required fields for the ad copy generator."""
|
||||
|
||||
data = st.session_state.ad_copy_data
|
||||
|
||||
# Check required fields
|
||||
if not data['campaign_name']:
|
||||
st.error("Campaign Name is required.")
|
||||
return False
|
||||
|
||||
if not data['location']:
|
||||
st.error("Location is required.")
|
||||
return False
|
||||
|
||||
if not data['primary_headline']:
|
||||
st.error("Primary Headline is required.")
|
||||
return False
|
||||
|
||||
if not data['description']:
|
||||
st.error("Ad Description is required.")
|
||||
return False
|
||||
|
||||
if not data['key_points']:
|
||||
st.error("At least one Key Point is required.")
|
||||
return False
|
||||
|
||||
if not data['usp']:
|
||||
st.error("Unique Selling Proposition is required.")
|
||||
return False
|
||||
|
||||
if data['cta_type'] == 'custom' and not data['cta_text']:
|
||||
st.error("Custom CTA Text is required when using a custom CTA.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generate_ad_copy() -> Optional[str]:
|
||||
"""Generate the ad copy content using AI."""
|
||||
|
||||
try:
|
||||
data = st.session_state.ad_copy_data
|
||||
|
||||
# Prepare the prompt for the LLM
|
||||
prompt = f"""
|
||||
Create a Facebook Ad with the following specifications:
|
||||
|
||||
Campaign Details:
|
||||
- Name: {data['campaign_name']}
|
||||
- Objective: {data['objective']}
|
||||
- Format: {data['format']}
|
||||
- Placements: {', '.join(data['placements'])}
|
||||
|
||||
Target Audience:
|
||||
- Age: {data['age_range'][0]}-{data['age_range'][1]}
|
||||
- Gender: {data['gender']}
|
||||
- Location: {data['location']}
|
||||
- Interests: {', '.join(data['interests'])}
|
||||
- Behaviors: {', '.join(data['behaviors'])}
|
||||
|
||||
Ad Content:
|
||||
- Primary Headline: {data['primary_headline']}
|
||||
- Secondary Headline: {data['secondary_headline']}
|
||||
- Description: {data['description']}
|
||||
- Link Description: {data['link_description']}
|
||||
- Brand Voice: {data['brand_voice']}
|
||||
- Key Points: {', '.join(data['key_points'])}
|
||||
- USP: {data['usp']}
|
||||
|
||||
Call-to-Action:
|
||||
- Type: {data['cta_type']}
|
||||
- Custom Text: {data['cta_text'] if data['cta_type'] == 'custom' else 'N/A'}
|
||||
- Urgency: {data['offer_details'] if data['use_urgency'] else 'No urgency element'}
|
||||
|
||||
The ad copy should be engaging, persuasive, and optimized for the selected objective.
|
||||
Use appropriate formatting and ensure the tone matches the selected brand voice.
|
||||
Include all key points and USP in a natural way.
|
||||
Make the call-to-action compelling and relevant to the objective.
|
||||
"""
|
||||
|
||||
# Get response from LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
return response
|
||||
else:
|
||||
st.error("Failed to generate ad copy content. Please try again.")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating ad copy: {str(e)}")
|
||||
st.error("An error occurred while generating the ad copy. Please try again.")
|
||||
return None
|
||||
|
||||
def generate_ad_variations() -> Optional[List[str]]:
|
||||
"""Generate variations of the ad copy for A/B testing."""
|
||||
|
||||
try:
|
||||
data = st.session_state.ad_copy_data
|
||||
|
||||
# Prepare the prompt for variations
|
||||
prompt = f"""
|
||||
Create 2 variations of the following Facebook Ad copy for A/B testing.
|
||||
Keep the core message and USP but vary the:
|
||||
1. Headline approach
|
||||
2. Description structure
|
||||
3. Call-to-action phrasing
|
||||
|
||||
Original Ad Copy:
|
||||
{data['generated_content']}
|
||||
|
||||
Make each variation unique while maintaining the brand voice ({data['brand_voice']})
|
||||
and focusing on the main objective ({data['objective']}).
|
||||
"""
|
||||
|
||||
# Get response from LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
# Split the response into variations
|
||||
variations = response.split('\n\nVariation')
|
||||
return variations[1:] if len(variations) > 1 else []
|
||||
else:
|
||||
st.warning("Failed to generate ad variations. Using original copy only.")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating ad variations: {str(e)}")
|
||||
st.warning("Failed to generate ad variations. Using original copy only.")
|
||||
return None
|
||||
|
||||
def download_ad_copy(content: str):
|
||||
"""Download the ad copy content as a text file."""
|
||||
|
||||
try:
|
||||
# Create a timestamp for the filename
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"facebook_ad_copy_{timestamp}.txt"
|
||||
|
||||
# Create a download button
|
||||
st.download_button(
|
||||
label="Download Text File",
|
||||
data=content,
|
||||
file_name=filename,
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error downloading ad copy: {str(e)}")
|
||||
st.error("An error occurred while downloading the ad copy. Please try again.")
|
||||
|
||||
def export_ad_copy_json():
|
||||
"""Export the ad copy data as a JSON file."""
|
||||
|
||||
try:
|
||||
data = st.session_state.ad_copy_data
|
||||
|
||||
# Create a timestamp for the filename
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"facebook_ad_copy_{timestamp}.json"
|
||||
|
||||
# Convert data to JSON
|
||||
json_data = json.dumps(data, indent=2)
|
||||
|
||||
# Create a download button
|
||||
st.download_button(
|
||||
label="Download JSON File",
|
||||
data=json_data,
|
||||
file_name=filename,
|
||||
mime="application/json"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error exporting ad copy JSON: {str(e)}")
|
||||
st.error("An error occurred while exporting the ad copy data. Please try again.")
|
||||
@@ -0,0 +1,88 @@
|
||||
# Facebook Engagement Analyzer
|
||||
|
||||
## Overview
|
||||
The Facebook Engagement Analyzer is a powerful tool designed to help content creators understand and improve their Facebook content performance. It provides detailed analytics, audience insights, and AI-powered suggestions to optimize engagement and reach.
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Content Analysis
|
||||
- **AI-Powered Content Evaluation**: Analyzes your content for quality and engagement potential
|
||||
- **Strengths Identification**: Highlights what's working well in your content
|
||||
- **Improvement Areas**: Points out specific areas that could be enhanced
|
||||
- **Optimization Suggestions**: Provides actionable recommendations for content improvement
|
||||
|
||||
### 2. Performance Metrics
|
||||
- **Comprehensive Metrics Tracking**: Monitor likes, comments, shares, reach, impressions, and clicks
|
||||
- **Engagement Rate Calculation**: Automatically calculates and visualizes your engagement rate
|
||||
- **Competitor Benchmarking**: Compare your performance against industry averages and top performers
|
||||
- **Visual Analytics**: Interactive charts and graphs to visualize your performance data
|
||||
|
||||
### 3. Audience Insights
|
||||
- **Demographic Analysis**: Understand your audience's age, gender, location, and device usage
|
||||
- **Peak Engagement Times**: Identify the best days and times to post for maximum engagement
|
||||
- **Audience Behavior Patterns**: Gain insights into how your audience interacts with your content
|
||||
- **Visual Data Representation**: Pie charts, bar graphs, and line charts to visualize audience data
|
||||
|
||||
### 4. Improvement Suggestions
|
||||
- **AI-Generated Recommendations**: Get personalized suggestions based on your content and metrics
|
||||
- **Expected Impact Predictions**: Understand the potential impact of each suggestion
|
||||
- **Implementation Guidance**: Step-by-step instructions for implementing each suggestion
|
||||
- **A/B Testing Ideas**: Generate and manage A/B testing scenarios to optimize your content
|
||||
|
||||
## How to Use
|
||||
|
||||
1. **Access the Tool**: Navigate to the Facebook AI Writer dashboard and select "Engagement Analyzer"
|
||||
2. **Enter Your Content**: Paste your Facebook content or URL in the Content Analysis tab
|
||||
3. **Select Content Type**: Choose the type of content you're analyzing (Post, Story, Reel, etc.)
|
||||
4. **Set Date Range**: Specify the date range for your analysis
|
||||
5. **Analyze Content**: Click "Analyze Content" to get AI-powered insights
|
||||
6. **Enter Performance Metrics**: Input your actual performance metrics in the Performance Metrics tab
|
||||
7. **Review Audience Insights**: Explore demographic data and peak engagement times
|
||||
8. **Generate Improvement Suggestions**: Get personalized recommendations to improve your content
|
||||
9. **Create A/B Tests**: Set up A/B tests based on the suggested variations
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Analysis
|
||||
- Be specific about your content goals when analyzing
|
||||
- Include the full content text for most accurate analysis
|
||||
- Consider analyzing multiple pieces of content to identify patterns
|
||||
|
||||
### Performance Metrics
|
||||
- Enter accurate metrics for the most reliable insights
|
||||
- Track metrics consistently over time to identify trends
|
||||
- Compare metrics across different content types to understand what works best
|
||||
|
||||
### Audience Insights
|
||||
- Use demographic data to tailor your content to your audience
|
||||
- Post during peak engagement times for maximum reach
|
||||
- Consider your audience's device preferences when creating content
|
||||
|
||||
### Improvement Suggestions
|
||||
- Implement suggestions gradually and measure the impact
|
||||
- Focus on high-impact, low-effort improvements first
|
||||
- Use A/B testing to validate improvements before full implementation
|
||||
|
||||
## Technical Requirements
|
||||
- Internet connection
|
||||
- Facebook account with content to analyze
|
||||
- Performance metrics data (optional but recommended)
|
||||
|
||||
## Troubleshooting
|
||||
- **Analysis Not Working**: Ensure you've entered content and selected a content type
|
||||
- **Metrics Not Updating**: Check that you've entered valid numbers for all metrics
|
||||
- **Charts Not Displaying**: Try refreshing the page or clearing your browser cache
|
||||
- **Suggestions Not Generating**: Make sure you've analyzed content and entered metrics first
|
||||
|
||||
## Future Updates
|
||||
- Historical performance tracking
|
||||
- Competitor content analysis
|
||||
- Advanced sentiment analysis
|
||||
- Custom metric tracking
|
||||
- Export functionality for reports
|
||||
|
||||
## Contributing
|
||||
We welcome feedback and contributions to improve the Engagement Analyzer. Please share your suggestions and report any issues you encounter.
|
||||
|
||||
## License
|
||||
This tool is part of the ALwrity AI Writer suite and is subject to the same licensing terms.
|
||||
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
Facebook Engagement Analyzer Module
|
||||
|
||||
This module provides functionality to analyze Facebook content performance and provide
|
||||
AI-powered suggestions for improvement.
|
||||
"""
|
||||
|
||||
from .engagement_analyzer import analyze_fb_engagement
|
||||
|
||||
__all__ = ['analyze_fb_engagement']
|
||||
@@ -0,0 +1,907 @@
|
||||
"""
|
||||
Facebook Engagement Analyzer Module
|
||||
|
||||
This module provides functionality to analyze Facebook content performance and provide
|
||||
AI-powered suggestions for improvement. It helps content creators understand what works
|
||||
and how to optimize their content for better engagement.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import json
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from datetime import datetime, timedelta
|
||||
import plotly.express as px
|
||||
import plotly.graph_objects as go
|
||||
from typing import Dict, List, Any, Tuple, Optional, Union
|
||||
from loguru import logger
|
||||
import sys
|
||||
import base64
|
||||
from io import BytesIO
|
||||
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Configure logging
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
def initialize_session_state():
|
||||
"""Initialize session state with default values."""
|
||||
if 'engagement_data' not in st.session_state:
|
||||
st.session_state.engagement_data = {
|
||||
'content': "",
|
||||
'content_type': "Post",
|
||||
'metrics': {
|
||||
'likes': 0,
|
||||
'comments': 0,
|
||||
'shares': 0,
|
||||
'reach': 0,
|
||||
'impressions': 0,
|
||||
'clicks': 0,
|
||||
'engagement_rate': 0.0
|
||||
},
|
||||
'audience_demographics': {
|
||||
'age_groups': {},
|
||||
'gender': {},
|
||||
'location': {},
|
||||
'device': {}
|
||||
},
|
||||
'peak_engagement_times': [],
|
||||
'competitor_benchmarks': {},
|
||||
'analysis_results': {},
|
||||
'improvement_suggestions': []
|
||||
}
|
||||
|
||||
def analyze_fb_engagement():
|
||||
"""Analyze Facebook content performance and provide improvement suggestions."""
|
||||
|
||||
# Initialize session state
|
||||
initialize_session_state()
|
||||
|
||||
st.markdown("""
|
||||
### 📊 Facebook Engagement Analyzer
|
||||
Analyze your content performance and get AI-powered suggestions to improve engagement.
|
||||
Understand what works, identify patterns, and optimize your Facebook strategy.
|
||||
""")
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4 = st.tabs(["Content Analysis", "Performance Metrics", "Audience Insights", "Improvement Suggestions"])
|
||||
|
||||
with tab1:
|
||||
render_content_analysis_tab()
|
||||
|
||||
with tab2:
|
||||
render_performance_metrics_tab()
|
||||
|
||||
with tab3:
|
||||
render_audience_insights_tab()
|
||||
|
||||
with tab4:
|
||||
render_improvement_suggestions_tab()
|
||||
|
||||
def render_content_analysis_tab():
|
||||
"""Render the content analysis tab with input fields."""
|
||||
|
||||
st.markdown("#### Content for Analysis")
|
||||
|
||||
# Content Input
|
||||
content = st.text_area(
|
||||
"Enter your Facebook content or paste a URL",
|
||||
value=st.session_state.engagement_data['content'],
|
||||
height=150,
|
||||
help="Enter the text content or paste a URL to your Facebook post",
|
||||
key="content_input"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['content'] = content
|
||||
|
||||
# Content Type Selection
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
content_types = ["Post", "Story", "Reel", "Carousel", "Event", "Group Post", "Page"]
|
||||
|
||||
content_type = st.selectbox(
|
||||
"Content Type",
|
||||
options=content_types,
|
||||
index=content_types.index(st.session_state.engagement_data['content_type']) if st.session_state.engagement_data['content_type'] in content_types else 0,
|
||||
help="Select the type of content you're analyzing",
|
||||
key="content_type_select"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['content_type'] = content_type
|
||||
|
||||
with col2:
|
||||
# Date Range Selection
|
||||
date_range = st.date_input(
|
||||
"Date Range",
|
||||
value=(datetime.now() - timedelta(days=7), datetime.now()),
|
||||
help="Select the date range for analysis",
|
||||
key="date_range_select"
|
||||
)
|
||||
|
||||
# Analyze Button
|
||||
if st.button("Analyze Content", key="analyze_content_button"):
|
||||
if not content:
|
||||
st.warning("Please enter some content to analyze.")
|
||||
else:
|
||||
with st.spinner("Analyzing content performance..."):
|
||||
# Perform content analysis
|
||||
analysis_results = analyze_content(
|
||||
content,
|
||||
content_type,
|
||||
date_range
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['analysis_results'] = analysis_results
|
||||
|
||||
# Display results
|
||||
display_content_analysis(analysis_results)
|
||||
|
||||
def render_performance_metrics_tab():
|
||||
"""Render the performance metrics tab."""
|
||||
|
||||
st.markdown("#### Performance Metrics")
|
||||
|
||||
# Check if we have analysis results
|
||||
if not st.session_state.engagement_data['analysis_results']:
|
||||
st.info("Please analyze your content first in the Content Analysis tab.")
|
||||
return
|
||||
|
||||
# Metrics Input
|
||||
st.markdown("##### Enter Performance Metrics")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
metrics = st.session_state.engagement_data['metrics']
|
||||
|
||||
metrics['likes'] = st.number_input(
|
||||
"Likes",
|
||||
min_value=0,
|
||||
value=metrics['likes'],
|
||||
help="Number of likes",
|
||||
key="likes_input"
|
||||
)
|
||||
|
||||
metrics['comments'] = st.number_input(
|
||||
"Comments",
|
||||
min_value=0,
|
||||
value=metrics['comments'],
|
||||
help="Number of comments",
|
||||
key="comments_input"
|
||||
)
|
||||
|
||||
metrics['shares'] = st.number_input(
|
||||
"Shares",
|
||||
min_value=0,
|
||||
value=metrics['shares'],
|
||||
help="Number of shares",
|
||||
key="shares_input"
|
||||
)
|
||||
|
||||
metrics['reach'] = st.number_input(
|
||||
"Reach",
|
||||
min_value=0,
|
||||
value=metrics['reach'],
|
||||
help="Number of people who saw your content",
|
||||
key="reach_input"
|
||||
)
|
||||
|
||||
with col2:
|
||||
metrics['impressions'] = st.number_input(
|
||||
"Impressions",
|
||||
min_value=0,
|
||||
value=metrics['impressions'],
|
||||
help="Number of times your content was shown",
|
||||
key="impressions_input"
|
||||
)
|
||||
|
||||
metrics['clicks'] = st.number_input(
|
||||
"Clicks",
|
||||
min_value=0,
|
||||
value=metrics['clicks'],
|
||||
help="Number of clicks on your content",
|
||||
key="clicks_input"
|
||||
)
|
||||
|
||||
# Calculate engagement rate
|
||||
if metrics['reach'] > 0:
|
||||
metrics['engagement_rate'] = ((metrics['likes'] + metrics['comments'] + metrics['shares']) / metrics['reach']) * 100
|
||||
else:
|
||||
metrics['engagement_rate'] = 0.0
|
||||
|
||||
st.metric(
|
||||
"Engagement Rate",
|
||||
f"{metrics['engagement_rate']:.2f}%",
|
||||
help="Percentage of people who engaged with your content"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['metrics'] = metrics
|
||||
|
||||
# Visualize metrics
|
||||
visualize_performance_metrics(metrics)
|
||||
|
||||
# Competitor Benchmarks
|
||||
st.markdown("##### Competitor Benchmarks")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
competitor_metrics = {
|
||||
"Industry Average": {
|
||||
"engagement_rate": 2.5,
|
||||
"reach": metrics['reach'] * 1.2,
|
||||
"comments": metrics['comments'] * 1.1
|
||||
},
|
||||
"Top Performers": {
|
||||
"engagement_rate": 5.0,
|
||||
"reach": metrics['reach'] * 2.0,
|
||||
"comments": metrics['comments'] * 2.5
|
||||
}
|
||||
}
|
||||
|
||||
st.session_state.engagement_data['competitor_benchmarks'] = competitor_metrics
|
||||
|
||||
# Create a DataFrame for comparison
|
||||
comparison_data = {
|
||||
"Metric": ["Engagement Rate", "Reach", "Comments"],
|
||||
"Your Content": [
|
||||
metrics['engagement_rate'],
|
||||
metrics['reach'],
|
||||
metrics['comments']
|
||||
],
|
||||
"Industry Average": [
|
||||
competitor_metrics["Industry Average"]["engagement_rate"],
|
||||
competitor_metrics["Industry Average"]["reach"],
|
||||
competitor_metrics["Industry Average"]["comments"]
|
||||
],
|
||||
"Top Performers": [
|
||||
competitor_metrics["Top Performers"]["engagement_rate"],
|
||||
competitor_metrics["Top Performers"]["reach"],
|
||||
competitor_metrics["Top Performers"]["comments"]
|
||||
]
|
||||
}
|
||||
|
||||
df = pd.DataFrame(comparison_data)
|
||||
|
||||
# Display comparison chart
|
||||
fig = go.Figure()
|
||||
|
||||
fig.add_trace(go.Bar(
|
||||
x=df["Metric"],
|
||||
y=df["Your Content"],
|
||||
name="Your Content",
|
||||
marker_color="#1877F2"
|
||||
))
|
||||
|
||||
fig.add_trace(go.Bar(
|
||||
x=df["Metric"],
|
||||
y=df["Industry Average"],
|
||||
name="Industry Average",
|
||||
marker_color="#34A853"
|
||||
))
|
||||
|
||||
fig.add_trace(go.Bar(
|
||||
x=df["Metric"],
|
||||
y=df["Top Performers"],
|
||||
name="Top Performers",
|
||||
marker_color="#EA4335"
|
||||
))
|
||||
|
||||
fig.update_layout(
|
||||
title="Performance Comparison",
|
||||
xaxis_title="Metric",
|
||||
yaxis_title="Value",
|
||||
barmode="group",
|
||||
legend=dict(
|
||||
orientation="h",
|
||||
yanchor="bottom",
|
||||
y=1.02,
|
||||
xanchor="right",
|
||||
x=1
|
||||
)
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
def render_audience_insights_tab():
|
||||
"""Render the audience insights tab."""
|
||||
|
||||
st.markdown("#### Audience Insights")
|
||||
|
||||
# Check if we have analysis results
|
||||
if not st.session_state.engagement_data['analysis_results']:
|
||||
st.info("Please analyze your content first in the Content Analysis tab.")
|
||||
return
|
||||
|
||||
# Audience Demographics
|
||||
st.markdown("##### Audience Demographics")
|
||||
|
||||
# Initialize demographics if not exists
|
||||
demographics = st.session_state.engagement_data['audience_demographics']
|
||||
|
||||
# Age Groups
|
||||
st.markdown("###### Age Distribution")
|
||||
|
||||
age_data = {
|
||||
"18-24": 15,
|
||||
"25-34": 30,
|
||||
"35-44": 25,
|
||||
"45-54": 15,
|
||||
"55-64": 10,
|
||||
"65+": 5
|
||||
}
|
||||
|
||||
demographics['age_groups'] = age_data
|
||||
|
||||
# Create age distribution chart
|
||||
fig = px.pie(
|
||||
values=list(age_data.values()),
|
||||
names=list(age_data.keys()),
|
||||
title="Age Distribution"
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Gender
|
||||
st.markdown("###### Gender Distribution")
|
||||
|
||||
gender_data = {
|
||||
"Male": 45,
|
||||
"Female": 52,
|
||||
"Other": 3
|
||||
}
|
||||
|
||||
demographics['gender'] = gender_data
|
||||
|
||||
# Create gender distribution chart
|
||||
fig = px.pie(
|
||||
values=list(gender_data.values()),
|
||||
names=list(gender_data.keys()),
|
||||
title="Gender Distribution"
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Location
|
||||
st.markdown("###### Top Locations")
|
||||
|
||||
location_data = {
|
||||
"United States": 40,
|
||||
"United Kingdom": 15,
|
||||
"Canada": 10,
|
||||
"Australia": 8,
|
||||
"India": 7,
|
||||
"Other": 20
|
||||
}
|
||||
|
||||
demographics['location'] = location_data
|
||||
|
||||
# Create location distribution chart
|
||||
fig = px.bar(
|
||||
x=list(location_data.keys()),
|
||||
y=list(location_data.values()),
|
||||
title="Top Locations"
|
||||
)
|
||||
|
||||
fig.update_layout(
|
||||
xaxis_title="Country",
|
||||
yaxis_title="Percentage"
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Device
|
||||
st.markdown("###### Device Usage")
|
||||
|
||||
device_data = {
|
||||
"Mobile": 75,
|
||||
"Desktop": 20,
|
||||
"Tablet": 5
|
||||
}
|
||||
|
||||
demographics['device'] = device_data
|
||||
|
||||
# Create device distribution chart
|
||||
fig = px.pie(
|
||||
values=list(device_data.values()),
|
||||
names=list(device_data.keys()),
|
||||
title="Device Usage"
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['audience_demographics'] = demographics
|
||||
|
||||
# Peak Engagement Times
|
||||
st.markdown("##### Peak Engagement Times")
|
||||
|
||||
peak_times = [
|
||||
{"day": "Monday", "time": "9:00 AM", "engagement": 85},
|
||||
{"day": "Tuesday", "time": "2:00 PM", "engagement": 90},
|
||||
{"day": "Wednesday", "time": "11:00 AM", "engagement": 95},
|
||||
{"day": "Thursday", "time": "3:00 PM", "engagement": 88},
|
||||
{"day": "Friday", "time": "5:00 PM", "engagement": 92},
|
||||
{"day": "Saturday", "time": "10:00 AM", "engagement": 78},
|
||||
{"day": "Sunday", "time": "4:00 PM", "engagement": 82}
|
||||
]
|
||||
|
||||
st.session_state.engagement_data['peak_engagement_times'] = peak_times
|
||||
|
||||
# Create peak times chart
|
||||
days = [item["day"] for item in peak_times]
|
||||
times = [item["time"] for item in peak_times]
|
||||
engagement = [item["engagement"] for item in peak_times]
|
||||
|
||||
fig = go.Figure()
|
||||
|
||||
fig.add_trace(go.Scatter(
|
||||
x=days,
|
||||
y=engagement,
|
||||
mode="lines+markers",
|
||||
name="Engagement",
|
||||
line=dict(color="#1877F2", width=3),
|
||||
marker=dict(size=10)
|
||||
))
|
||||
|
||||
fig.update_layout(
|
||||
title="Peak Engagement Times",
|
||||
xaxis_title="Day of Week",
|
||||
yaxis_title="Engagement Score",
|
||||
annotations=[
|
||||
dict(
|
||||
x=days[i],
|
||||
y=engagement[i],
|
||||
text=times[i],
|
||||
showarrow=True,
|
||||
arrowhead=1,
|
||||
ax=0,
|
||||
ay=-40
|
||||
) for i in range(len(days))
|
||||
]
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
def render_improvement_suggestions_tab():
|
||||
"""Render the improvement suggestions tab."""
|
||||
|
||||
st.markdown("#### Improvement Suggestions")
|
||||
|
||||
# Check if we have analysis results
|
||||
if not st.session_state.engagement_data['analysis_results']:
|
||||
st.info("Please analyze your content first in the Content Analysis tab.")
|
||||
return
|
||||
|
||||
# Generate improvement suggestions
|
||||
if st.button("Generate Improvement Suggestions", key="generate_suggestions_button"):
|
||||
with st.spinner("Generating improvement suggestions..."):
|
||||
# Generate suggestions
|
||||
suggestions = generate_improvement_suggestions(
|
||||
st.session_state.engagement_data['content'],
|
||||
st.session_state.engagement_data['content_type'],
|
||||
st.session_state.engagement_data['metrics'],
|
||||
st.session_state.engagement_data['audience_demographics']
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.engagement_data['improvement_suggestions'] = suggestions
|
||||
|
||||
# Display suggestions
|
||||
display_improvement_suggestions(suggestions)
|
||||
|
||||
# Display existing suggestions if available
|
||||
if st.session_state.engagement_data['improvement_suggestions']:
|
||||
display_improvement_suggestions(st.session_state.engagement_data['improvement_suggestions'])
|
||||
|
||||
# A/B Testing
|
||||
st.markdown("##### A/B Testing Suggestions")
|
||||
|
||||
# Generate A/B testing suggestions
|
||||
if st.button("Generate A/B Testing Suggestions", key="generate_ab_testing_button"):
|
||||
with st.spinner("Generating A/B testing suggestions..."):
|
||||
# Generate A/B testing suggestions
|
||||
ab_testing_suggestions = generate_ab_testing_suggestions(
|
||||
st.session_state.engagement_data['content'],
|
||||
st.session_state.engagement_data['content_type']
|
||||
)
|
||||
|
||||
# Display A/B testing suggestions
|
||||
display_ab_testing_suggestions(ab_testing_suggestions)
|
||||
|
||||
def analyze_content(content: str, content_type: str, date_range: Tuple[datetime.date, datetime.date]) -> Dict[str, Any]:
|
||||
"""Analyze content and return analysis results."""
|
||||
|
||||
# Prepare prompt for content analysis
|
||||
prompt = f"""
|
||||
Analyze the following Facebook {content_type} content and provide insights on its performance potential:
|
||||
|
||||
Content: "{content}"
|
||||
|
||||
Date Range: {date_range[0]} to {date_range[1]}
|
||||
|
||||
Please provide a detailed analysis including:
|
||||
1. Content quality assessment
|
||||
2. Engagement potential
|
||||
3. Key strengths
|
||||
4. Areas for improvement
|
||||
5. Suggested optimizations
|
||||
|
||||
Format your response as a JSON object with the following structure:
|
||||
{{
|
||||
"content_quality": {{
|
||||
"score": <score from 1-10>,
|
||||
"feedback": "<detailed feedback>"
|
||||
}},
|
||||
"engagement_potential": {{
|
||||
"score": <score from 1-10>,
|
||||
"feedback": "<detailed feedback>"
|
||||
}},
|
||||
"strengths": ["<strength 1>", "<strength 2>", ...],
|
||||
"improvements": ["<improvement 1>", "<improvement 2>", ...],
|
||||
"optimizations": ["<optimization 1>", "<optimization 2>", ...]
|
||||
}}
|
||||
"""
|
||||
|
||||
try:
|
||||
# Generate analysis using LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
# Parse JSON response
|
||||
analysis_results = json.loads(response)
|
||||
|
||||
return analysis_results
|
||||
except Exception as e:
|
||||
logger.error(f"Error analyzing content: {e}")
|
||||
|
||||
# Return default analysis results
|
||||
return {
|
||||
"content_quality": {
|
||||
"score": 7,
|
||||
"feedback": "Content appears to be well-structured and engaging."
|
||||
},
|
||||
"engagement_potential": {
|
||||
"score": 8,
|
||||
"feedback": "Content has good potential for engagement based on its format and content."
|
||||
},
|
||||
"strengths": [
|
||||
"Clear and concise messaging",
|
||||
"Engaging content structure",
|
||||
"Relevant to target audience"
|
||||
],
|
||||
"improvements": [
|
||||
"Add more visual elements",
|
||||
"Include a stronger call-to-action",
|
||||
"Optimize posting time"
|
||||
],
|
||||
"optimizations": [
|
||||
"Add relevant hashtags",
|
||||
"Include emojis for visual appeal",
|
||||
"Tag relevant accounts"
|
||||
]
|
||||
}
|
||||
|
||||
def display_content_analysis(analysis_results: Dict[str, Any]):
|
||||
"""Display content analysis results."""
|
||||
|
||||
# Content Quality
|
||||
st.markdown("##### Content Quality")
|
||||
|
||||
quality_score = analysis_results["content_quality"]["score"]
|
||||
quality_feedback = analysis_results["content_quality"]["feedback"]
|
||||
|
||||
# Create gauge chart for content quality
|
||||
fig = go.Figure(go.Indicator(
|
||||
mode="gauge+number",
|
||||
value=quality_score,
|
||||
domain={'x': [0, 1], 'y': [0, 1]},
|
||||
title={'text': "Content Quality Score"},
|
||||
gauge={
|
||||
'axis': {'range': [0, 10]},
|
||||
'bar': {'color': "#1877F2"},
|
||||
'steps': [
|
||||
{'range': [0, 3], 'color': "lightgray"},
|
||||
{'range': [3, 7], 'color': "gray"},
|
||||
{'range': [7, 10], 'color': "darkgray"}
|
||||
],
|
||||
'threshold': {
|
||||
'line': {'color': "red", 'width': 4},
|
||||
'thickness': 0.75,
|
||||
'value': 7
|
||||
}
|
||||
}
|
||||
))
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
st.markdown(f"**Feedback:** {quality_feedback}")
|
||||
|
||||
# Engagement Potential
|
||||
st.markdown("##### Engagement Potential")
|
||||
|
||||
engagement_score = analysis_results["engagement_potential"]["score"]
|
||||
engagement_feedback = analysis_results["engagement_potential"]["feedback"]
|
||||
|
||||
# Create gauge chart for engagement potential
|
||||
fig = go.Figure(go.Indicator(
|
||||
mode="gauge+number",
|
||||
value=engagement_score,
|
||||
domain={'x': [0, 1], 'y': [0, 1]},
|
||||
title={'text': "Engagement Potential Score"},
|
||||
gauge={
|
||||
'axis': {'range': [0, 10]},
|
||||
'bar': {'color': "#34A853"},
|
||||
'steps': [
|
||||
{'range': [0, 3], 'color': "lightgray"},
|
||||
{'range': [3, 7], 'color': "gray"},
|
||||
{'range': [7, 10], 'color': "darkgray"}
|
||||
],
|
||||
'threshold': {
|
||||
'line': {'color': "red", 'width': 4},
|
||||
'thickness': 0.75,
|
||||
'value': 7
|
||||
}
|
||||
}
|
||||
))
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
st.markdown(f"**Feedback:** {engagement_feedback}")
|
||||
|
||||
# Strengths
|
||||
st.markdown("##### Key Strengths")
|
||||
|
||||
for strength in analysis_results["strengths"]:
|
||||
st.markdown(f"- {strength}")
|
||||
|
||||
# Areas for Improvement
|
||||
st.markdown("##### Areas for Improvement")
|
||||
|
||||
for improvement in analysis_results["improvements"]:
|
||||
st.markdown(f"- {improvement}")
|
||||
|
||||
# Suggested Optimizations
|
||||
st.markdown("##### Suggested Optimizations")
|
||||
|
||||
for optimization in analysis_results["optimizations"]:
|
||||
st.markdown(f"- {optimization}")
|
||||
|
||||
def visualize_performance_metrics(metrics: Dict[str, Any]):
|
||||
"""Visualize performance metrics."""
|
||||
|
||||
# Create metrics chart
|
||||
metric_names = ["Likes", "Comments", "Shares", "Reach", "Impressions", "Clicks"]
|
||||
metric_values = [
|
||||
metrics["likes"],
|
||||
metrics["comments"],
|
||||
metrics["shares"],
|
||||
metrics["reach"],
|
||||
metrics["impressions"],
|
||||
metrics["clicks"]
|
||||
]
|
||||
|
||||
fig = go.Figure(data=[
|
||||
go.Bar(
|
||||
x=metric_names,
|
||||
y=metric_values,
|
||||
marker_color=["#1877F2", "#34A853", "#EA4335", "#FBBC05", "#4285F4", "#46BDC6"]
|
||||
)
|
||||
])
|
||||
|
||||
fig.update_layout(
|
||||
title="Performance Metrics",
|
||||
xaxis_title="Metric",
|
||||
yaxis_title="Count"
|
||||
)
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# Engagement Rate Gauge
|
||||
fig = go.Figure(go.Indicator(
|
||||
mode="gauge+number",
|
||||
value=metrics["engagement_rate"],
|
||||
domain={'x': [0, 1], 'y': [0, 1]},
|
||||
title={'text': "Engagement Rate"},
|
||||
gauge={
|
||||
'axis': {'range': [0, 10]},
|
||||
'bar': {'color': "#1877F2"},
|
||||
'steps': [
|
||||
{'range': [0, 1], 'color': "lightgray"},
|
||||
{'range': [1, 3], 'color': "gray"},
|
||||
{'range': [3, 10], 'color': "darkgray"}
|
||||
],
|
||||
'threshold': {
|
||||
'line': {'color': "red", 'width': 4},
|
||||
'thickness': 0.75,
|
||||
'value': 3
|
||||
}
|
||||
}
|
||||
))
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
def generate_improvement_suggestions(
|
||||
content: str,
|
||||
content_type: str,
|
||||
metrics: Dict[str, Any],
|
||||
demographics: Dict[str, Dict[str, Any]]
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Generate improvement suggestions based on content analysis and metrics."""
|
||||
|
||||
# Prepare prompt for improvement suggestions
|
||||
prompt = f"""
|
||||
Based on the following Facebook {content_type} content and performance metrics, provide specific improvement suggestions:
|
||||
|
||||
Content: "{content}"
|
||||
|
||||
Metrics:
|
||||
- Likes: {metrics['likes']}
|
||||
- Comments: {metrics['comments']}
|
||||
- Shares: {metrics['shares']}
|
||||
- Reach: {metrics['reach']}
|
||||
- Impressions: {metrics['impressions']}
|
||||
- Clicks: {metrics['clicks']}
|
||||
- Engagement Rate: {metrics['engagement_rate']}%
|
||||
|
||||
Audience Demographics:
|
||||
- Age Groups: {demographics['age_groups']}
|
||||
- Gender: {demographics['gender']}
|
||||
- Top Locations: {demographics['location']}
|
||||
- Device Usage: {demographics['device']}
|
||||
|
||||
Please provide 5 specific, actionable improvement suggestions that would help increase engagement.
|
||||
Format your response as a JSON array of objects with the following structure:
|
||||
[
|
||||
{{
|
||||
"category": "<category>",
|
||||
"suggestion": "<detailed suggestion>",
|
||||
"expected_impact": "<expected impact on engagement>",
|
||||
"implementation": "<how to implement this suggestion>"
|
||||
}},
|
||||
...
|
||||
]
|
||||
"""
|
||||
|
||||
try:
|
||||
# Generate suggestions using LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
# Parse JSON response
|
||||
suggestions = json.loads(response)
|
||||
|
||||
return suggestions
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating improvement suggestions: {e}")
|
||||
|
||||
# Return default suggestions
|
||||
return [
|
||||
{
|
||||
"category": "Content Structure",
|
||||
"suggestion": "Add a more compelling headline to grab attention in the first 3 seconds.",
|
||||
"expected_impact": "Increase initial engagement by 25%",
|
||||
"implementation": "Place the headline at the beginning of your post and make it bold or use emojis to stand out."
|
||||
},
|
||||
{
|
||||
"category": "Visual Elements",
|
||||
"suggestion": "Include high-quality images or videos that complement your message.",
|
||||
"expected_impact": "Increase engagement by 40%",
|
||||
"implementation": "Add relevant images or short videos that illustrate your main points."
|
||||
},
|
||||
{
|
||||
"category": "Call-to-Action",
|
||||
"suggestion": "Add a stronger, more specific call-to-action.",
|
||||
"expected_impact": "Increase click-through rate by 30%",
|
||||
"implementation": "End your post with a clear, action-oriented question or instruction."
|
||||
},
|
||||
{
|
||||
"category": "Posting Time",
|
||||
"suggestion": "Optimize your posting time based on audience activity.",
|
||||
"expected_impact": "Increase reach by 20%",
|
||||
"implementation": "Post during peak engagement times (Wednesdays at 11 AM) when your audience is most active."
|
||||
},
|
||||
{
|
||||
"category": "Hashtag Strategy",
|
||||
"suggestion": "Use a mix of popular and niche hashtags relevant to your content.",
|
||||
"expected_impact": "Increase discoverability by 35%",
|
||||
"implementation": "Research trending hashtags in your industry and include 3-5 relevant hashtags in your post."
|
||||
}
|
||||
]
|
||||
|
||||
def display_improvement_suggestions(suggestions: List[Dict[str, Any]]):
|
||||
"""Display improvement suggestions."""
|
||||
|
||||
for i, suggestion in enumerate(suggestions):
|
||||
with st.expander(f"{i+1}. {suggestion['category']}", expanded=True):
|
||||
st.markdown(f"**Suggestion:** {suggestion['suggestion']}")
|
||||
st.markdown(f"**Expected Impact:** {suggestion['expected_impact']}")
|
||||
st.markdown(f"**Implementation:** {suggestion['implementation']}")
|
||||
|
||||
def generate_ab_testing_suggestions(content: str, content_type: str) -> List[Dict[str, Any]]:
|
||||
"""Generate A/B testing suggestions."""
|
||||
|
||||
# Prepare prompt for A/B testing suggestions
|
||||
prompt = f"""
|
||||
Based on the following Facebook {content_type} content, provide specific A/B testing suggestions:
|
||||
|
||||
Content: "{content}"
|
||||
|
||||
Please provide 3 specific A/B testing ideas that would help optimize engagement.
|
||||
Format your response as a JSON array of objects with the following structure:
|
||||
[
|
||||
{{
|
||||
"element": "<element to test>",
|
||||
"variant_a": "<description of variant A>",
|
||||
"variant_b": "<description of variant B>",
|
||||
"metric": "<primary metric to measure>",
|
||||
"hypothesis": "<hypothesis about which variant will perform better>"
|
||||
}},
|
||||
...
|
||||
]
|
||||
"""
|
||||
|
||||
try:
|
||||
# Generate A/B testing suggestions using LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
# Parse JSON response
|
||||
ab_testing_suggestions = json.loads(response)
|
||||
|
||||
return ab_testing_suggestions
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating A/B testing suggestions: {e}")
|
||||
|
||||
# Return default A/B testing suggestions
|
||||
return [
|
||||
{
|
||||
"element": "Headline",
|
||||
"variant_a": "Keep the current headline",
|
||||
"variant_b": "Use a more emotional or provocative headline",
|
||||
"metric": "Click-through rate",
|
||||
"hypothesis": "The emotional headline will increase click-through rate by 15%"
|
||||
},
|
||||
{
|
||||
"element": "Call-to-Action",
|
||||
"variant_a": "Use a question as the call-to-action",
|
||||
"variant_b": "Use a command as the call-to-action",
|
||||
"metric": "Engagement rate",
|
||||
"hypothesis": "The question format will increase engagement rate by 10%"
|
||||
},
|
||||
{
|
||||
"element": "Visual Style",
|
||||
"variant_a": "Use a single image",
|
||||
"variant_b": "Use a carousel of images",
|
||||
"metric": "Time spent viewing",
|
||||
"hypothesis": "The carousel will increase time spent viewing by 25%"
|
||||
}
|
||||
]
|
||||
|
||||
def display_ab_testing_suggestions(ab_testing_suggestions: List[Dict[str, Any]]):
|
||||
"""Display A/B testing suggestions."""
|
||||
|
||||
for i, suggestion in enumerate(ab_testing_suggestions):
|
||||
with st.expander(f"{i+1}. {suggestion['element']}", expanded=True):
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("**Variant A**")
|
||||
st.markdown(suggestion['variant_a'])
|
||||
|
||||
with col2:
|
||||
st.markdown("**Variant B**")
|
||||
st.markdown(suggestion['variant_b'])
|
||||
|
||||
st.markdown(f"**Primary Metric:** {suggestion['metric']}")
|
||||
st.markdown(f"**Hypothesis:** {suggestion['hypothesis']}")
|
||||
|
||||
# Add a button to create A/B test
|
||||
if st.button(f"Create A/B Test for {suggestion['element']}", key=f"ab_test_button_{i}"):
|
||||
st.success(f"A/B test for {suggestion['element']} created successfully!")
|
||||
@@ -0,0 +1,162 @@
|
||||
# Facebook Event Generator 📅
|
||||
|
||||
## Overview
|
||||
|
||||
The Facebook Event Generator is a powerful AI-powered tool designed to help content creators, event organizers, and businesses create engaging Facebook event descriptions. This tool leverages advanced AI to generate compelling event content, optimize engagement, and drive attendance.
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Event Details Management
|
||||
- **Event Type Selection**: Choose between Physical, Online, or Hybrid events
|
||||
- **Basic Information**: Name, category, date, time, and timezone
|
||||
- **Location Details**: Venue information for physical events
|
||||
- **Online Event Setup**: Platform selection and meeting details
|
||||
- **Custom Description Types**: Basic, Detailed, or Professional
|
||||
|
||||
### 2. Content Customization
|
||||
- **Content Style Options**: Professional, Casual, Formal, Engaging, Educational
|
||||
- **Content Elements**:
|
||||
- Agenda
|
||||
- Speakers
|
||||
- Benefits
|
||||
- Requirements
|
||||
- FAQ
|
||||
- Testimonials
|
||||
- Sponsors
|
||||
- Event Highlights
|
||||
|
||||
### 3. Media Options
|
||||
- **Cover Image Generation**: AI-powered image creation
|
||||
- **Style Selection**: Modern, Professional, Creative, Minimalist, Bold
|
||||
- **Brand Color Integration**: Custom color scheme support
|
||||
- **Image Quality Control**: Low, Medium, High options
|
||||
- **Aspect Ratio Options**: 16:9, 1:1, 4:3
|
||||
|
||||
### 4. Engagement Features
|
||||
- **Interactive Elements**:
|
||||
- Polls
|
||||
- Quizzes
|
||||
- Countdown timers
|
||||
- RSVP management
|
||||
- Reminders
|
||||
- Feedback forms
|
||||
- **Social Sharing**:
|
||||
- Hashtag suggestions
|
||||
- Social media links
|
||||
- Share buttons
|
||||
- Friend invitation options
|
||||
- **Custom Engagement Prompts**: AI-generated prompts to boost interaction
|
||||
|
||||
### 5. Preview & Export
|
||||
- **Live Preview**: See your event description as it will appear
|
||||
- **Export Options**:
|
||||
- Copy to clipboard
|
||||
- Download as text file
|
||||
- **Format Validation**: Ensure all required fields are completed
|
||||
|
||||
## How to Use
|
||||
|
||||
### Step 1: Access the Event Generator
|
||||
1. Navigate to the Facebook AI Writer dashboard
|
||||
2. Select the "Event Description Generator" card
|
||||
3. Click "Use Event Description Generator"
|
||||
|
||||
### Step 2: Enter Event Details
|
||||
1. Select event type (Physical/Online/Hybrid)
|
||||
2. Fill in basic information:
|
||||
- Event name
|
||||
- Category
|
||||
- Date and time
|
||||
- Timezone
|
||||
3. Add location details (for physical/hybrid events)
|
||||
4. Add online platform details (for online/hybrid events)
|
||||
|
||||
### Step 3: Customize Content
|
||||
1. Choose content style
|
||||
2. Select content elements to include
|
||||
3. Add key points and event goal
|
||||
4. Define target audience
|
||||
|
||||
### Step 4: Add Media
|
||||
1. Select cover image style
|
||||
2. Choose brand colors
|
||||
3. Set image quality and ratio
|
||||
4. Generate preview images
|
||||
|
||||
### Step 5: Configure Engagement
|
||||
1. Enable interactive elements
|
||||
2. Set up social sharing options
|
||||
3. Add custom engagement prompts
|
||||
4. Configure RSVP and reminder settings
|
||||
|
||||
### Step 6: Preview and Export
|
||||
1. Review generated content
|
||||
2. Make adjustments if needed
|
||||
3. Export in your preferred format
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Creation
|
||||
- Keep event names clear and engaging
|
||||
- Use specific dates and times
|
||||
- Include all essential event details
|
||||
- Add clear call-to-action
|
||||
- Use relevant hashtags
|
||||
|
||||
### Engagement
|
||||
- Enable RSVP functionality
|
||||
- Add interactive elements
|
||||
- Include social sharing options
|
||||
- Use engagement prompts
|
||||
- Set up reminders
|
||||
|
||||
### Media
|
||||
- Use high-quality images
|
||||
- Maintain brand consistency
|
||||
- Optimize for mobile viewing
|
||||
- Include visual hierarchy
|
||||
- Use appropriate aspect ratios
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- Modern web browser
|
||||
- Internet connection
|
||||
- API keys for AI providers
|
||||
- Sufficient storage for media files
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
- **Content not generating**: Check required fields
|
||||
- **Images not appearing**: Verify API keys
|
||||
- **Export failures**: Check file permissions
|
||||
- **Validation errors**: Review input fields
|
||||
|
||||
### Getting Help
|
||||
For additional support:
|
||||
1. Check the documentation
|
||||
2. Contact support team
|
||||
3. Visit our help center
|
||||
4. Join our community forum
|
||||
|
||||
## Future Updates
|
||||
|
||||
### Planned Features
|
||||
- Advanced analytics
|
||||
- A/B testing
|
||||
- Multi-language support
|
||||
- Template library
|
||||
- Integration with calendar apps
|
||||
- Automated scheduling
|
||||
- Performance tracking
|
||||
- Custom branding options
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome feedback and contributions to improve the Event Generator. Please follow our contribution guidelines and submit pull requests to our repository.
|
||||
|
||||
## License
|
||||
|
||||
This tool is part of the ALwrity AI Writer suite and is subject to the same licensing terms.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Facebook Event Generator Module
|
||||
|
||||
This module provides functionality to generate engaging Facebook event descriptions.
|
||||
"""
|
||||
|
||||
from .event_generator import write_fb_event
|
||||
|
||||
__all__ = ['write_fb_event']
|
||||
@@ -0,0 +1,776 @@
|
||||
"""
|
||||
Facebook Event Generator Module
|
||||
|
||||
This module provides functionality to generate engaging Facebook event descriptions with various features
|
||||
and customization options.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
from datetime import datetime, date, time
|
||||
import json
|
||||
import os
|
||||
from typing import Dict, Any, List, Optional, Union, Tuple
|
||||
from loguru import logger
|
||||
import sys
|
||||
import base64
|
||||
from io import BytesIO
|
||||
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
from .....gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
|
||||
|
||||
# Configure logging
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
def initialize_session_state():
|
||||
"""Initialize session state with default values."""
|
||||
if 'event_data' not in st.session_state:
|
||||
st.session_state.event_data = {
|
||||
'basic_info': {},
|
||||
'content': {},
|
||||
'media': {},
|
||||
'engagement': {},
|
||||
'analytics': {}
|
||||
}
|
||||
|
||||
# Initialize individual fields with default values that match selectbox options
|
||||
defaults = {
|
||||
'event_type': "Physical Event",
|
||||
'event_category': "Business",
|
||||
'timezone': "UTC",
|
||||
'platform': "Zoom",
|
||||
'description_type': "Basic",
|
||||
'content_style': "Professional",
|
||||
'cover_image_style': "Modern",
|
||||
'color_scheme': "#1877F2",
|
||||
'image_ratio': "16:9",
|
||||
'image_quality': "High",
|
||||
'event_name': "",
|
||||
'event_date': date.today(),
|
||||
'event_time': time(12, 0), # Default to noon
|
||||
'venue_name': "",
|
||||
'street_address': "",
|
||||
'city': "",
|
||||
'country': "",
|
||||
'meeting_link': "",
|
||||
'meeting_id': "",
|
||||
'passcode': "",
|
||||
'key_points': "",
|
||||
'target_audience': "",
|
||||
'event_goal': "",
|
||||
'engagement_prompts': ""
|
||||
}
|
||||
|
||||
for field, default_value in defaults.items():
|
||||
if field not in st.session_state:
|
||||
st.session_state[field] = default_value
|
||||
|
||||
def write_fb_event():
|
||||
"""Generate an engaging Facebook event description with various features and customization options."""
|
||||
|
||||
# Initialize session state
|
||||
initialize_session_state()
|
||||
|
||||
st.markdown("""
|
||||
### 📅 Facebook Event Generator
|
||||
Create compelling event descriptions that drive attendance and engagement. Customize your event
|
||||
with various features and get AI-powered suggestions for optimal performance.
|
||||
""")
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4, tab5 = st.tabs(["Event Details", "Content & Media", "Engagement", "Analytics", "Preview & Export"])
|
||||
|
||||
with tab1:
|
||||
render_event_details_tab()
|
||||
|
||||
with tab2:
|
||||
render_content_media_tab()
|
||||
|
||||
with tab3:
|
||||
render_engagement_tab()
|
||||
|
||||
with tab4:
|
||||
render_analytics_tab()
|
||||
|
||||
with tab5:
|
||||
render_preview_export_tab()
|
||||
|
||||
def render_event_details_tab():
|
||||
"""Render the event details tab with input fields."""
|
||||
|
||||
# Basic Event Information
|
||||
st.markdown("#### Basic Event Information")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
event_types = ["Physical Event", "Online Event", "Hybrid Event"]
|
||||
event_type = st.selectbox(
|
||||
"Event Type",
|
||||
options=event_types,
|
||||
index=event_types.index(st.session_state.event_type) if st.session_state.event_type in event_types else 0,
|
||||
help="Select the type of event you're creating",
|
||||
key="event_type"
|
||||
)
|
||||
|
||||
event_name = st.text_input(
|
||||
"Event Name",
|
||||
value=st.session_state.event_name,
|
||||
help="Enter a catchy and descriptive name for your event",
|
||||
key="event_name"
|
||||
)
|
||||
|
||||
event_categories = ["Business", "Education", "Entertainment", "Sports", "Community", "Other"]
|
||||
event_category = st.selectbox(
|
||||
"Event Category",
|
||||
options=event_categories,
|
||||
index=event_categories.index(st.session_state.event_category) if st.session_state.event_category in event_categories else 0,
|
||||
help="Select the category that best describes your event",
|
||||
key="event_category"
|
||||
)
|
||||
|
||||
with col2:
|
||||
# Handle date input without conflicting with session state
|
||||
if "event_date" not in st.session_state:
|
||||
st.session_state.event_date = date.today()
|
||||
|
||||
event_date = st.date_input(
|
||||
"Event Date",
|
||||
min_value=date.today(),
|
||||
help="Select the date of your event",
|
||||
key="event_date"
|
||||
)
|
||||
|
||||
# Handle time input without conflicting with session state
|
||||
if "event_time" not in st.session_state:
|
||||
st.session_state.event_time = time(12, 0)
|
||||
|
||||
event_time = st.time_input(
|
||||
"Event Time",
|
||||
help="Select the time of your event",
|
||||
key="event_time"
|
||||
)
|
||||
|
||||
timezones = ["UTC", "EST", "PST", "GMT", "IST"]
|
||||
timezone = st.selectbox(
|
||||
"Timezone",
|
||||
options=timezones,
|
||||
index=timezones.index(st.session_state.timezone) if st.session_state.timezone in timezones else 0,
|
||||
help="Select the timezone for your event",
|
||||
key="timezone"
|
||||
)
|
||||
|
||||
# Location Details
|
||||
st.markdown("#### Location Details")
|
||||
|
||||
if event_type in ["Physical Event", "Hybrid Event"]:
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
venue_name = st.text_input(
|
||||
"Venue Name",
|
||||
value=st.session_state.venue_name,
|
||||
help="Enter the name of the venue",
|
||||
key="venue_name"
|
||||
)
|
||||
|
||||
street_address = st.text_input(
|
||||
"Street Address",
|
||||
value=st.session_state.street_address,
|
||||
help="Enter the street address",
|
||||
key="street_address"
|
||||
)
|
||||
|
||||
with col2:
|
||||
city = st.text_input(
|
||||
"City",
|
||||
value=st.session_state.city,
|
||||
help="Enter the city",
|
||||
key="city"
|
||||
)
|
||||
|
||||
country = st.text_input(
|
||||
"Country",
|
||||
value=st.session_state.country,
|
||||
help="Enter the country",
|
||||
key="country"
|
||||
)
|
||||
|
||||
if event_type in ["Online Event", "Hybrid Event"]:
|
||||
st.markdown("#### Online Event Details")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
platforms = ["Zoom", "Google Meet", "Microsoft Teams", "Facebook Live", "Other"]
|
||||
platform = st.selectbox(
|
||||
"Platform",
|
||||
options=platforms,
|
||||
index=platforms.index(st.session_state.platform) if st.session_state.platform in platforms else 0,
|
||||
help="Select the platform for your online event",
|
||||
key="platform"
|
||||
)
|
||||
|
||||
meeting_link = st.text_input(
|
||||
"Meeting Link",
|
||||
value=st.session_state.meeting_link,
|
||||
help="Enter the meeting link (optional)",
|
||||
key="meeting_link"
|
||||
)
|
||||
|
||||
with col2:
|
||||
meeting_id = st.text_input(
|
||||
"Meeting ID",
|
||||
value=st.session_state.meeting_id,
|
||||
help="Enter the meeting ID (optional)",
|
||||
key="meeting_id"
|
||||
)
|
||||
|
||||
passcode = st.text_input(
|
||||
"Passcode",
|
||||
value=st.session_state.passcode,
|
||||
help="Enter the passcode (optional)",
|
||||
key="passcode"
|
||||
)
|
||||
|
||||
# Event Description
|
||||
st.markdown("#### Event Description")
|
||||
|
||||
description_types = ["Basic", "Detailed", "Professional"]
|
||||
description_type = st.radio(
|
||||
"Description Type",
|
||||
options=description_types,
|
||||
index=description_types.index(st.session_state.description_type) if st.session_state.description_type in description_types else 0,
|
||||
help="Select the level of detail for your event description",
|
||||
key="description_type"
|
||||
)
|
||||
|
||||
key_points = st.text_area(
|
||||
"Key Points to Include",
|
||||
value=st.session_state.key_points,
|
||||
help="Enter key points that should be included in the event description",
|
||||
height=100,
|
||||
key="key_points"
|
||||
)
|
||||
|
||||
target_audience = st.text_input(
|
||||
"Target Audience",
|
||||
value=st.session_state.target_audience,
|
||||
help="Describe your target audience",
|
||||
key="target_audience"
|
||||
)
|
||||
|
||||
event_goal = st.text_area(
|
||||
"Event Goal",
|
||||
value=st.session_state.event_goal,
|
||||
help="What do you want to achieve with this event?",
|
||||
height=100,
|
||||
key="event_goal"
|
||||
)
|
||||
|
||||
def render_content_media_tab():
|
||||
"""Render the content and media tab with customization options."""
|
||||
|
||||
st.markdown("#### Content Customization")
|
||||
|
||||
# Template Selection
|
||||
st.markdown("##### Template Selection")
|
||||
|
||||
template_type = st.selectbox(
|
||||
"Template Type",
|
||||
["Custom", "Conference", "Workshop", "Webinar", "Networking", "Product Launch", "Fundraiser"],
|
||||
help="Select a template type for your event"
|
||||
)
|
||||
|
||||
# Content Style - Move this after template selection
|
||||
content_styles = ["Professional", "Casual", "Formal", "Engaging", "Educational"]
|
||||
default_style = "Professional"
|
||||
|
||||
# Set default style based on template
|
||||
if template_type != "Custom":
|
||||
if template_type == "Conference":
|
||||
default_style = "Professional"
|
||||
elif template_type == "Workshop":
|
||||
default_style = "Educational"
|
||||
elif template_type == "Webinar":
|
||||
default_style = "Professional"
|
||||
elif template_type == "Networking":
|
||||
default_style = "Casual"
|
||||
elif template_type == "Product Launch":
|
||||
default_style = "Engaging"
|
||||
elif template_type == "Fundraiser":
|
||||
default_style = "Engaging"
|
||||
|
||||
content_style = st.selectbox(
|
||||
"Content Style",
|
||||
content_styles,
|
||||
index=content_styles.index(default_style),
|
||||
help="Select the style of your event description",
|
||||
key="content_style"
|
||||
)
|
||||
|
||||
# Content Elements
|
||||
st.markdown("##### Content Elements")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
include_agenda = st.checkbox("Include Agenda", value=True)
|
||||
include_speakers = st.checkbox("Include Speakers", value=True)
|
||||
include_benefits = st.checkbox("Include Benefits", value=True)
|
||||
include_requirements = st.checkbox("Include Requirements", value=True)
|
||||
|
||||
with col2:
|
||||
include_faq = st.checkbox("Include FAQ", value=True)
|
||||
include_testimonials = st.checkbox("Include Testimonials", value=True)
|
||||
include_sponsors = st.checkbox("Include Sponsors", value=True)
|
||||
include_highlights = st.checkbox("Include Event Highlights", value=True)
|
||||
|
||||
# Media Options
|
||||
st.markdown("#### Media Options")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
cover_image_style = st.selectbox(
|
||||
"Cover Image Style",
|
||||
["Modern", "Professional", "Creative", "Minimalist", "Bold"],
|
||||
help="Select the style for your event cover image",
|
||||
key="cover_image_style"
|
||||
)
|
||||
|
||||
color_scheme = st.color_picker(
|
||||
"Brand Color",
|
||||
"#1877F2",
|
||||
help="Select your brand color for the event",
|
||||
key="color_scheme"
|
||||
)
|
||||
|
||||
with col2:
|
||||
image_ratio = st.selectbox(
|
||||
"Image Ratio",
|
||||
["16:9", "1:1", "4:3"],
|
||||
help="Select the aspect ratio for your images",
|
||||
key="image_ratio"
|
||||
)
|
||||
|
||||
image_quality = st.select_slider(
|
||||
"Image Quality",
|
||||
options=["Low", "Medium", "High"],
|
||||
value="High",
|
||||
help="Select the quality for generated images",
|
||||
key="image_quality"
|
||||
)
|
||||
|
||||
def render_engagement_tab():
|
||||
"""Render the engagement tab with interactive elements."""
|
||||
|
||||
st.markdown("#### Engagement Features")
|
||||
|
||||
# Interactive Elements
|
||||
st.markdown("##### Interactive Elements")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
# Enhanced Poll Options
|
||||
use_poll = st.checkbox("Add Poll", value=False)
|
||||
if use_poll:
|
||||
poll_type = st.selectbox(
|
||||
"Poll Type",
|
||||
["Multiple Choice", "Rating", "Open-ended", "Ranking"]
|
||||
)
|
||||
poll_questions = st.text_area(
|
||||
"Poll Questions",
|
||||
help="Enter poll questions (one per line)",
|
||||
height=100
|
||||
)
|
||||
poll_duration = st.number_input(
|
||||
"Poll Duration (days)",
|
||||
min_value=1,
|
||||
max_value=30,
|
||||
value=7
|
||||
)
|
||||
|
||||
# Enhanced Quiz Options
|
||||
use_quiz = st.checkbox("Add Quiz", value=False)
|
||||
if use_quiz:
|
||||
quiz_type = st.selectbox(
|
||||
"Quiz Type",
|
||||
["Trivia", "Personality", "Knowledge Check"]
|
||||
)
|
||||
quiz_questions = st.text_area(
|
||||
"Quiz Questions",
|
||||
help="Enter quiz questions (one per line)",
|
||||
height=100
|
||||
)
|
||||
quiz_rewards = st.text_input(
|
||||
"Quiz Rewards",
|
||||
help="Enter rewards for quiz completion"
|
||||
)
|
||||
|
||||
use_countdown = st.checkbox("Add Countdown", value=False)
|
||||
|
||||
with col2:
|
||||
# Enhanced RSVP Options
|
||||
use_rsvp = st.checkbox("Enable RSVP", value=True)
|
||||
if use_rsvp:
|
||||
rsvp_options = st.multiselect(
|
||||
"RSVP Options",
|
||||
["Attending", "Maybe", "Not Attending", "Bring a Guest"]
|
||||
)
|
||||
rsvp_limit = st.number_input(
|
||||
"RSVP Limit",
|
||||
min_value=0,
|
||||
value=0,
|
||||
help="0 for unlimited"
|
||||
)
|
||||
rsvp_deadline = st.date_input(
|
||||
"RSVP Deadline",
|
||||
min_value=date.today()
|
||||
)
|
||||
|
||||
use_reminder = st.checkbox("Enable Reminders", value=True)
|
||||
if use_reminder:
|
||||
reminder_times = st.multiselect(
|
||||
"Reminder Times",
|
||||
["1 day before", "1 hour before", "15 minutes before", "Custom"]
|
||||
)
|
||||
if "Custom" in reminder_times:
|
||||
custom_reminder = st.text_input(
|
||||
"Custom Reminder Time",
|
||||
help="Format: X days/hours/minutes before"
|
||||
)
|
||||
|
||||
use_feedback = st.checkbox("Enable Feedback Form", value=True)
|
||||
|
||||
# Social Sharing
|
||||
st.markdown("##### Social Sharing")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
include_hashtags = st.checkbox("Include Hashtags", value=True)
|
||||
if include_hashtags:
|
||||
hashtag_count = st.slider(
|
||||
"Number of Hashtags",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=5
|
||||
)
|
||||
custom_hashtags = st.text_input(
|
||||
"Custom Hashtags",
|
||||
help="Enter custom hashtags (comma separated)"
|
||||
)
|
||||
|
||||
include_social_links = st.checkbox("Include Social Links", value=True)
|
||||
|
||||
with col2:
|
||||
include_share_buttons = st.checkbox("Include Share Buttons", value=True)
|
||||
include_invite_friends = st.checkbox("Include Invite Friends", value=True)
|
||||
|
||||
# Engagement Prompts
|
||||
st.markdown("##### Engagement Prompts")
|
||||
|
||||
engagement_prompts = st.text_area(
|
||||
"Custom Engagement Prompts",
|
||||
help="Enter custom prompts to encourage engagement",
|
||||
height=100,
|
||||
key="engagement_prompts"
|
||||
)
|
||||
|
||||
# Language Options
|
||||
st.markdown("##### Language Options")
|
||||
|
||||
language = st.selectbox(
|
||||
"Event Language",
|
||||
["English", "Spanish", "French", "German", "Italian", "Portuguese", "Chinese", "Japanese", "Korean", "Other"]
|
||||
)
|
||||
|
||||
if language != "English":
|
||||
st.info(f"Event description will be generated in {language}. You can still input details in English.")
|
||||
|
||||
def render_analytics_tab():
|
||||
"""Render the analytics tab with insights and predictions."""
|
||||
|
||||
st.markdown("#### Analytics & Insights")
|
||||
|
||||
# Engagement Prediction
|
||||
st.markdown("##### Engagement Prediction")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("**Predicted Engagement Metrics**")
|
||||
|
||||
# Generate mock predictions based on input
|
||||
if st.session_state.event_name and st.session_state.target_audience:
|
||||
predicted_rsvp = min(100, max(10, len(st.session_state.event_name) * 5))
|
||||
predicted_views = predicted_rsvp * 10
|
||||
predicted_engagement = min(100, max(20, predicted_rsvp * 0.8))
|
||||
|
||||
st.metric("Predicted RSVPs", f"{predicted_rsvp}")
|
||||
st.metric("Predicted Views", f"{predicted_views}")
|
||||
st.metric("Predicted Engagement Rate", f"{predicted_engagement}%")
|
||||
else:
|
||||
st.info("Fill in event details to see engagement predictions")
|
||||
|
||||
with col2:
|
||||
st.markdown("**Engagement Factors**")
|
||||
|
||||
factors = {
|
||||
"Event Name": 85,
|
||||
"Description Quality": 90,
|
||||
"Visual Appeal": 75,
|
||||
"Timing": 80,
|
||||
"Target Audience Match": 95
|
||||
}
|
||||
|
||||
for factor, score in factors.items():
|
||||
st.progress(score / 100)
|
||||
st.text(f"{factor}: {score}%")
|
||||
|
||||
# Best Practices
|
||||
st.markdown("##### Best Practices")
|
||||
|
||||
best_practices = [
|
||||
"Use clear, action-oriented language in your event title",
|
||||
"Include all essential details in the first 3 sentences",
|
||||
"Add visual elements to increase engagement",
|
||||
"Use hashtags strategically (3-5 is optimal)",
|
||||
"Include a clear call-to-action",
|
||||
"Optimize for mobile viewing",
|
||||
"Post at optimal times (typically 1-3pm on weekdays)"
|
||||
]
|
||||
|
||||
for practice in best_practices:
|
||||
st.markdown(f"✅ {practice}")
|
||||
|
||||
# A/B Testing Suggestions
|
||||
st.markdown("##### A/B Testing Suggestions")
|
||||
|
||||
if st.button("Generate A/B Testing Ideas"):
|
||||
st.markdown("**Title Variations:**")
|
||||
st.markdown(f"1. {st.session_state.event_name}")
|
||||
st.markdown(f"2. {st.session_state.event_name} - Don't Miss Out!")
|
||||
st.markdown(f"3. Join Us: {st.session_state.event_name}")
|
||||
|
||||
st.markdown("**Description Variations:**")
|
||||
st.markdown("1. Focus on benefits and outcomes")
|
||||
st.markdown("2. Focus on problem-solving and solutions")
|
||||
st.markdown("3. Focus on community and networking")
|
||||
|
||||
st.markdown("**Visual Variations:**")
|
||||
st.markdown("1. Use brand colors prominently")
|
||||
st.markdown("2. Use contrasting colors for attention")
|
||||
st.markdown("3. Use minimal design with focus on text")
|
||||
|
||||
def render_preview_export_tab():
|
||||
"""Render the preview and export tab."""
|
||||
|
||||
st.markdown("#### Preview & Export")
|
||||
|
||||
# Preview Options
|
||||
preview_type = st.radio(
|
||||
"Preview Type",
|
||||
["Mobile", "Desktop", "Social Cards", "All"]
|
||||
)
|
||||
|
||||
# Generate Event Button
|
||||
if st.button("🚀 Generate Event Description", key="generate_event"):
|
||||
with st.spinner("Generating your event description..."):
|
||||
# Validate required fields
|
||||
if not validate_event_fields():
|
||||
return
|
||||
|
||||
# Generate event description
|
||||
event_description = generate_event_description()
|
||||
|
||||
# Store in session state
|
||||
st.session_state.event_description = event_description
|
||||
|
||||
# Display preview based on selection
|
||||
if preview_type == "Mobile" or preview_type == "All":
|
||||
st.markdown("##### Mobile Preview")
|
||||
st.markdown("""
|
||||
<div style="border: 1px solid #ddd; border-radius: 10px; padding: 15px; max-width: 375px; margin: 0 auto; background-color: #f9f9f9;">
|
||||
<h3 style="margin-top: 0;">{}</h3>
|
||||
<p style="color: #666;">{} at {}</p>
|
||||
<div style="margin: 15px 0;">
|
||||
{}
|
||||
</div>
|
||||
</div>
|
||||
""".format(
|
||||
st.session_state.event_name,
|
||||
st.session_state.event_date.strftime("%B %d, %Y"),
|
||||
st.session_state.event_time.strftime("%I:%M %p"),
|
||||
event_description
|
||||
), unsafe_allow_html=True)
|
||||
|
||||
if preview_type == "Desktop" or preview_type == "All":
|
||||
st.markdown("##### Desktop Preview")
|
||||
st.markdown("""
|
||||
<div style="border: 1px solid #ddd; border-radius: 10px; padding: 20px; max-width: 600px; margin: 0 auto; background-color: #f9f9f9;">
|
||||
<h2 style="margin-top: 0;">{}</h2>
|
||||
<p style="color: #666;">{} at {}</p>
|
||||
<div style="margin: 20px 0;">
|
||||
{}
|
||||
</div>
|
||||
</div>
|
||||
""".format(
|
||||
st.session_state.event_name,
|
||||
st.session_state.event_date.strftime("%B %d, %Y"),
|
||||
st.session_state.event_time.strftime("%I:%M %p"),
|
||||
event_description
|
||||
), unsafe_allow_html=True)
|
||||
|
||||
if preview_type == "Social Cards" or preview_type == "All":
|
||||
st.markdown("##### Social Cards Preview")
|
||||
st.markdown("""
|
||||
<div style="border: 1px solid #ddd; border-radius: 10px; padding: 15px; max-width: 500px; margin: 0 auto; background-color: #f9f9f9;">
|
||||
<h3 style="margin-top: 0;">{}</h3>
|
||||
<p style="color: #666;">{} at {}</p>
|
||||
<div style="margin: 15px 0;">
|
||||
{}
|
||||
</div>
|
||||
</div>
|
||||
""".format(
|
||||
st.session_state.event_name,
|
||||
st.session_state.event_date.strftime("%B %d, %Y"),
|
||||
st.session_state.event_time.strftime("%I:%M %p"),
|
||||
event_description[:200] + "..." if len(event_description) > 200 else event_description
|
||||
), unsafe_allow_html=True)
|
||||
|
||||
# Export options
|
||||
st.markdown("#### Export Options")
|
||||
|
||||
col1, col2, col3 = st.columns(3)
|
||||
|
||||
with col1:
|
||||
if st.button("📋 Copy to Clipboard"):
|
||||
st.code(event_description)
|
||||
st.success("Event description copied to clipboard!")
|
||||
|
||||
with col2:
|
||||
if st.button("💾 Download as Text"):
|
||||
download_event_description(event_description)
|
||||
|
||||
with col3:
|
||||
if st.button("📅 Export to Calendar"):
|
||||
st.info("Calendar export feature coming soon!")
|
||||
|
||||
def validate_event_fields() -> bool:
|
||||
"""Validate required event fields with enhanced validation."""
|
||||
validation_rules = {
|
||||
"Event Name": {
|
||||
"required": True,
|
||||
"min_length": 5,
|
||||
"max_length": 100,
|
||||
"type": str
|
||||
},
|
||||
"Event Date": {
|
||||
"required": True,
|
||||
"min_date": date.today(),
|
||||
"type": Union[date, type(None)]
|
||||
},
|
||||
"Target Audience": {
|
||||
"required": True,
|
||||
"min_length": 10,
|
||||
"type": str
|
||||
},
|
||||
"Event Goal": {
|
||||
"required": True,
|
||||
"min_length": 20,
|
||||
"type": str
|
||||
}
|
||||
}
|
||||
|
||||
errors = []
|
||||
for field, rules in validation_rules.items():
|
||||
field_key = field.lower().replace(" ", "_")
|
||||
value = st.session_state.get(field_key)
|
||||
|
||||
# Skip validation if field is not required and value is empty
|
||||
if not rules["required"] and (value is None or value == ""):
|
||||
continue
|
||||
|
||||
# Type validation
|
||||
if "type" in rules and value is not None:
|
||||
expected_type = rules["type"]
|
||||
if not isinstance(value, expected_type):
|
||||
errors.append(f"{field} must be of type {expected_type}")
|
||||
continue
|
||||
|
||||
# Required field validation
|
||||
if rules["required"] and (value is None or value == ""):
|
||||
errors.append(f"{field} is required")
|
||||
continue
|
||||
|
||||
# Length validation for strings
|
||||
if isinstance(value, str):
|
||||
if "min_length" in rules and len(value) < rules["min_length"]:
|
||||
errors.append(f"{field} must be at least {rules['min_length']} characters")
|
||||
if "max_length" in rules and len(value) > rules["max_length"]:
|
||||
errors.append(f"{field} must be less than {rules['max_length']} characters")
|
||||
|
||||
# Date validation
|
||||
if isinstance(value, date):
|
||||
if "min_date" in rules and value < rules["min_date"]:
|
||||
errors.append(f"{field} must be in the future")
|
||||
|
||||
if errors:
|
||||
st.error("\n".join(errors))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generate_event_description() -> str:
|
||||
"""Generate the event description using AI with enhanced features."""
|
||||
prompt = f"""
|
||||
Create a compelling Facebook event description for:
|
||||
|
||||
Event Name: {st.session_state.get('event_name', '')}
|
||||
Event Type: {st.session_state.get('event_type', '')}
|
||||
Event Category: {st.session_state.get('event_category', '')}
|
||||
Date & Time: {st.session_state.get('event_date', '')} at {st.session_state.get('event_time', '')}
|
||||
Target Audience: {st.session_state.get('target_audience', '')}
|
||||
Event Goal: {st.session_state.get('event_goal', '')}
|
||||
|
||||
Key Points to Include: {st.session_state.get('key_points', '')}
|
||||
|
||||
Style: {st.session_state.get('content_style', '')}
|
||||
|
||||
Additional Requirements:
|
||||
1. Include SEO-optimized keywords
|
||||
2. Add emoji suggestions for key points
|
||||
3. Include trending hashtags in the event category
|
||||
4. Add engagement hooks at strategic points
|
||||
5. Include social proof elements
|
||||
6. Add urgency triggers
|
||||
7. Include mobile-optimized formatting
|
||||
8. Add accessibility considerations
|
||||
|
||||
Format the description with:
|
||||
- Engaging opening
|
||||
- Clear event details
|
||||
- Key benefits
|
||||
- Call to action
|
||||
- Relevant hashtags
|
||||
"""
|
||||
|
||||
try:
|
||||
response = llm_text_gen(prompt)
|
||||
return response
|
||||
except Exception as err:
|
||||
st.error(f"An error occurred while generating the event description: {err}")
|
||||
return ""
|
||||
|
||||
def download_event_description(content: str):
|
||||
"""Download the event description as a text file."""
|
||||
# Create a download link
|
||||
b64 = base64.b64encode(content.encode()).decode()
|
||||
href = f'<a href="data:file/txt;base64,{b64}" download="event_description.txt">Download Event Description</a>'
|
||||
st.markdown(href, unsafe_allow_html=True)
|
||||
@@ -0,0 +1,164 @@
|
||||
# Facebook Carousel Generator 🔄
|
||||
|
||||
Welcome to the Facebook Carousel Generator! This powerful tool helps you create engaging, professional-looking carousel posts for Facebook with AI-powered content and visuals.
|
||||
|
||||
## What is a Facebook Carousel? 🤔
|
||||
|
||||
A Facebook carousel is a post format that allows you to showcase up to 10 images or videos in a single post, each with its own caption. Users can swipe through the content, making it perfect for:
|
||||
- Showcasing multiple products
|
||||
- Telling a story
|
||||
- Sharing step-by-step tutorials
|
||||
- Highlighting features and benefits
|
||||
- Displaying before-and-after transformations
|
||||
|
||||
## Features ✨
|
||||
|
||||
### 1. Content Setup 📝
|
||||
- **Business Profile**: Customize content for your specific industry
|
||||
- **Target Audience**: Define who you want to reach
|
||||
- **Purpose Selection**: Choose from multiple carousel purposes:
|
||||
- Product Showcase
|
||||
- How-to Guide
|
||||
- Before and After
|
||||
- Features/Benefits
|
||||
- Customer Success Stories
|
||||
- Product Collection
|
||||
- Service Overview
|
||||
- Educational Series
|
||||
- Brand Story
|
||||
|
||||
### 2. Carousel Structure 🏗️
|
||||
Choose from various storytelling formats:
|
||||
- Progressive Story
|
||||
- Feature Showcase
|
||||
- Step-by-Step Guide
|
||||
- Problem-Solution
|
||||
- Collection Display
|
||||
- Before-After Series
|
||||
- FAQ Format
|
||||
- Tips & Tricks
|
||||
|
||||
### 3. Visual Elements 🎨
|
||||
Customize your carousel's look:
|
||||
- Visual styles (Modern, Bold, Minimalist, etc.)
|
||||
- Color schemes
|
||||
- Brand color integration
|
||||
- Image styles
|
||||
- Text overlays
|
||||
- Font selections
|
||||
- Composition options
|
||||
|
||||
### 4. AI-Powered Generation 🤖
|
||||
The tool automatically creates:
|
||||
- Engaging captions
|
||||
- Slide content
|
||||
- Image suggestions
|
||||
- Hashtag recommendations
|
||||
- Engagement prompts
|
||||
|
||||
## How to Use 📱
|
||||
|
||||
### Step 1: Content Setup
|
||||
1. Enter your business type and target audience
|
||||
2. Select your carousel purpose
|
||||
3. Choose your brand voice
|
||||
4. Enter your key message
|
||||
5. Select number of slides (2-10)
|
||||
6. Pick your preferred carousel structure
|
||||
|
||||
### Step 2: Customize Content
|
||||
Select what to include:
|
||||
- Statistics/Facts
|
||||
- Testimonials
|
||||
- Pricing
|
||||
- Call-to-Action
|
||||
- Hashtags
|
||||
- Emojis
|
||||
- Questions
|
||||
- Bullet Points
|
||||
- Numbered Lists
|
||||
|
||||
### Step 3: Visual Design
|
||||
1. Choose your visual style
|
||||
2. Select color scheme
|
||||
3. Pick image style
|
||||
4. Configure text overlays (optional)
|
||||
5. Customize composition
|
||||
|
||||
### Step 4: Preview & Export
|
||||
View your carousel in:
|
||||
- Mobile preview
|
||||
- Desktop preview
|
||||
- Content overview
|
||||
- Download options:
|
||||
- Complete ZIP package
|
||||
- Individual files
|
||||
- With posting guidelines
|
||||
|
||||
## Best Practices 💡
|
||||
|
||||
### Carousel Tips
|
||||
1. **Keep it Consistent**: Maintain visual consistency across all slides
|
||||
2. **Start Strong**: Put your best image first to grab attention
|
||||
3. **Tell a Story**: Make slides flow naturally from one to the next
|
||||
4. **Clear CTAs**: Include clear call-to-actions
|
||||
5. **Mobile-First**: Design with mobile viewing in mind
|
||||
|
||||
### Posting Tips
|
||||
1. **Best Times**: Post between 1-4 PM on weekdays
|
||||
2. **Hashtags**: Use all provided hashtags for maximum reach
|
||||
3. **Engagement**: Respond to comments within the first hour
|
||||
4. **Cross-Promote**: Share to Stories after posting
|
||||
5. **Monitor**: Track performance for the first 24 hours
|
||||
|
||||
## Export Options 💾
|
||||
|
||||
### 1. Complete Package (ZIP)
|
||||
Includes:
|
||||
- All carousel images
|
||||
- Main caption
|
||||
- Individual slide captions
|
||||
- Hashtags file
|
||||
- Engagement prompts
|
||||
- Posting guidelines
|
||||
- Metadata
|
||||
|
||||
### 2. Individual Files
|
||||
Download separately:
|
||||
- Individual images
|
||||
- Caption text
|
||||
- Hashtags list
|
||||
- Engagement prompts
|
||||
|
||||
### 3. Posting Guidelines
|
||||
Receive detailed instructions on:
|
||||
- How to upload your carousel
|
||||
- Best posting practices
|
||||
- Engagement strategies
|
||||
- Performance monitoring tips
|
||||
|
||||
## Need Help? 🆘
|
||||
|
||||
If you encounter any issues or have questions:
|
||||
1. Check the preview before generating final images
|
||||
2. Ensure all required fields are filled
|
||||
3. Try different visual styles if the first attempt isn't perfect
|
||||
4. Experiment with different carousel structures
|
||||
|
||||
## Pro Tips 🌟
|
||||
|
||||
1. **Planning**: Plan your carousel story before starting
|
||||
2. **Branding**: Use your brand colors for consistency
|
||||
3. **Testing**: Preview on both mobile and desktop
|
||||
4. **Engagement**: Use the provided engagement prompts
|
||||
5. **Analytics**: Save successful carousels as templates
|
||||
|
||||
## Technical Requirements 🔧
|
||||
|
||||
- Stable internet connection
|
||||
- Web browser (Chrome, Firefox, Safari, or Edge)
|
||||
- Facebook Business Page (for posting)
|
||||
|
||||
Remember: The better the input, the better the output! Take time to fill in all relevant information for the best results.
|
||||
|
||||
Happy creating! 🎨✨
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,145 @@
|
||||
# Facebook Reel Generator
|
||||
|
||||
## Overview
|
||||
|
||||
The Facebook Reel Generator is a powerful AI-powered tool designed to help content creators, marketers, and businesses create engaging Facebook Reels content. This tool leverages advanced AI to generate creative scripts, visual concepts, and content strategies optimized for Facebook's short-form video platform.
|
||||
|
||||
## Features
|
||||
|
||||
### Current Features
|
||||
|
||||
#### 1. Reel Content Generation
|
||||
- **Script Generation**: Create complete scripts for Facebook Reels with hooks, main content, and calls-to-action
|
||||
- **Content Structure**: Automatically formats content with proper pacing for short-form video
|
||||
- **Brand Voice Customization**: Adapt content to match your brand's tone and style
|
||||
- **Target Audience Optimization**: Tailor content specifically for your target demographic
|
||||
- **Purpose-Driven Content**: Generate content aligned with specific marketing goals (awareness, engagement, conversion, etc.)
|
||||
|
||||
#### 2. Visual Elements
|
||||
- **Image Generation**: Create custom images for your Reels using AI image generation
|
||||
- **Visual Style Options**: Choose from various visual styles (modern, minimalist, bold, etc.)
|
||||
- **Aspect Ratio Optimization**: Generate images in the optimal 9:16 aspect ratio for Reels
|
||||
- **Image Quality Settings**: Control the quality and detail level of generated images
|
||||
|
||||
#### 3. Advanced Options
|
||||
- **Content Length Control**: Specify preferred length for your Reel content
|
||||
- **Language Style Selection**: Choose from formal, casual, humorous, or other language styles
|
||||
- **AI Provider Selection**: Choose between different AI providers for content generation
|
||||
- **Hashtag Suggestions**: Get relevant hashtag recommendations for your Reels
|
||||
|
||||
### Coming Soon Features
|
||||
|
||||
#### 1. Music Integration
|
||||
- **Trending Music Suggestions**: Get recommendations for popular music tracks
|
||||
- **Music Mood Matching**: Find music that matches your content's emotional tone
|
||||
- **Copyright-Safe Options**: Access royalty-free music suggestions
|
||||
|
||||
#### 2. Video Script Generation
|
||||
- **Shot-by-Shot Breakdown**: Get detailed visual direction for each segment
|
||||
- **Transition Suggestions**: Receive creative transition ideas between scenes
|
||||
- **Visual Effects Recommendations**: Get ideas for filters and effects to enhance your Reel
|
||||
|
||||
#### 3. Performance Optimization
|
||||
- **Trend Analysis**: Identify current trends in your niche for Reel content
|
||||
- **Engagement Prediction**: Get insights on potential performance of your content
|
||||
- **A/B Testing Suggestions**: Receive variations of content to test different approaches
|
||||
|
||||
## How to Use
|
||||
|
||||
### Step 1: Access the Reel Generator
|
||||
1. Navigate to the Facebook AI Writer dashboard
|
||||
2. Select the "FB Reel Generator" card
|
||||
3. Click "Use FB Reel Generator"
|
||||
|
||||
### Step 2: Configure Your Reel Content
|
||||
1. Fill in the basic information:
|
||||
- Business type
|
||||
- Target audience
|
||||
- Reel purpose
|
||||
- Brand voice
|
||||
- Key message
|
||||
- Call to action
|
||||
2. Select content preferences:
|
||||
- Include hashtags
|
||||
- Include hooks
|
||||
- Include trending topics
|
||||
3. Click "Generate Reel Content"
|
||||
|
||||
### Step 3: Customize Visual Elements
|
||||
1. Once your content is generated, navigate to the "Visual Elements" tab
|
||||
2. Select your preferred visual style
|
||||
3. Choose the aspect ratio (9:16 recommended for Reels)
|
||||
4. Adjust image quality settings
|
||||
5. Click "Generate Images"
|
||||
|
||||
### Step 4: Fine-tune with Advanced Options
|
||||
1. Navigate to the "Advanced Options" tab
|
||||
2. Adjust content length preferences
|
||||
3. Select language style
|
||||
4. Choose your preferred AI provider
|
||||
5. Click "Apply Advanced Settings"
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Creation
|
||||
- Keep your key message concise and focused
|
||||
- Use action-oriented language in your call to action
|
||||
- Be specific about your target audience to get more relevant content
|
||||
- Experiment with different brand voices to find what resonates with your audience
|
||||
|
||||
### Visual Elements
|
||||
- Use the 9:16 aspect ratio for optimal display on mobile devices
|
||||
- Select visual styles that align with your brand identity
|
||||
- Consider using higher quality settings for more professional-looking images
|
||||
|
||||
### Performance Optimization
|
||||
- Regularly update your content based on performance data
|
||||
- Test different hooks and openings to see what captures attention
|
||||
- Use the suggested hashtags to increase discoverability
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- A modern web browser (Chrome, Firefox, Safari, or Edge)
|
||||
- Internet connection
|
||||
- API keys for AI providers (OpenAI, Google Gemini, etc.)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
- **Content not generating**: Ensure all required fields are filled out
|
||||
- **Images not appearing**: Check your internet connection and API key status
|
||||
- **Error messages**: Verify that your API keys are valid and have sufficient credits
|
||||
|
||||
### Getting Help
|
||||
If you encounter any issues not covered in this guide, please contact support or check our documentation for additional resources.
|
||||
|
||||
## Future Roadmap
|
||||
|
||||
### Phase 1 (Current)
|
||||
- Basic content generation
|
||||
- Image generation
|
||||
- Advanced customization options
|
||||
|
||||
### Phase 2 (Coming Soon)
|
||||
- Music integration
|
||||
- Video script generation
|
||||
- Performance analytics
|
||||
|
||||
### Phase 3 (Future)
|
||||
- AI-powered video editing suggestions
|
||||
- Audience sentiment analysis
|
||||
- Competitor content analysis
|
||||
- Automated content scheduling
|
||||
- Multi-platform adaptation (Instagram Reels, TikTok)
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome feedback and contributions to improve the Facebook Reel Generator. If you have suggestions for new features or improvements, please reach out to our development team.
|
||||
|
||||
## License
|
||||
|
||||
This tool is part of the ALwrity AI Writer suite and is subject to the same licensing terms.
|
||||
|
||||
---
|
||||
|
||||
*Last updated: April 2025*
|
||||
@@ -0,0 +1,902 @@
|
||||
"""
|
||||
Facebook Reel Generator Module
|
||||
|
||||
This module provides functionality to generate Facebook Reel content using AI.
|
||||
It leverages text and image generation capabilities to create engaging reel content.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import os
|
||||
import sys
|
||||
from loguru import logger
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
# Import text generation
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Import image generation
|
||||
from .....gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
|
||||
|
||||
# Configure logging
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
def write_fb_reel():
|
||||
"""
|
||||
Main function to render the Facebook Reel Generator UI and handle the generation process.
|
||||
"""
|
||||
# Add back to dashboard button with minimal top margin
|
||||
st.markdown("""
|
||||
<div style='margin-top: 1rem; margin-bottom: 1rem;'>
|
||||
<a href="/" class="streamlit-button" style='text-decoration: none; color: white; background-color: #1877F2; padding: 0.5rem 1rem; border-radius: 0.5rem;'>← Back to Dashboard</a>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Main title card with improved spacing
|
||||
st.markdown("""
|
||||
<div style='background-color: #f0f2f6; padding: 1.5rem; border-radius: 5px; margin-bottom: 1.5rem;'>
|
||||
<div style='display: flex; align-items: center; justify-content: center; margin-bottom: 0.5rem;'>
|
||||
<span style='font-size: 2rem; margin-right: 0.5rem;'>🎥</span>
|
||||
<h1 style='color: #1877F2; margin: 0;'>Facebook Reel Generator</h1>
|
||||
</div>
|
||||
<p style='text-align: center; margin: 0;'>Create engaging Facebook Reels with AI-powered content</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3 = st.tabs(["Reel Content", "Visual Elements", "Advanced Options"])
|
||||
|
||||
with tab1:
|
||||
render_reel_content_tab()
|
||||
|
||||
with tab2:
|
||||
render_visual_elements_tab()
|
||||
|
||||
with tab3:
|
||||
render_advanced_options_tab()
|
||||
|
||||
def render_reel_content_tab():
|
||||
"""Render the Reel Content tab with input fields and generation options."""
|
||||
st.markdown("### Reel Content Settings")
|
||||
|
||||
# Create columns for input fields
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
business_type = st.text_input(
|
||||
"Business/Industry Type",
|
||||
placeholder="e.g., Fashion, Food, Fitness, Tech",
|
||||
help="The type of business or industry you're creating content for"
|
||||
)
|
||||
|
||||
target_audience = st.text_input(
|
||||
"Target Audience",
|
||||
placeholder="e.g., Young professionals, Parents, Fitness enthusiasts",
|
||||
help="Who is your content aimed at?"
|
||||
)
|
||||
|
||||
reel_purpose = st.selectbox(
|
||||
"Reel Purpose",
|
||||
options=[
|
||||
"Product Showcase",
|
||||
"Tutorial/How-to",
|
||||
"Behind the Scenes",
|
||||
"Customer Testimonials",
|
||||
"Brand Story",
|
||||
"Promotion/Offer",
|
||||
"Educational Content",
|
||||
"Entertainment"
|
||||
],
|
||||
help="What is the main purpose of your reel?"
|
||||
)
|
||||
|
||||
with col2:
|
||||
brand_voice = st.selectbox(
|
||||
"Brand Voice/Tone",
|
||||
options=[
|
||||
"Professional",
|
||||
"Casual/Friendly",
|
||||
"Humorous",
|
||||
"Inspirational",
|
||||
"Educational",
|
||||
"Luxury/Elegant",
|
||||
"Energetic",
|
||||
"Relaxed"
|
||||
],
|
||||
help="The tone and voice that represents your brand"
|
||||
)
|
||||
|
||||
key_message = st.text_area(
|
||||
"Key Message",
|
||||
placeholder="What's the main message you want to convey in your reel?",
|
||||
help="The primary message or takeaway for your audience"
|
||||
)
|
||||
|
||||
call_to_action = st.selectbox(
|
||||
"Call to Action",
|
||||
options=[
|
||||
"Follow Us",
|
||||
"Shop Now",
|
||||
"Learn More",
|
||||
"Sign Up",
|
||||
"Share",
|
||||
"Comment",
|
||||
"Save for Later",
|
||||
"Custom"
|
||||
],
|
||||
help="What action do you want viewers to take after watching?"
|
||||
)
|
||||
|
||||
if call_to_action == "Custom":
|
||||
custom_cta = st.text_input(
|
||||
"Custom Call to Action",
|
||||
placeholder="Enter your custom call to action"
|
||||
)
|
||||
else:
|
||||
custom_cta = ""
|
||||
|
||||
# Additional content options
|
||||
st.markdown("### Content Preferences")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
include_hashtags = st.checkbox("Include Hashtag Suggestions", value=True)
|
||||
include_hook = st.checkbox("Include Hook/Opening", value=True)
|
||||
include_transitions = st.checkbox("Include Transition Suggestions", value=True)
|
||||
|
||||
with col2:
|
||||
include_text_overlays = st.checkbox("Include Text Overlay Suggestions", value=True)
|
||||
include_engagement_tips = st.checkbox("Include Engagement Tips", value=True)
|
||||
include_trending_topics = st.checkbox("Include Trending Topics", value=True)
|
||||
|
||||
# Generate button
|
||||
if st.button("Generate Reel Content", type="primary"):
|
||||
if not business_type or not target_audience or not key_message:
|
||||
st.error("Please fill in the required fields: Business Type, Target Audience, and Key Message")
|
||||
return
|
||||
|
||||
with st.spinner("Generating your Facebook Reel content..."):
|
||||
# Generate the reel content
|
||||
reel_content = generate_reel_content(
|
||||
business_type=business_type,
|
||||
target_audience=target_audience,
|
||||
reel_purpose=reel_purpose,
|
||||
brand_voice=brand_voice,
|
||||
key_message=key_message,
|
||||
call_to_action=call_to_action,
|
||||
custom_cta=custom_cta,
|
||||
include_hashtags=include_hashtags,
|
||||
include_hook=include_hook,
|
||||
include_transitions=include_transitions,
|
||||
include_text_overlays=include_text_overlays,
|
||||
include_engagement_tips=include_engagement_tips,
|
||||
include_trending_topics=include_trending_topics
|
||||
)
|
||||
|
||||
# Display the generated content
|
||||
if reel_content:
|
||||
st.markdown("### Generated Reel Content")
|
||||
|
||||
# Create a container with a nice background for the content
|
||||
st.markdown("""
|
||||
<div style='background-color: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid #1877F2; margin-bottom: 20px;'>
|
||||
<h4 style='color: #1877F2;'>Your Facebook Reel Script</h4>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Parse and display the content in a structured way
|
||||
display_reel_content(reel_content)
|
||||
|
||||
# Add a download button for the content
|
||||
st.download_button(
|
||||
label="Download Reel Content",
|
||||
data=reel_content,
|
||||
file_name=f"facebook_reel_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
# Store the content in session state for the visual elements tab
|
||||
st.session_state['reel_content'] = reel_content
|
||||
else:
|
||||
st.error("Failed to generate reel content. Please try again.")
|
||||
|
||||
def render_visual_elements_tab():
|
||||
"""Render the Visual Elements tab for generating images and visual content."""
|
||||
st.markdown("### Visual Elements for Your Reel")
|
||||
|
||||
# Check if reel content has been generated
|
||||
if 'reel_content' not in st.session_state:
|
||||
st.info("Please generate reel content in the 'Reel Content' tab first.")
|
||||
return
|
||||
|
||||
st.markdown("""
|
||||
<div style='background-color: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 10px;'>
|
||||
<p><strong>Note:</strong> This feature generates visual elements for your reel. Music and video elements are coming soon.</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Visual element options
|
||||
st.markdown("#### Generate Visual Elements")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
visual_style = st.selectbox(
|
||||
"Visual Style",
|
||||
options=[
|
||||
"Modern and Clean",
|
||||
"Bold and Vibrant",
|
||||
"Minimalist",
|
||||
"Playful and Fun",
|
||||
"Professional",
|
||||
"Lifestyle",
|
||||
"Product-Focused",
|
||||
"Custom"
|
||||
],
|
||||
help="The overall visual style for your reel"
|
||||
)
|
||||
|
||||
if visual_style == "Custom":
|
||||
custom_style = st.text_input(
|
||||
"Custom Visual Style",
|
||||
placeholder="Describe your desired visual style"
|
||||
)
|
||||
else:
|
||||
custom_style = ""
|
||||
|
||||
num_images = st.slider(
|
||||
"Number of Images to Generate",
|
||||
min_value=1,
|
||||
max_value=5,
|
||||
value=3,
|
||||
help="How many visual elements would you like to generate?"
|
||||
)
|
||||
|
||||
with col2:
|
||||
image_aspect_ratio = st.selectbox(
|
||||
"Image Aspect Ratio",
|
||||
options=[
|
||||
"9:16 (Vertical - Reel)",
|
||||
"1:1 (Square)",
|
||||
"16:9 (Horizontal)",
|
||||
"4:5 (Instagram Portrait)"
|
||||
],
|
||||
help="The aspect ratio for your visual elements"
|
||||
)
|
||||
|
||||
image_quality = st.select_slider(
|
||||
"Image Quality",
|
||||
options=["Basic", "Standard", "High", "Premium"],
|
||||
value="Standard",
|
||||
help="The quality level for generated images"
|
||||
)
|
||||
|
||||
# Image generation prompt customization
|
||||
st.markdown("#### Customize Image Generation")
|
||||
|
||||
image_prompt_style = st.radio(
|
||||
"Image Prompt Style",
|
||||
options=["Automatic", "Custom"],
|
||||
help="Choose how to generate the image prompts"
|
||||
)
|
||||
|
||||
if image_prompt_style == "Custom":
|
||||
custom_image_prompt = st.text_area(
|
||||
"Custom Image Prompt",
|
||||
placeholder="Enter a custom prompt for image generation",
|
||||
help="Describe what you want the image to look like"
|
||||
)
|
||||
else:
|
||||
custom_image_prompt = ""
|
||||
|
||||
# Generate images button
|
||||
if st.button("Generate Visual Elements", type="primary"):
|
||||
with st.spinner("Generating visual elements for your reel..."):
|
||||
# Generate images based on the reel content
|
||||
images = generate_reel_images(
|
||||
reel_content=st.session_state['reel_content'],
|
||||
visual_style=visual_style,
|
||||
custom_style=custom_style if visual_style == "Custom" else None,
|
||||
num_images=num_images,
|
||||
image_aspect_ratio=image_aspect_ratio,
|
||||
image_quality=image_quality,
|
||||
custom_image_prompt=custom_image_prompt if image_prompt_style == "Custom" else None
|
||||
)
|
||||
|
||||
# Display the generated images
|
||||
if images:
|
||||
st.markdown("### Generated Visual Elements")
|
||||
|
||||
# Display images in a grid
|
||||
cols = st.columns(min(3, len(images)))
|
||||
for i, image_path in enumerate(images):
|
||||
with cols[i % len(cols)]:
|
||||
st.image(image_path, use_container_width=True)
|
||||
st.download_button(
|
||||
label=f"Download Image {i+1}",
|
||||
data=open(image_path, "rb").read(),
|
||||
file_name=f"reel_image_{i+1}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png",
|
||||
mime="image/png"
|
||||
)
|
||||
else:
|
||||
st.error("Failed to generate visual elements. Please try again.")
|
||||
|
||||
# Coming soon features
|
||||
st.markdown("### Coming Soon Features")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("""
|
||||
<div style='background-color: #e9ecef; padding: 15px; border-radius: 5px; margin-bottom: 10px;'>
|
||||
<h4>🎵 Music Suggestions</h4>
|
||||
<p>AI-powered music recommendations that match your reel's mood and content.</p>
|
||||
<span style='background-color: #6c757d; color: white; padding: 2px 8px; border-radius: 10px; font-size: 0.8em;'>Coming Soon</span>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
st.markdown("""
|
||||
<div style='background-color: #e9ecef; padding: 15px; border-radius: 5px; margin-bottom: 10px;'>
|
||||
<h4>🎬 Video Elements</h4>
|
||||
<p>Generate video clips, transitions, and effects to enhance your reel.</p>
|
||||
<span style='background-color: #6c757d; color: white; padding: 2px 8px; border-radius: 10px; font-size: 0.8em;'>Coming Soon</span>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def render_advanced_options_tab():
|
||||
"""Render the Advanced Options tab for additional customization."""
|
||||
st.markdown("### Advanced Options")
|
||||
|
||||
# Check if reel content has been generated
|
||||
if 'reel_content' not in st.session_state:
|
||||
st.info("Please generate reel content in the 'Reel Content' tab first.")
|
||||
return
|
||||
|
||||
st.markdown("""
|
||||
<div style='background-color: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 10px;'>
|
||||
<p><strong>Note:</strong> These advanced options allow for more customization of your reel content.</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Advanced content options
|
||||
st.markdown("#### Content Customization")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
content_length = st.select_slider(
|
||||
"Content Length",
|
||||
options=["Short (15s)", "Medium (30s)", "Long (60s)"],
|
||||
value="Medium (30s)",
|
||||
help="The target length for your reel content"
|
||||
)
|
||||
|
||||
language_style = st.selectbox(
|
||||
"Language Style",
|
||||
options=[
|
||||
"Simple and Clear",
|
||||
"Professional",
|
||||
"Casual",
|
||||
"Technical",
|
||||
"Persuasive",
|
||||
"Storytelling"
|
||||
],
|
||||
help="The language style for your content"
|
||||
)
|
||||
|
||||
with col2:
|
||||
include_stats = st.checkbox("Include Statistics/Facts", value=False)
|
||||
include_quotes = st.checkbox("Include Quote Suggestions", value=False)
|
||||
include_emoji = st.checkbox("Include Emoji Suggestions", value=True)
|
||||
|
||||
# AI model options
|
||||
st.markdown("#### AI Model Options")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
creativity_level = st.select_slider(
|
||||
"Creativity Level",
|
||||
options=["Conservative", "Balanced", "Creative", "Very Creative"],
|
||||
value="Balanced",
|
||||
help="How creative should the AI be in generating content"
|
||||
)
|
||||
|
||||
with col2:
|
||||
ai_provider = st.selectbox(
|
||||
"AI Provider",
|
||||
options=["Auto-Select", "OpenAI", "Google Gemini", "Anthropic Claude"],
|
||||
help="Which AI provider to use for content generation"
|
||||
)
|
||||
|
||||
# Generate with advanced options button
|
||||
if st.button("Regenerate with Advanced Options", type="primary"):
|
||||
with st.spinner("Regenerating your Facebook Reel content with advanced options..."):
|
||||
# Get the original content parameters from session state
|
||||
original_params = st.session_state.get('reel_params', {})
|
||||
|
||||
# Update with advanced options
|
||||
advanced_params = {
|
||||
**original_params,
|
||||
'content_length': content_length,
|
||||
'language_style': language_style,
|
||||
'include_stats': include_stats,
|
||||
'include_quotes': include_quotes,
|
||||
'include_emoji': include_emoji,
|
||||
'creativity_level': creativity_level,
|
||||
'ai_provider': ai_provider
|
||||
}
|
||||
|
||||
# Generate the reel content with advanced options
|
||||
reel_content = generate_reel_content_advanced(advanced_params)
|
||||
|
||||
# Display the generated content
|
||||
if reel_content:
|
||||
st.markdown("### Regenerated Reel Content")
|
||||
|
||||
# Create a container with a nice background for the content
|
||||
st.markdown("""
|
||||
<div style='background-color: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid #1877F2; margin-bottom: 20px;'>
|
||||
<h4 style='color: #1877F2;'>Your Facebook Reel Script</h4>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Parse and display the content in a structured way
|
||||
display_reel_content(reel_content)
|
||||
|
||||
# Add a download button for the content
|
||||
st.download_button(
|
||||
label="Download Reel Content",
|
||||
data=reel_content,
|
||||
file_name=f"facebook_reel_advanced_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
# Update the content in session state
|
||||
st.session_state['reel_content'] = reel_content
|
||||
else:
|
||||
st.error("Failed to regenerate reel content. Please try again.")
|
||||
|
||||
def generate_reel_content(
|
||||
business_type: str,
|
||||
target_audience: str,
|
||||
reel_purpose: str,
|
||||
brand_voice: str,
|
||||
key_message: str,
|
||||
call_to_action: str,
|
||||
custom_cta: str = "",
|
||||
include_hashtags: bool = True,
|
||||
include_hook: bool = True,
|
||||
include_transitions: bool = True,
|
||||
include_text_overlays: bool = True,
|
||||
include_engagement_tips: bool = True,
|
||||
include_trending_topics: bool = True
|
||||
) -> str:
|
||||
"""
|
||||
Generate Facebook Reel content based on user inputs.
|
||||
|
||||
Args:
|
||||
business_type: The type of business or industry
|
||||
target_audience: The target audience for the reel
|
||||
reel_purpose: The purpose of the reel
|
||||
brand_voice: The brand voice or tone
|
||||
key_message: The key message to convey
|
||||
call_to_action: The call to action
|
||||
custom_cta: Custom call to action text if "Custom" is selected
|
||||
include_hashtags: Whether to include hashtag suggestions
|
||||
include_hook: Whether to include a hook/opening
|
||||
include_transitions: Whether to include transition suggestions
|
||||
include_text_overlays: Whether to include text overlay suggestions
|
||||
include_engagement_tips: Whether to include engagement tips
|
||||
include_trending_topics: Whether to include trending topics
|
||||
|
||||
Returns:
|
||||
str: The generated reel content
|
||||
"""
|
||||
try:
|
||||
# Store parameters in session state for advanced options
|
||||
st.session_state['reel_params'] = {
|
||||
'business_type': business_type,
|
||||
'target_audience': target_audience,
|
||||
'reel_purpose': reel_purpose,
|
||||
'brand_voice': brand_voice,
|
||||
'key_message': key_message,
|
||||
'call_to_action': call_to_action,
|
||||
'custom_cta': custom_cta,
|
||||
'include_hashtags': include_hashtags,
|
||||
'include_hook': include_hook,
|
||||
'include_transitions': include_transitions,
|
||||
'include_text_overlays': include_text_overlays,
|
||||
'include_engagement_tips': include_engagement_tips,
|
||||
'include_trending_topics': include_trending_topics
|
||||
}
|
||||
|
||||
# Construct the prompt for the AI
|
||||
prompt = f"""
|
||||
Create a detailed Facebook Reel script for a {business_type} business targeting {target_audience}.
|
||||
|
||||
The purpose of this reel is: {reel_purpose}
|
||||
The brand voice/tone should be: {brand_voice}
|
||||
The key message to convey is: {key_message}
|
||||
The call to action should be: {call_to_action}{f" - {custom_cta}" if custom_cta else ""}
|
||||
|
||||
Please provide a complete Facebook Reel script with the following elements:
|
||||
|
||||
1. A hook (first 3 seconds) that grabs attention
|
||||
2. Main content (15-30 seconds) that delivers the key message
|
||||
3. A strong call-to-action at the end
|
||||
|
||||
Additional elements to include:
|
||||
{f"- Hashtag suggestions relevant to the content and industry" if include_hashtags else ""}
|
||||
{f"- Text overlay suggestions for key points" if include_text_overlays else ""}
|
||||
{f"- Transition suggestions between scenes" if include_transitions else ""}
|
||||
{f"- Engagement tips to encourage interaction" if include_engagement_tips else ""}
|
||||
{f"- Trending topics that could be incorporated" if include_trending_topics else ""}
|
||||
|
||||
Format the output as a structured script with clear sections and timing suggestions.
|
||||
"""
|
||||
|
||||
# Generate the content using the AI
|
||||
logger.info(f"[generate_reel_content] Generating reel content for {business_type}")
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
logger.info(f"[generate_reel_content] Successfully generated reel content")
|
||||
return response
|
||||
else:
|
||||
logger.error(f"[generate_reel_content] Failed to generate reel content")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[generate_reel_content] Error generating reel content: {str(e)}")
|
||||
return None
|
||||
|
||||
def generate_reel_content_advanced(params: Dict[str, Any]) -> str:
|
||||
"""
|
||||
Generate Facebook Reel content with advanced options.
|
||||
|
||||
Args:
|
||||
params: Dictionary of parameters for content generation
|
||||
|
||||
Returns:
|
||||
str: The generated reel content
|
||||
"""
|
||||
try:
|
||||
# Extract parameters
|
||||
business_type = params.get('business_type', '')
|
||||
target_audience = params.get('target_audience', '')
|
||||
reel_purpose = params.get('reel_purpose', '')
|
||||
brand_voice = params.get('brand_voice', '')
|
||||
key_message = params.get('key_message', '')
|
||||
call_to_action = params.get('call_to_action', '')
|
||||
custom_cta = params.get('custom_cta', '')
|
||||
content_length = params.get('content_length', 'Medium (30s)')
|
||||
language_style = params.get('language_style', 'Simple and Clear')
|
||||
include_stats = params.get('include_stats', False)
|
||||
include_quotes = params.get('include_quotes', False)
|
||||
include_emoji = params.get('include_emoji', True)
|
||||
creativity_level = params.get('creativity_level', 'Balanced')
|
||||
ai_provider = params.get('ai_provider', 'Auto-Select')
|
||||
|
||||
# Construct the advanced prompt
|
||||
prompt = f"""
|
||||
Create a detailed Facebook Reel script for a {business_type} business targeting {target_audience}.
|
||||
|
||||
The purpose of this reel is: {reel_purpose}
|
||||
The brand voice/tone should be: {brand_voice}
|
||||
The key message to convey is: {key_message}
|
||||
The call to action should be: {call_to_action}{f" - {custom_cta}" if custom_cta else ""}
|
||||
|
||||
Advanced requirements:
|
||||
- Content length: {content_length}
|
||||
- Language style: {language_style}
|
||||
- Creativity level: {creativity_level}
|
||||
{f"- Include relevant statistics or facts to support the message" if include_stats else ""}
|
||||
{f"- Include quote suggestions that could be used in the reel" if include_quotes else ""}
|
||||
{f"- Include emoji suggestions for text overlays" if include_emoji else ""}
|
||||
|
||||
Please provide a complete Facebook Reel script with the following elements:
|
||||
|
||||
1. A hook (first 3 seconds) that grabs attention
|
||||
2. Main content that delivers the key message
|
||||
3. A strong call-to-action at the end
|
||||
|
||||
Format the output as a structured script with clear sections and timing suggestions.
|
||||
"""
|
||||
|
||||
# Generate the content using the AI
|
||||
logger.info(f"[generate_reel_content_advanced] Generating advanced reel content for {business_type}")
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
logger.info(f"[generate_reel_content_advanced] Successfully generated advanced reel content")
|
||||
return response
|
||||
else:
|
||||
logger.error(f"[generate_reel_content_advanced] Failed to generate advanced reel content")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[generate_reel_content_advanced] Error generating advanced reel content: {str(e)}")
|
||||
return None
|
||||
|
||||
def generate_reel_images(
|
||||
reel_content: str,
|
||||
visual_style: str,
|
||||
custom_style: Optional[str] = None,
|
||||
num_images: int = 3,
|
||||
image_aspect_ratio: str = "9:16 (Vertical - Reel)",
|
||||
image_quality: str = "Standard",
|
||||
custom_image_prompt: Optional[str] = None
|
||||
) -> List[str]:
|
||||
"""
|
||||
Generate images for a Facebook Reel based on the content.
|
||||
|
||||
Args:
|
||||
reel_content: The generated reel content
|
||||
visual_style: The visual style for the images
|
||||
custom_style: Custom style description if "Custom" is selected
|
||||
num_images: Number of images to generate
|
||||
image_aspect_ratio: The aspect ratio for the images
|
||||
image_quality: The quality level for the images
|
||||
custom_image_prompt: Custom prompt for image generation
|
||||
|
||||
Returns:
|
||||
List[str]: List of paths to the generated images
|
||||
"""
|
||||
try:
|
||||
logger.info(f"[generate_reel_images] Generating {num_images} images for reel")
|
||||
|
||||
# Extract key elements from the reel content
|
||||
prompt = f"""
|
||||
Based on the following Facebook Reel content, extract {num_images} key visual elements or scenes that would make compelling images.
|
||||
For each element, provide a detailed description that would work well for AI image generation.
|
||||
|
||||
Reel Content:
|
||||
{reel_content}
|
||||
|
||||
For each visual element, provide:
|
||||
1. A descriptive title
|
||||
2. A detailed image generation prompt that includes:
|
||||
- The main subject
|
||||
- The setting/background
|
||||
- The mood/atmosphere
|
||||
- The style ({visual_style}{f" - {custom_style}" if custom_style else ""})
|
||||
- The aspect ratio ({image_aspect_ratio})
|
||||
- The quality level ({image_quality})
|
||||
|
||||
Format each element as:
|
||||
TITLE: [title]
|
||||
PROMPT: [detailed prompt]
|
||||
|
||||
Generate exactly {num_images} elements.
|
||||
"""
|
||||
|
||||
# Generate the image prompts using the AI
|
||||
logger.info(f"[generate_reel_images] Generating image prompts")
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if not response:
|
||||
logger.error(f"[generate_reel_images] Failed to generate image prompts")
|
||||
return []
|
||||
|
||||
# Parse the response to extract the image prompts
|
||||
image_prompts = []
|
||||
current_title = ""
|
||||
current_prompt = ""
|
||||
|
||||
for line in response.split('\n'):
|
||||
if line.startswith("TITLE:"):
|
||||
if current_title and current_prompt:
|
||||
image_prompts.append((current_title, current_prompt))
|
||||
current_title = line.replace("TITLE:", "").strip()
|
||||
current_prompt = ""
|
||||
elif line.startswith("PROMPT:"):
|
||||
current_prompt = line.replace("PROMPT:", "").strip()
|
||||
elif current_prompt and line.strip():
|
||||
current_prompt += " " + line.strip()
|
||||
|
||||
# Add the last prompt if there is one
|
||||
if current_title and current_prompt:
|
||||
image_prompts.append((current_title, current_prompt))
|
||||
|
||||
# If we don't have enough prompts, generate generic ones
|
||||
while len(image_prompts) < num_images:
|
||||
image_prompts.append((f"Generic Image {len(image_prompts)+1}",
|
||||
f"A visually appealing image related to {visual_style} style for a Facebook Reel"))
|
||||
|
||||
# Generate the images
|
||||
image_paths = []
|
||||
for i, (title, prompt) in enumerate(image_prompts[:num_images]):
|
||||
# Use custom prompt if provided
|
||||
if custom_image_prompt and i == 0:
|
||||
prompt = custom_image_prompt
|
||||
|
||||
logger.info(f"[generate_reel_images] Generating image {i+1}: {title}")
|
||||
image_path = generate_image(prompt)
|
||||
|
||||
if image_path:
|
||||
image_paths.append(image_path)
|
||||
logger.info(f"[generate_reel_images] Successfully generated image {i+1}")
|
||||
else:
|
||||
logger.error(f"[generate_reel_images] Failed to generate image {i+1}")
|
||||
|
||||
return image_paths
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[generate_reel_images] Error generating reel images: {str(e)}")
|
||||
return []
|
||||
|
||||
def display_reel_content(content: str):
|
||||
"""
|
||||
Display the reel content in a structured and visually appealing way.
|
||||
|
||||
Args:
|
||||
content: The generated reel content
|
||||
"""
|
||||
# Check if the content contains markdown code blocks
|
||||
if "```markdown" in content:
|
||||
# Extract the content from the markdown code block
|
||||
try:
|
||||
# Find the start and end of the markdown block
|
||||
start_idx = content.find("```markdown") + len("```markdown")
|
||||
end_idx = content.find("```", start_idx)
|
||||
if end_idx == -1: # If no closing markdown block found
|
||||
end_idx = len(content)
|
||||
|
||||
# Extract the markdown content
|
||||
markdown_content = content[start_idx:end_idx].strip()
|
||||
|
||||
# Split the content into sections
|
||||
sections = markdown_content.split('\n\n')
|
||||
|
||||
# Create tabs for different sections
|
||||
if len(sections) > 1:
|
||||
tabs = st.tabs(["Full Script", "Hook", "Main Content", "Call to Action", "Additional Elements"])
|
||||
|
||||
with tabs[0]: # Full Script
|
||||
st.markdown(markdown_content)
|
||||
|
||||
# Try to identify and display other sections
|
||||
hook_section = ""
|
||||
main_content = ""
|
||||
cta_section = ""
|
||||
additional_elements = ""
|
||||
|
||||
for section in sections:
|
||||
section_lower = section.lower()
|
||||
if "hook" in section_lower or "opening" in section_lower or "first 3 seconds" in section_lower or "0-3 seconds" in section_lower:
|
||||
hook_section = section
|
||||
elif "main content" in section_lower or "key message" in section_lower or "15-30 seconds" in section_lower:
|
||||
main_content = section
|
||||
elif "call to action" in section_lower or "cta" in section_lower or "end" in section_lower:
|
||||
cta_section = section
|
||||
elif "hashtag" in section_lower or "text overlay" in section_lower or "transition" in section_lower or "engagement" in section_lower or "trending" in section_lower or "additional" in section_lower:
|
||||
additional_elements += section + "\n\n"
|
||||
|
||||
with tabs[1]: # Hook
|
||||
if hook_section:
|
||||
st.markdown(hook_section)
|
||||
else:
|
||||
st.info("No specific hook section identified in the content.")
|
||||
|
||||
with tabs[2]: # Main Content
|
||||
if main_content:
|
||||
st.markdown(main_content)
|
||||
else:
|
||||
st.info("No specific main content section identified in the content.")
|
||||
|
||||
with tabs[3]: # Call to Action
|
||||
if cta_section:
|
||||
st.markdown(cta_section)
|
||||
else:
|
||||
st.info("No specific call to action section identified in the content.")
|
||||
|
||||
with tabs[4]: # Additional Elements
|
||||
if additional_elements:
|
||||
st.markdown(additional_elements)
|
||||
else:
|
||||
st.info("No additional elements identified in the content.")
|
||||
else:
|
||||
# If we can't split into sections, just display the content
|
||||
st.markdown(markdown_content)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing markdown content: {str(e)}")
|
||||
# Fallback to displaying the raw content
|
||||
st.markdown(content)
|
||||
else:
|
||||
# If no markdown code block, use the original approach
|
||||
# Split the content into sections
|
||||
sections = content.split('\n\n')
|
||||
|
||||
# Create tabs for different sections
|
||||
if len(sections) > 1:
|
||||
tabs = st.tabs(["Full Script", "Hook", "Main Content", "Call to Action", "Additional Elements"])
|
||||
|
||||
with tabs[0]: # Full Script
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_content = content.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_content}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Try to identify and display other sections
|
||||
hook_section = ""
|
||||
main_content = ""
|
||||
cta_section = ""
|
||||
additional_elements = ""
|
||||
|
||||
for section in sections:
|
||||
section_lower = section.lower()
|
||||
if "hook" in section_lower or "opening" in section_lower or "first 3 seconds" in section_lower or "0-3 seconds" in section_lower:
|
||||
hook_section = section
|
||||
elif "main content" in section_lower or "key message" in section_lower or "15-30 seconds" in section_lower:
|
||||
main_content = section
|
||||
elif "call to action" in section_lower or "cta" in section_lower or "end" in section_lower:
|
||||
cta_section = section
|
||||
elif "hashtag" in section_lower or "text overlay" in section_lower or "transition" in section_lower or "engagement" in section_lower or "trending" in section_lower or "additional" in section_lower:
|
||||
additional_elements += section + "\n\n"
|
||||
|
||||
with tabs[1]: # Hook
|
||||
if hook_section:
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_hook = hook_section.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_hook}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.info("No specific hook section identified in the content.")
|
||||
|
||||
with tabs[2]: # Main Content
|
||||
if main_content:
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_main = main_content.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_main}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.info("No specific main content section identified in the content.")
|
||||
|
||||
with tabs[3]: # Call to Action
|
||||
if cta_section:
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_cta = cta_section.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_cta}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.info("No specific call to action section identified in the content.")
|
||||
|
||||
with tabs[4]: # Additional Elements
|
||||
if additional_elements:
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_additional = additional_elements.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_additional}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.info("No additional elements identified in the content.")
|
||||
else:
|
||||
# If we can't split into sections, just display the content
|
||||
# Replace newlines with HTML line breaks
|
||||
formatted_content = content.replace('\n', '<br>')
|
||||
st.markdown(f"""
|
||||
<div style='background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0;'>
|
||||
{formatted_content}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
@@ -0,0 +1,124 @@
|
||||
# Facebook Group Post Generator
|
||||
|
||||
## Overview
|
||||
The Facebook Group Post Generator is a powerful tool designed to help content creators and community managers create engaging posts for Facebook Groups. It provides a comprehensive interface for crafting community-focused content that drives discussion and fosters engagement within Facebook Groups.
|
||||
|
||||
## Features
|
||||
|
||||
### Content & Media Management
|
||||
- **Multiple Post Types**: Create discussions, questions, announcements, resources, or event posts
|
||||
- **Rich Media Support**: Add images, videos, documents, or links to your posts
|
||||
- **AI-Powered Content Generation**: Generate engaging content based on your specifications
|
||||
- **Content Customization**: Fine-tune your post content with various formatting options
|
||||
|
||||
### Interactive Elements
|
||||
- **Poll Creation**: Create polls with up to 4 options to gather member opinions
|
||||
- **Question Features**: Add questions to encourage member responses
|
||||
- **Announcement Toggle**: Mark important posts as announcements for better visibility
|
||||
- **Media Attachments**: Support for various media types to enhance post engagement
|
||||
|
||||
### Engagement Optimization
|
||||
- **Target Audience Selection**: Customize posts for specific member segments
|
||||
- **Tone Customization**: Choose from professional, casual, friendly, formal, or humorous tones
|
||||
- **Call-to-Action Options**: Select from various actions to encourage member participation
|
||||
- **Engagement Prompts**: Add prompts to stimulate discussion and comments
|
||||
|
||||
### Preview & Export
|
||||
- **Live Preview**: See how your post will appear before publishing
|
||||
- **Export Options**: Copy to clipboard or download as text file
|
||||
- **Format Validation**: Ensure your post meets Facebook's requirements
|
||||
- **Timestamp Tracking**: Keep track of when posts were created
|
||||
|
||||
## How to Use
|
||||
|
||||
1. **Access the Generator**
|
||||
- Navigate to the Facebook Group Post Generator in the AI Writer dashboard
|
||||
- Select "Create New Post" to start
|
||||
|
||||
2. **Configure Post Settings**
|
||||
- Choose your post type
|
||||
- Add your content or let AI generate it
|
||||
- Select media options if needed
|
||||
|
||||
3. **Add Interactive Elements**
|
||||
- Create polls or questions
|
||||
- Set announcement status
|
||||
- Configure engagement settings
|
||||
|
||||
4. **Generate and Export**
|
||||
- Click "Generate Group Post" to create your content
|
||||
- Preview the generated post
|
||||
- Export or copy the content
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Creation
|
||||
- Keep posts concise and focused
|
||||
- Use clear, engaging language
|
||||
- Include relevant hashtags
|
||||
- Add visual elements when appropriate
|
||||
|
||||
### Engagement
|
||||
- Ask open-ended questions
|
||||
- Create polls for member input
|
||||
- Use appropriate tone for your audience
|
||||
- Include clear calls-to-action
|
||||
|
||||
### Media Usage
|
||||
- Optimize images for Facebook
|
||||
- Keep videos short and engaging
|
||||
- Use high-quality media
|
||||
- Include alt text for accessibility
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- Streamlit
|
||||
- Required Python packages:
|
||||
- streamlit
|
||||
- typing
|
||||
- datetime
|
||||
- json
|
||||
- logging
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Content Generation Fails**
|
||||
- Check your internet connection
|
||||
- Verify input parameters
|
||||
- Try reducing content length
|
||||
|
||||
2. **Media Upload Issues**
|
||||
- Ensure file size is within limits
|
||||
- Check file format compatibility
|
||||
- Verify file permissions
|
||||
|
||||
3. **Export Problems**
|
||||
- Check available disk space
|
||||
- Verify write permissions
|
||||
- Ensure proper file naming
|
||||
|
||||
## Future Updates
|
||||
|
||||
- Enhanced AI content generation
|
||||
- Additional media type support
|
||||
- Advanced analytics integration
|
||||
- Template library
|
||||
- Bulk post scheduling
|
||||
- Multi-language support
|
||||
- Advanced engagement metrics
|
||||
- A/B testing capabilities
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to improve the Facebook Group Post Generator. Please follow these steps:
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
This module is licensed under the MIT License. See the LICENSE file for details.
|
||||
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Facebook Group Post Generator Module
|
||||
|
||||
This module provides functionality to generate engaging posts for Facebook Groups.
|
||||
It helps content creators create community-focused content that drives engagement
|
||||
and fosters discussion within Facebook Groups.
|
||||
"""
|
||||
|
||||
from .group_post_generator import write_fb_group_post
|
||||
|
||||
__all__ = ['write_fb_group_post']
|
||||
@@ -0,0 +1,327 @@
|
||||
"""
|
||||
Facebook Group Post Generator Module
|
||||
|
||||
This module provides functionality to generate engaging posts for Facebook Groups.
|
||||
It helps content creators create community-focused content that drives engagement
|
||||
and fosters discussion within Facebook Groups.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional, Union, Tuple
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def write_fb_group_post():
|
||||
"""
|
||||
Generate a Facebook Group post with various customization options.
|
||||
|
||||
This function provides a comprehensive interface for creating engaging
|
||||
Facebook Group posts with features like:
|
||||
- Content customization
|
||||
- Polls and questions
|
||||
- Announcements
|
||||
- Media attachments
|
||||
- Engagement prompts
|
||||
"""
|
||||
|
||||
st.title("Facebook Group Post Generator")
|
||||
st.markdown("""
|
||||
Create engaging posts for your Facebook Groups that drive discussion and community engagement.
|
||||
Customize your content, add interactive elements, and optimize for maximum impact.
|
||||
""")
|
||||
|
||||
# Initialize session state for form data
|
||||
if 'group_post_data' not in st.session_state:
|
||||
st.session_state.group_post_data = {
|
||||
'post_type': 'discussion',
|
||||
'content': '',
|
||||
'media_type': 'none',
|
||||
'poll_options': [],
|
||||
'question': '',
|
||||
'is_announcement': False,
|
||||
'engagement_prompt': '',
|
||||
'hashtags': [],
|
||||
'target_audience': 'all',
|
||||
'post_tone': 'professional',
|
||||
'call_to_action': 'discuss'
|
||||
}
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4 = st.tabs([
|
||||
"Content & Media",
|
||||
"Interactive Elements",
|
||||
"Engagement",
|
||||
"Preview & Export"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
render_content_media_tab()
|
||||
|
||||
with tab2:
|
||||
render_interactive_elements_tab()
|
||||
|
||||
with tab3:
|
||||
render_engagement_tab()
|
||||
|
||||
with tab4:
|
||||
render_preview_export_tab()
|
||||
|
||||
# Generate button
|
||||
if st.button("Generate Group Post", type="primary"):
|
||||
if validate_group_post_fields():
|
||||
with st.spinner("Generating your group post..."):
|
||||
post_content = generate_group_post()
|
||||
if post_content:
|
||||
st.session_state.group_post_data['generated_content'] = post_content
|
||||
st.success("Group post generated successfully!")
|
||||
st.session_state.show_preview = True
|
||||
|
||||
def render_content_media_tab():
|
||||
"""Render the content and media input fields."""
|
||||
|
||||
st.header("Content & Media")
|
||||
|
||||
# Post Type Selection
|
||||
post_type = st.selectbox(
|
||||
"Post Type",
|
||||
options=['discussion', 'question', 'announcement', 'resource', 'event'],
|
||||
index=['discussion', 'question', 'announcement', 'resource', 'event'].index(
|
||||
st.session_state.group_post_data['post_type']
|
||||
),
|
||||
help="Choose the type of post you want to create"
|
||||
)
|
||||
st.session_state.group_post_data['post_type'] = post_type
|
||||
|
||||
# Content Input
|
||||
content = st.text_area(
|
||||
"Post Content",
|
||||
value=st.session_state.group_post_data['content'],
|
||||
height=200,
|
||||
help="Write your post content or leave blank for AI generation"
|
||||
)
|
||||
st.session_state.group_post_data['content'] = content
|
||||
|
||||
# Media Options
|
||||
media_type = st.selectbox(
|
||||
"Media Type",
|
||||
options=['none', 'image', 'video', 'document', 'link'],
|
||||
index=['none', 'image', 'video', 'document', 'link'].index(
|
||||
st.session_state.group_post_data['media_type']
|
||||
),
|
||||
help="Add media to your post"
|
||||
)
|
||||
st.session_state.group_post_data['media_type'] = media_type
|
||||
|
||||
if media_type != 'none':
|
||||
if media_type == 'image':
|
||||
st.file_uploader("Upload Image", type=['jpg', 'jpeg', 'png'])
|
||||
elif media_type == 'video':
|
||||
st.file_uploader("Upload Video", type=['mp4', 'mov'])
|
||||
elif media_type == 'document':
|
||||
st.file_uploader("Upload Document", type=['pdf', 'doc', 'docx'])
|
||||
elif media_type == 'link':
|
||||
st.text_input("Enter URL", help="Paste the URL you want to share")
|
||||
|
||||
def render_interactive_elements_tab():
|
||||
"""Render the interactive elements options."""
|
||||
|
||||
st.header("Interactive Elements")
|
||||
|
||||
# Poll Creation
|
||||
if st.checkbox("Add Poll", help="Create a poll for group members"):
|
||||
poll_question = st.text_input("Poll Question")
|
||||
poll_options = []
|
||||
for i in range(4):
|
||||
option = st.text_input(f"Option {i+1}")
|
||||
if option:
|
||||
poll_options.append(option)
|
||||
st.session_state.group_post_data['poll_options'] = poll_options
|
||||
|
||||
# Question Creation
|
||||
if st.checkbox("Add Question", help="Ask a question to group members"):
|
||||
question = st.text_input("Your Question")
|
||||
st.session_state.group_post_data['question'] = question
|
||||
|
||||
# Announcement Toggle
|
||||
is_announcement = st.checkbox(
|
||||
"Mark as Announcement",
|
||||
value=st.session_state.group_post_data['is_announcement'],
|
||||
help="Pin this post as an announcement in the group"
|
||||
)
|
||||
st.session_state.group_post_data['is_announcement'] = is_announcement
|
||||
|
||||
def render_engagement_tab():
|
||||
"""Render the engagement options."""
|
||||
|
||||
st.header("Engagement Settings")
|
||||
|
||||
# Engagement Prompt
|
||||
engagement_prompt = st.text_area(
|
||||
"Engagement Prompt",
|
||||
value=st.session_state.group_post_data['engagement_prompt'],
|
||||
help="Add a prompt to encourage comments and discussion"
|
||||
)
|
||||
st.session_state.group_post_data['engagement_prompt'] = engagement_prompt
|
||||
|
||||
# Target Audience
|
||||
target_audience = st.selectbox(
|
||||
"Target Audience",
|
||||
options=['all', 'new_members', 'active_members', 'specific_role'],
|
||||
index=['all', 'new_members', 'active_members', 'specific_role'].index(
|
||||
st.session_state.group_post_data['target_audience']
|
||||
),
|
||||
help="Select who this post is primarily for"
|
||||
)
|
||||
st.session_state.group_post_data['target_audience'] = target_audience
|
||||
|
||||
# Post Tone
|
||||
post_tone = st.selectbox(
|
||||
"Post Tone",
|
||||
options=['professional', 'casual', 'friendly', 'formal', 'humorous'],
|
||||
index=['professional', 'casual', 'friendly', 'formal', 'humorous'].index(
|
||||
st.session_state.group_post_data['post_tone']
|
||||
),
|
||||
help="Choose the tone for your post"
|
||||
)
|
||||
st.session_state.group_post_data['post_tone'] = post_tone
|
||||
|
||||
# Call to Action
|
||||
call_to_action = st.selectbox(
|
||||
"Call to Action",
|
||||
options=['discuss', 'share', 'learn', 'participate', 'feedback'],
|
||||
index=['discuss', 'share', 'learn', 'participate', 'feedback'].index(
|
||||
st.session_state.group_post_data['call_to_action']
|
||||
),
|
||||
help="What action do you want members to take?"
|
||||
)
|
||||
st.session_state.group_post_data['call_to_action'] = call_to_action
|
||||
|
||||
def render_preview_export_tab():
|
||||
"""Render the preview and export options."""
|
||||
|
||||
st.header("Preview & Export")
|
||||
|
||||
if 'generated_content' in st.session_state.group_post_data:
|
||||
st.subheader("Generated Post")
|
||||
st.markdown(st.session_state.group_post_data['generated_content'])
|
||||
|
||||
# Export options
|
||||
st.subheader("Export Options")
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
if st.button("Copy to Clipboard"):
|
||||
st.code(st.session_state.group_post_data['generated_content'])
|
||||
|
||||
with col2:
|
||||
if st.button("Download as Text"):
|
||||
download_group_post(st.session_state.group_post_data['generated_content'])
|
||||
|
||||
def validate_group_post_fields() -> bool:
|
||||
"""Validate the group post fields."""
|
||||
|
||||
data = st.session_state.group_post_data
|
||||
|
||||
# Basic validation rules
|
||||
validation_rules = {
|
||||
'post_type': {'required': True, 'type': str},
|
||||
'content': {'required': False, 'type': str},
|
||||
'media_type': {'required': True, 'type': str},
|
||||
'poll_options': {'required': False, 'type': list},
|
||||
'question': {'required': False, 'type': str},
|
||||
'is_announcement': {'required': True, 'type': bool},
|
||||
'engagement_prompt': {'required': False, 'type': str},
|
||||
'target_audience': {'required': True, 'type': str},
|
||||
'post_tone': {'required': True, 'type': str},
|
||||
'call_to_action': {'required': True, 'type': str}
|
||||
}
|
||||
|
||||
errors = []
|
||||
|
||||
for field, rules in validation_rules.items():
|
||||
value = data.get(field)
|
||||
|
||||
# Skip validation for optional fields if empty
|
||||
if not rules['required'] and not value:
|
||||
continue
|
||||
|
||||
# Type validation
|
||||
if value and not isinstance(value, rules['type']):
|
||||
errors.append(f"{field.replace('_', ' ').title()} must be of type {rules['type'].__name__}")
|
||||
continue
|
||||
|
||||
# Required field validation
|
||||
if rules['required'] and not value:
|
||||
errors.append(f"{field.replace('_', ' ').title()} is required")
|
||||
|
||||
if errors:
|
||||
for error in errors:
|
||||
st.error(error)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generate_group_post() -> Optional[str]:
|
||||
"""Generate the group post content using AI."""
|
||||
|
||||
try:
|
||||
data = st.session_state.group_post_data
|
||||
|
||||
# Prepare the prompt for the LLM
|
||||
prompt = f"""
|
||||
Create a Facebook Group post with the following specifications:
|
||||
|
||||
Post Type: {data['post_type']}
|
||||
Content: {data['content'] if data['content'] else 'Generate engaging content'}
|
||||
Media Type: {data['media_type']}
|
||||
Target Audience: {data['target_audience']}
|
||||
Post Tone: {data['post_tone']}
|
||||
Call to Action: {data['call_to_action']}
|
||||
|
||||
Additional Elements:
|
||||
- Poll Options: {', '.join(data['poll_options']) if data['poll_options'] else 'None'}
|
||||
- Question: {data['question'] if data['question'] else 'None'}
|
||||
- Is Announcement: {data['is_announcement']}
|
||||
- Engagement Prompt: {data['engagement_prompt'] if data['engagement_prompt'] else 'None'}
|
||||
|
||||
The post should be engaging, community-focused, and encourage discussion.
|
||||
Include appropriate formatting, emojis, and hashtags where relevant.
|
||||
"""
|
||||
|
||||
# Get response from LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
return response
|
||||
else:
|
||||
st.error("Failed to generate group post content. Please try again.")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating group post: {str(e)}")
|
||||
st.error("An error occurred while generating the group post. Please try again.")
|
||||
return None
|
||||
|
||||
def download_group_post(content: str):
|
||||
"""Download the generated group post as a text file."""
|
||||
|
||||
try:
|
||||
# Create a timestamp for the filename
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"facebook_group_post_{timestamp}.txt"
|
||||
|
||||
# Create the download button
|
||||
st.download_button(
|
||||
label="Download Post",
|
||||
data=content,
|
||||
file_name=filename,
|
||||
mime="text/plain"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error downloading group post: {str(e)}")
|
||||
st.error("An error occurred while downloading the post. Please try again.")
|
||||
@@ -0,0 +1,145 @@
|
||||
# Facebook Hashtag Generator
|
||||
|
||||
A powerful tool for generating optimized hashtags for your Facebook content. This module helps content creators maximize their reach and engagement through strategic hashtag selection and placement.
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Smart Hashtag Generation
|
||||
- AI-powered hashtag suggestions based on content analysis
|
||||
- Industry-specific hashtag recommendations
|
||||
- Mix of trending and niche hashtags
|
||||
- Customizable number of hashtags
|
||||
- Content type-specific optimization
|
||||
|
||||
### 2. Performance Predictions
|
||||
- Reach estimates for each hashtag
|
||||
- Engagement rate predictions
|
||||
- Competition level analysis
|
||||
- Visual performance metrics
|
||||
- Best performing hashtag combinations
|
||||
|
||||
### 3. Hashtag Library
|
||||
- Save and organize your hashtags
|
||||
- Create custom collections
|
||||
- Quick access to frequently used hashtags
|
||||
- Easy management of hashtag sets
|
||||
- Import/export functionality
|
||||
|
||||
### 4. Placement Optimization
|
||||
- Smart placement suggestions
|
||||
- Integration within content
|
||||
- End-of-post placement
|
||||
- Mixed placement strategies
|
||||
- Preview of hashtag placement
|
||||
|
||||
## How to Use
|
||||
|
||||
1. **Generate Hashtags**
|
||||
- Enter your content or topic
|
||||
- Select your industry
|
||||
- Choose content type
|
||||
- Set hashtag preferences
|
||||
- Click "Generate Hashtags"
|
||||
|
||||
2. **Manage Library**
|
||||
- Save generated hashtags
|
||||
- Create collections
|
||||
- Add custom hashtags
|
||||
- Remove unused hashtags
|
||||
- Organize by category
|
||||
|
||||
3. **View Insights**
|
||||
- Check performance metrics
|
||||
- Analyze reach predictions
|
||||
- Review engagement rates
|
||||
- Compare competition levels
|
||||
- Get optimal combinations
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Analysis
|
||||
- Provide detailed content description
|
||||
- Include key topics and themes
|
||||
- Mention target audience
|
||||
- Specify content goals
|
||||
- Add relevant context
|
||||
|
||||
### Hashtag Selection
|
||||
- Mix popular and niche hashtags
|
||||
- Use industry-specific tags
|
||||
- Include trending hashtags
|
||||
- Avoid overused combinations
|
||||
- Test different variations
|
||||
|
||||
### Placement Strategy
|
||||
- Natural integration
|
||||
- Strategic positioning
|
||||
- Readability focus
|
||||
- Engagement optimization
|
||||
- Mobile-friendly format
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- Streamlit
|
||||
- Required Python packages:
|
||||
- streamlit
|
||||
- loguru
|
||||
- typing
|
||||
- json
|
||||
- re
|
||||
- random
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Generation Failures**
|
||||
- Check content input
|
||||
- Verify industry selection
|
||||
- Ensure internet connection
|
||||
- Clear browser cache
|
||||
- Restart application
|
||||
|
||||
2. **Performance Issues**
|
||||
- Reduce hashtag count
|
||||
- Clear saved hashtags
|
||||
- Update browser
|
||||
- Check system resources
|
||||
- Contact support
|
||||
|
||||
### Error Messages
|
||||
- "Please enter content" - Add content description
|
||||
- "Invalid industry" - Select from dropdown
|
||||
- "Generation failed" - Try again or use defaults
|
||||
- "Save failed" - Check storage permissions
|
||||
- "Display error" - Refresh page
|
||||
|
||||
## Future Updates
|
||||
|
||||
### Planned Features
|
||||
- Advanced analytics
|
||||
- Competitor analysis
|
||||
- Hashtag tracking
|
||||
- Performance history
|
||||
- Bulk generation
|
||||
- API integration
|
||||
- Custom algorithms
|
||||
- Multi-language support
|
||||
- Export options
|
||||
- Collaboration tools
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to improve the Hashtag Generator:
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Submit a pull request
|
||||
5. Follow coding standards
|
||||
6. Add tests
|
||||
7. Update documentation
|
||||
|
||||
## License
|
||||
|
||||
This module is part of the AI Writer suite and is subject to the same licensing terms. See the main LICENSE file for details.
|
||||
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Facebook Hashtag Generator Module
|
||||
|
||||
This module provides functionality to generate optimized hashtags for Facebook content.
|
||||
"""
|
||||
|
||||
from .hashtag_generator import write_fb_hashtags
|
||||
|
||||
__all__ = ['write_fb_hashtags']
|
||||
@@ -0,0 +1,567 @@
|
||||
"""
|
||||
Facebook Hashtag Generator Module
|
||||
|
||||
This module provides functionality to generate relevant and trending hashtags for Facebook content.
|
||||
It analyzes content, suggests optimal hashtag combinations, and provides performance predictions.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
from typing import List, Dict, Any, Tuple, Optional
|
||||
from loguru import logger
|
||||
import sys
|
||||
import base64
|
||||
from io import BytesIO
|
||||
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Configure logging
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
def initialize_session_state():
|
||||
"""Initialize session state with default values."""
|
||||
if 'hashtag_data' not in st.session_state:
|
||||
st.session_state.hashtag_data = {
|
||||
'content': "",
|
||||
'industry': "",
|
||||
'content_type': "Post",
|
||||
'hashtag_count': 5,
|
||||
'include_trending': True,
|
||||
'include_niche': True,
|
||||
'generated_hashtags': [],
|
||||
'performance_predictions': {},
|
||||
'saved_hashtags': []
|
||||
}
|
||||
|
||||
def write_fb_hashtags():
|
||||
"""Generate relevant and trending hashtags for Facebook content."""
|
||||
|
||||
# Initialize session state
|
||||
initialize_session_state()
|
||||
|
||||
st.markdown("""
|
||||
### #️⃣ Facebook Hashtag Generator
|
||||
Create optimized hashtag combinations that maximize your content's reach and engagement.
|
||||
Our AI analyzes your content and suggests the perfect hashtags for your Facebook posts.
|
||||
""")
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3 = st.tabs(["Generate Hashtags", "Hashtag Library", "Performance Insights"])
|
||||
|
||||
with tab1:
|
||||
render_generate_tab()
|
||||
|
||||
with tab2:
|
||||
render_library_tab()
|
||||
|
||||
with tab3:
|
||||
render_insights_tab()
|
||||
|
||||
def render_generate_tab():
|
||||
"""Render the hashtag generation tab with input fields."""
|
||||
|
||||
# Content Input
|
||||
st.markdown("#### Content for Hashtag Analysis")
|
||||
|
||||
content = st.text_area(
|
||||
"Enter your content or describe what you're posting about",
|
||||
value=st.session_state.hashtag_data['content'],
|
||||
height=150,
|
||||
help="Enter the text content or describe the topic of your Facebook post",
|
||||
key="content_input"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['content'] = content
|
||||
|
||||
# Industry and Content Type
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
industries = [
|
||||
"Technology", "Health & Wellness", "Fashion", "Food & Beverage",
|
||||
"Travel", "Education", "Finance", "Entertainment", "Fitness",
|
||||
"Beauty", "Home & Garden", "Automotive", "Real Estate", "Business",
|
||||
"Art & Design", "Sports", "Parenting", "Pets", "Other"
|
||||
]
|
||||
|
||||
industry = st.selectbox(
|
||||
"Industry",
|
||||
options=industries,
|
||||
index=industries.index(st.session_state.hashtag_data['industry']) if st.session_state.hashtag_data['industry'] in industries else 0,
|
||||
help="Select your industry for more relevant hashtag suggestions",
|
||||
key="industry_select"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['industry'] = industry
|
||||
|
||||
with col2:
|
||||
content_types = ["Post", "Story", "Reel", "Carousel", "Event", "Group Post"]
|
||||
|
||||
content_type = st.selectbox(
|
||||
"Content Type",
|
||||
options=content_types,
|
||||
index=content_types.index(st.session_state.hashtag_data['content_type']) if st.session_state.hashtag_data['content_type'] in content_types else 0,
|
||||
help="Select the type of content you're creating",
|
||||
key="content_type_select"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['content_type'] = content_type
|
||||
|
||||
# Hashtag Preferences
|
||||
st.markdown("#### Hashtag Preferences")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
hashtag_count = st.slider(
|
||||
"Number of Hashtags",
|
||||
min_value=1,
|
||||
max_value=30,
|
||||
value=st.session_state.hashtag_data['hashtag_count'],
|
||||
help="Select how many hashtags you want to generate",
|
||||
key="hashtag_count_slider"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['hashtag_count'] = hashtag_count
|
||||
|
||||
include_trending = st.checkbox(
|
||||
"Include Trending Hashtags",
|
||||
value=st.session_state.hashtag_data['include_trending'],
|
||||
help="Include currently trending hashtags in suggestions",
|
||||
key="include_trending_checkbox"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['include_trending'] = include_trending
|
||||
|
||||
with col2:
|
||||
include_niche = st.checkbox(
|
||||
"Include Niche Hashtags",
|
||||
value=st.session_state.hashtag_data['include_niche'],
|
||||
help="Include niche, industry-specific hashtags",
|
||||
key="include_niche_checkbox"
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['include_niche'] = include_niche
|
||||
|
||||
hashtag_placement = st.radio(
|
||||
"Hashtag Placement",
|
||||
["End of Post", "Throughout Content", "Both"],
|
||||
index=0,
|
||||
help="Select where you want to place the hashtags",
|
||||
key="hashtag_placement_radio"
|
||||
)
|
||||
|
||||
# Generate Button
|
||||
if st.button("Generate Hashtags", key="generate_hashtags_button"):
|
||||
if not content:
|
||||
st.warning("Please enter some content to generate hashtags.")
|
||||
else:
|
||||
with st.spinner("Generating optimized hashtags..."):
|
||||
# Generate hashtags
|
||||
generated_hashtags, performance_predictions = generate_hashtags(
|
||||
content,
|
||||
industry,
|
||||
content_type,
|
||||
hashtag_count,
|
||||
include_trending,
|
||||
include_niche
|
||||
)
|
||||
|
||||
# Update session state
|
||||
st.session_state.hashtag_data['generated_hashtags'] = generated_hashtags
|
||||
st.session_state.hashtag_data['performance_predictions'] = performance_predictions
|
||||
|
||||
# Display results
|
||||
display_hashtag_results(generated_hashtags, performance_predictions, hashtag_placement)
|
||||
|
||||
def render_library_tab():
|
||||
"""Render the hashtag library tab."""
|
||||
|
||||
st.markdown("#### Hashtag Library")
|
||||
|
||||
# Initialize saved hashtags if not exists
|
||||
if 'saved_hashtags' not in st.session_state.hashtag_data:
|
||||
st.session_state.hashtag_data['saved_hashtags'] = []
|
||||
|
||||
# Create collections
|
||||
collections = ["Favorites", "Industry", "Campaign", "Custom"]
|
||||
|
||||
selected_collection = st.selectbox(
|
||||
"Select Collection",
|
||||
options=collections,
|
||||
index=0,
|
||||
help="Select a hashtag collection to view or edit",
|
||||
key="collection_select"
|
||||
)
|
||||
|
||||
# Display saved hashtags
|
||||
if st.session_state.hashtag_data['saved_hashtags']:
|
||||
st.markdown(f"**{selected_collection} Collection**")
|
||||
|
||||
for i, hashtag in enumerate(st.session_state.hashtag_data['saved_hashtags']):
|
||||
col1, col2 = st.columns([3, 1])
|
||||
|
||||
with col1:
|
||||
st.write(f"#{hashtag}")
|
||||
|
||||
with col2:
|
||||
if st.button("Remove", key=f"remove_{i}"):
|
||||
st.session_state.hashtag_data['saved_hashtags'].remove(hashtag)
|
||||
st.rerun()
|
||||
else:
|
||||
st.info("Your hashtag library is empty. Generate hashtags and save them to build your library.")
|
||||
|
||||
# Add new hashtag
|
||||
st.markdown("#### Add New Hashtag")
|
||||
|
||||
col1, col2 = st.columns([3, 1])
|
||||
|
||||
with col1:
|
||||
new_hashtag = st.text_input(
|
||||
"Enter hashtag (without #)",
|
||||
value="",
|
||||
help="Enter a hashtag to add to your library",
|
||||
key="new_hashtag_input"
|
||||
)
|
||||
|
||||
with col2:
|
||||
if st.button("Add", key="add_hashtag_button"):
|
||||
if new_hashtag:
|
||||
# Remove # if present
|
||||
new_hashtag = new_hashtag.replace("#", "")
|
||||
|
||||
# Add to saved hashtags
|
||||
if new_hashtag not in st.session_state.hashtag_data['saved_hashtags']:
|
||||
st.session_state.hashtag_data['saved_hashtags'].append(new_hashtag)
|
||||
st.success(f"Added #{new_hashtag} to your library.")
|
||||
else:
|
||||
st.warning(f"#{new_hashtag} is already in your library.")
|
||||
else:
|
||||
st.warning("Please enter a hashtag.")
|
||||
|
||||
def render_insights_tab():
|
||||
"""Render the performance insights tab."""
|
||||
|
||||
st.markdown("#### Hashtag Performance Insights")
|
||||
|
||||
# Check if we have generated hashtags
|
||||
if not st.session_state.hashtag_data['generated_hashtags']:
|
||||
st.info("Generate hashtags first to see performance insights.")
|
||||
return
|
||||
|
||||
# Display performance metrics
|
||||
st.markdown("##### Performance Predictions")
|
||||
|
||||
performance_predictions = st.session_state.hashtag_data['performance_predictions']
|
||||
|
||||
# Create a bar chart for reach predictions
|
||||
reach_data = {hashtag: data['reach'] for hashtag, data in performance_predictions.items()}
|
||||
|
||||
if reach_data:
|
||||
st.bar_chart(reach_data)
|
||||
|
||||
# Display detailed metrics
|
||||
st.markdown("##### Detailed Metrics")
|
||||
|
||||
for hashtag, metrics in performance_predictions.items():
|
||||
with st.expander(f"#{hashtag}"):
|
||||
col1, col2, col3 = st.columns(3)
|
||||
|
||||
with col1:
|
||||
st.metric("Reach", f"{metrics['reach']:,}")
|
||||
|
||||
with col2:
|
||||
st.metric("Engagement", f"{metrics['engagement']}%")
|
||||
|
||||
with col3:
|
||||
st.metric("Competition", metrics['competition'])
|
||||
|
||||
# Hashtag recommendations
|
||||
st.markdown("##### Recommendations")
|
||||
|
||||
# Find best performing hashtags
|
||||
best_hashtags = sorted(
|
||||
performance_predictions.items(),
|
||||
key=lambda x: x[1]['reach'],
|
||||
reverse=True
|
||||
)[:3]
|
||||
|
||||
st.markdown("**Best Performing Hashtags:**")
|
||||
for hashtag, metrics in best_hashtags:
|
||||
st.write(f"#{hashtag} - Reach: {metrics['reach']:,}, Engagement: {metrics['engagement']}%")
|
||||
|
||||
# Optimal combination
|
||||
st.markdown("**Optimal Hashtag Combination:**")
|
||||
optimal_combination = " ".join([f"#{hashtag}" for hashtag, _ in best_hashtags])
|
||||
st.code(optimal_combination)
|
||||
|
||||
# Copy button
|
||||
if st.button("Copy Optimal Combination", key="copy_optimal_button"):
|
||||
st.code(optimal_combination)
|
||||
st.success("Copied to clipboard!")
|
||||
|
||||
def generate_hashtags(
|
||||
content: str,
|
||||
industry: str,
|
||||
content_type: str,
|
||||
hashtag_count: int,
|
||||
include_trending: bool,
|
||||
include_niche: bool
|
||||
) -> Tuple[List[str], Dict[str, Dict[str, Any]]]:
|
||||
"""Generate hashtags based on content and preferences."""
|
||||
|
||||
# Prepare the prompt for the AI
|
||||
prompt = f"""
|
||||
Generate {hashtag_count} relevant and effective hashtags for a Facebook {content_type} in the {industry} industry.
|
||||
|
||||
Content or topic: {content}
|
||||
|
||||
Requirements:
|
||||
- Include a mix of popular and niche hashtags
|
||||
- Focus on hashtags that drive engagement and reach
|
||||
- Ensure hashtags are relevant to the content and industry
|
||||
- Format as a comma-separated list without the # symbol
|
||||
- Include {hashtag_count} hashtags total
|
||||
"""
|
||||
|
||||
if include_trending:
|
||||
prompt += "- Include some currently trending hashtags in this industry\n"
|
||||
|
||||
if include_niche:
|
||||
prompt += "- Include niche, industry-specific hashtags that have less competition\n"
|
||||
|
||||
prompt += """
|
||||
For each hashtag, also provide a performance prediction in this format:
|
||||
[hashtag_name]: [reach_number], [engagement_percentage], [competition_level]
|
||||
|
||||
Example:
|
||||
digitalmarketing: 50000, 3.2, Medium
|
||||
socialmediamarketing: 75000, 2.8, High
|
||||
"""
|
||||
|
||||
try:
|
||||
# Generate hashtags using AI
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
# Parse the response
|
||||
hashtags = []
|
||||
performance_predictions = {}
|
||||
|
||||
# Extract hashtags and performance data
|
||||
lines = response.strip().split('\n')
|
||||
for line in lines:
|
||||
if ':' in line:
|
||||
parts = line.split(':')
|
||||
if len(parts) == 2:
|
||||
hashtag = parts[0].strip()
|
||||
metrics = parts[1].strip().split(',')
|
||||
|
||||
if len(metrics) >= 3:
|
||||
try:
|
||||
reach = int(metrics[0].strip())
|
||||
engagement = float(metrics[1].strip().replace('%', ''))
|
||||
competition = metrics[2].strip()
|
||||
|
||||
hashtags.append(hashtag)
|
||||
performance_predictions[hashtag] = {
|
||||
'reach': reach,
|
||||
'engagement': engagement,
|
||||
'competition': competition
|
||||
}
|
||||
except (ValueError, IndexError):
|
||||
# Skip malformed entries
|
||||
continue
|
||||
|
||||
# If we couldn't parse the response properly, generate some default hashtags
|
||||
if not hashtags:
|
||||
hashtags = generate_default_hashtags(content, industry, hashtag_count)
|
||||
performance_predictions = generate_default_predictions(hashtags)
|
||||
|
||||
return hashtags, performance_predictions
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating hashtags: {e}")
|
||||
# Generate default hashtags as fallback
|
||||
hashtags = generate_default_hashtags(content, industry, hashtag_count)
|
||||
performance_predictions = generate_default_predictions(hashtags)
|
||||
return hashtags, performance_predictions
|
||||
|
||||
def generate_default_hashtags(content: str, industry: str, count: int) -> List[str]:
|
||||
"""Generate default hashtags when AI generation fails."""
|
||||
|
||||
# Extract keywords from content
|
||||
keywords = re.findall(r'\b\w+\b', content.lower())
|
||||
keywords = [k for k in keywords if len(k) > 3] # Filter out short words
|
||||
|
||||
# Industry-specific hashtags
|
||||
industry_hashtags = {
|
||||
"Technology": ["tech", "innovation", "digital", "future", "ai", "technews", "startup"],
|
||||
"Health & Wellness": ["health", "wellness", "fitness", "healthy", "wellbeing", "mindfulness"],
|
||||
"Fashion": ["fashion", "style", "trend", "outfit", "fashionista", "accessories"],
|
||||
"Food & Beverage": ["food", "foodie", "recipe", "cooking", "delicious", "foodporn"],
|
||||
"Travel": ["travel", "wanderlust", "adventure", "explore", "travelgram", "vacation"],
|
||||
"Education": ["education", "learning", "knowledge", "study", "student", "academic"],
|
||||
"Finance": ["finance", "money", "investing", "financial", "business", "wealth"],
|
||||
"Entertainment": ["entertainment", "fun", "music", "movie", "tv", "celebrity"],
|
||||
"Fitness": ["fitness", "workout", "gym", "exercise", "health", "training"],
|
||||
"Beauty": ["beauty", "makeup", "skincare", "beautytips", "glam", "beautylover"],
|
||||
"Home & Garden": ["home", "garden", "decor", "interior", "diy", "homemade"],
|
||||
"Automotive": ["car", "automotive", "vehicle", "driving", "cars", "auto"],
|
||||
"Real Estate": ["realestate", "property", "home", "housing", "realtor", "investment"],
|
||||
"Business": ["business", "entrepreneur", "success", "marketing", "smallbusiness", "startup"],
|
||||
"Art & Design": ["art", "design", "creative", "artist", "illustration", "designer"],
|
||||
"Sports": ["sports", "athlete", "game", "team", "competition", "winning"],
|
||||
"Parenting": ["parenting", "family", "kids", "children", "mom", "dad"],
|
||||
"Pets": ["pets", "dog", "cat", "animal", "petlover", "adoption"],
|
||||
"Other": ["trending", "viral", "popular", "mustsee", "recommended", "best"]
|
||||
}
|
||||
|
||||
# Get industry hashtags
|
||||
industry_tags = industry_hashtags.get(industry, industry_hashtags["Other"])
|
||||
|
||||
# Combine keywords and industry hashtags
|
||||
all_hashtags = list(set(keywords + industry_tags))
|
||||
|
||||
# Shuffle and select
|
||||
random.shuffle(all_hashtags)
|
||||
selected_hashtags = all_hashtags[:count]
|
||||
|
||||
return selected_hashtags
|
||||
|
||||
def generate_default_predictions(hashtags: List[str]) -> Dict[str, Dict[str, Any]]:
|
||||
"""Generate default performance predictions for hashtags."""
|
||||
|
||||
predictions = {}
|
||||
|
||||
for hashtag in hashtags:
|
||||
# Generate random but realistic predictions
|
||||
reach = random.randint(1000, 100000)
|
||||
engagement = round(random.uniform(0.5, 5.0), 1)
|
||||
competition = random.choice(["Low", "Medium", "High"])
|
||||
|
||||
predictions[hashtag] = {
|
||||
'reach': reach,
|
||||
'engagement': engagement,
|
||||
'competition': competition
|
||||
}
|
||||
|
||||
return predictions
|
||||
|
||||
def display_hashtag_results(
|
||||
hashtags: List[str],
|
||||
performance_predictions: Dict[str, Dict[str, Any]],
|
||||
placement: str
|
||||
):
|
||||
"""Display the generated hashtags and performance predictions."""
|
||||
|
||||
st.markdown("#### Generated Hashtags")
|
||||
|
||||
# Display hashtags
|
||||
hashtag_text = " ".join([f"#{hashtag}" for hashtag in hashtags])
|
||||
st.code(hashtag_text)
|
||||
|
||||
# Copy button
|
||||
if st.button("Copy All Hashtags", key="copy_hashtags_button"):
|
||||
st.code(hashtag_text)
|
||||
st.success("Copied to clipboard!")
|
||||
|
||||
# Save button
|
||||
if st.button("Save to Library", key="save_hashtags_button"):
|
||||
for hashtag in hashtags:
|
||||
if hashtag not in st.session_state.hashtag_data['saved_hashtags']:
|
||||
st.session_state.hashtag_data['saved_hashtags'].append(hashtag)
|
||||
st.success("Hashtags saved to your library!")
|
||||
|
||||
# Display placement suggestion
|
||||
st.markdown("#### Recommended Placement")
|
||||
|
||||
if placement == "End of Post":
|
||||
st.markdown("""
|
||||
**Place these hashtags at the end of your post:**
|
||||
|
||||
Add a line break after your content, then add the hashtags.
|
||||
""")
|
||||
st.code(hashtag_text)
|
||||
|
||||
elif placement == "Throughout Content":
|
||||
st.markdown("""
|
||||
**Weave these hashtags throughout your content:**
|
||||
|
||||
Integrate hashtags naturally within your sentences where they make sense.
|
||||
""")
|
||||
|
||||
# Create a sample with hashtags integrated
|
||||
sample_content = st.session_state.hashtag_data['content']
|
||||
words = sample_content.split()
|
||||
|
||||
# Insert hashtags at random positions
|
||||
for hashtag in hashtags[:3]: # Use first 3 hashtags
|
||||
if len(words) > 5:
|
||||
pos = random.randint(0, len(words) - 1)
|
||||
words.insert(pos, f"#{hashtag}")
|
||||
|
||||
sample_with_hashtags = " ".join(words)
|
||||
st.code(sample_with_hashtags)
|
||||
|
||||
else: # Both
|
||||
st.markdown("""
|
||||
**Use a combination of both approaches:**
|
||||
|
||||
1. Weave some hashtags naturally within your content
|
||||
2. Add the remaining hashtags at the end
|
||||
""")
|
||||
|
||||
# Create a sample with some hashtags integrated
|
||||
sample_content = st.session_state.hashtag_data['content']
|
||||
words = sample_content.split()
|
||||
|
||||
# Insert some hashtags at random positions
|
||||
for hashtag in hashtags[:2]: # Use first 2 hashtags
|
||||
if len(words) > 5:
|
||||
pos = random.randint(0, len(words) - 1)
|
||||
words.insert(pos, f"#{hashtag}")
|
||||
|
||||
sample_with_hashtags = " ".join(words)
|
||||
st.code(sample_with_hashtags)
|
||||
|
||||
# Add remaining hashtags at the end
|
||||
remaining_hashtags = " ".join([f"#{hashtag}" for hashtag in hashtags[2:]])
|
||||
st.markdown("**Add these at the end:**")
|
||||
st.code(remaining_hashtags)
|
||||
|
||||
# Display performance insights
|
||||
st.markdown("#### Performance Insights")
|
||||
|
||||
# Create a bar chart for reach predictions
|
||||
reach_data = {hashtag: data['reach'] for hashtag, data in performance_predictions.items()}
|
||||
|
||||
if reach_data:
|
||||
st.bar_chart(reach_data)
|
||||
|
||||
# Display detailed metrics
|
||||
st.markdown("##### Detailed Metrics")
|
||||
|
||||
for hashtag, metrics in performance_predictions.items():
|
||||
with st.expander(f"#{hashtag}"):
|
||||
col1, col2, col3 = st.columns(3)
|
||||
|
||||
with col1:
|
||||
st.metric("Reach", f"{metrics['reach']:,}")
|
||||
|
||||
with col2:
|
||||
st.metric("Engagement", f"{metrics['engagement']}%")
|
||||
|
||||
with col3:
|
||||
st.metric("Competition", metrics['competition'])
|
||||
@@ -0,0 +1,133 @@
|
||||
# Facebook Page About Generator
|
||||
|
||||
## Overview
|
||||
The Facebook Page About Generator is a powerful tool designed to help businesses and organizations create professional and engaging About sections for their Facebook Pages. It provides a comprehensive interface for crafting compelling content that effectively communicates brand identity, mission, and value proposition to visitors.
|
||||
|
||||
## Features
|
||||
|
||||
### Basic Information Management
|
||||
- **Business Details**: Input business name, industry, founding date, location, and contact information
|
||||
- **Mission Statement**: Create a concise and impactful mission statement
|
||||
- **Website Integration**: Add website URL and other online presence links
|
||||
- **Contact Information**: Include phone, email, and physical address
|
||||
|
||||
### Brand Voice & Tone
|
||||
- **Tone Selection**: Choose from professional, friendly, casual, formal, or humorous tones
|
||||
- **Brand Personality**: Define key personality traits that reflect your brand
|
||||
- **Target Audience**: Specify your primary audience demographics and interests
|
||||
- **Brand Values**: Highlight core values that guide your business
|
||||
|
||||
### Key Sections
|
||||
- **About Us/Our Story**: Share your company's history and journey
|
||||
- **Products/Services**: Highlight your offerings and their benefits
|
||||
- **Unique Selling Proposition**: Communicate what sets you apart
|
||||
- **Team/Leadership**: Showcase key team members and leadership
|
||||
- **Awards/Recognition**: Display achievements and accolades
|
||||
- **Customer Testimonials**: Share positive feedback from clients
|
||||
- **Call-to-Action**: Encourage visitors to take specific actions
|
||||
|
||||
### Preview & Export
|
||||
- **Live Preview**: See how your About section will appear before publishing
|
||||
- **Export Options**: Copy to clipboard or download as text file
|
||||
- **Format Validation**: Ensure your content meets Facebook's requirements
|
||||
- **SEO Optimization**: Get suggestions for better visibility
|
||||
|
||||
## How to Use
|
||||
|
||||
1. **Access the Generator**
|
||||
- Navigate to the Facebook Page About Generator in the AI Writer dashboard
|
||||
- Select "Create New About Section" to start
|
||||
|
||||
2. **Configure Basic Information**
|
||||
- Enter your business details
|
||||
- Define your mission statement
|
||||
- Add contact information
|
||||
|
||||
3. **Set Brand Voice & Tone**
|
||||
- Choose your preferred tone
|
||||
- Define brand personality traits
|
||||
- Specify target audience
|
||||
- List core brand values
|
||||
|
||||
4. **Customize Key Sections**
|
||||
- Toggle sections you want to include
|
||||
- Add custom content or generate with AI
|
||||
- Review and edit generated content
|
||||
|
||||
5. **Preview and Export**
|
||||
- Review the complete About section
|
||||
- Make final adjustments
|
||||
- Export or copy the content
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Creation
|
||||
- Keep descriptions concise and focused
|
||||
- Use clear, engaging language
|
||||
- Highlight unique aspects of your business
|
||||
- Include relevant keywords for SEO
|
||||
|
||||
### Brand Voice
|
||||
- Maintain consistent tone throughout
|
||||
- Align with your overall brand identity
|
||||
- Use language that resonates with your target audience
|
||||
- Avoid jargon unless industry-specific
|
||||
|
||||
### Section Organization
|
||||
- Prioritize most important information first
|
||||
- Use formatting for better readability
|
||||
- Include visual elements when appropriate
|
||||
- End with a clear call-to-action
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- Streamlit
|
||||
- Required Python packages:
|
||||
- streamlit
|
||||
- typing
|
||||
- datetime
|
||||
- json
|
||||
- logging
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Content Generation Fails**
|
||||
- Check your internet connection
|
||||
- Verify input parameters
|
||||
- Try reducing content length
|
||||
|
||||
2. **Export Problems**
|
||||
- Check available disk space
|
||||
- Verify write permissions
|
||||
- Ensure proper file naming
|
||||
|
||||
3. **Preview Issues**
|
||||
- Clear browser cache
|
||||
- Check for formatting errors
|
||||
- Verify all required fields are filled
|
||||
|
||||
## Future Updates
|
||||
|
||||
- Enhanced AI content generation
|
||||
- Industry-specific templates
|
||||
- Multi-language support
|
||||
- Advanced SEO recommendations
|
||||
- Integration with other social platforms
|
||||
- Analytics for About section performance
|
||||
- A/B testing capabilities
|
||||
- Custom section creation
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to improve the Facebook Page About Generator. Please follow these steps:
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
This module is licensed under the MIT License. See the LICENSE file for details.
|
||||
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Facebook Page About Generator Module
|
||||
|
||||
This module provides functionality to generate professional and engaging About sections
|
||||
for Facebook Pages. It helps businesses create compelling content that effectively
|
||||
communicates their brand identity, mission, and value proposition to visitors.
|
||||
"""
|
||||
|
||||
from .page_about_generator import write_fb_page_about
|
||||
|
||||
__all__ = ['write_fb_page_about']
|
||||
@@ -0,0 +1,649 @@
|
||||
"""
|
||||
Facebook Page About Generator Module
|
||||
|
||||
This module provides functionality to generate professional and engaging About sections
|
||||
for Facebook Pages. It helps businesses create compelling content that effectively
|
||||
communicates their brand identity, mission, and value proposition to visitors.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional, Union, Tuple
|
||||
from .....gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def write_fb_page_about():
|
||||
"""
|
||||
Generate a Facebook Page About section with various customization options.
|
||||
|
||||
This function provides a comprehensive interface for creating professional
|
||||
and engaging About sections for Facebook Pages with features like:
|
||||
- Basic information management
|
||||
- Brand voice and tone customization
|
||||
- Key sections configuration
|
||||
- Preview and export options
|
||||
"""
|
||||
|
||||
st.title("Facebook Page About Generator")
|
||||
st.markdown("""
|
||||
Create professional and engaging About sections for your Facebook Pages that effectively
|
||||
communicate your brand identity, mission, and value proposition to visitors.
|
||||
""")
|
||||
|
||||
# Initialize session state for form data
|
||||
if 'page_about_data' not in st.session_state:
|
||||
st.session_state.page_about_data = {
|
||||
# Basic Information
|
||||
'business_name': '',
|
||||
'industry': '',
|
||||
'founded_date': '',
|
||||
'location': '',
|
||||
'website': '',
|
||||
'phone': '',
|
||||
'email': '',
|
||||
'address': '',
|
||||
'mission_statement': '',
|
||||
|
||||
# Brand Voice & Tone
|
||||
'tone': 'professional',
|
||||
'brand_personality': [],
|
||||
'target_audience': '',
|
||||
'brand_values': [],
|
||||
|
||||
# Key Sections
|
||||
'include_about_us': True,
|
||||
'about_us_content': '',
|
||||
'include_products': True,
|
||||
'products_content': '',
|
||||
'include_usp': True,
|
||||
'usp_content': '',
|
||||
'include_team': False,
|
||||
'team_content': '',
|
||||
'include_awards': False,
|
||||
'awards_content': '',
|
||||
'include_testimonials': False,
|
||||
'testimonials_content': '',
|
||||
'include_cta': True,
|
||||
'cta_content': '',
|
||||
|
||||
# Content Length
|
||||
'content_length': 'standard',
|
||||
|
||||
# Generated Content
|
||||
'generated_content': '',
|
||||
'show_preview': False
|
||||
}
|
||||
|
||||
# Create tabs for different sections
|
||||
tab1, tab2, tab3, tab4 = st.tabs([
|
||||
"Basic Information",
|
||||
"Brand Voice & Tone",
|
||||
"Key Sections",
|
||||
"Preview & Export"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
render_basic_info_tab()
|
||||
|
||||
with tab2:
|
||||
render_brand_voice_tab()
|
||||
|
||||
with tab3:
|
||||
render_key_sections_tab()
|
||||
|
||||
with tab4:
|
||||
render_preview_export_tab()
|
||||
|
||||
# Generate button
|
||||
if st.button("Generate About Section", type="primary"):
|
||||
if validate_page_about_fields():
|
||||
with st.spinner("Generating your About section..."):
|
||||
about_content = generate_page_about()
|
||||
if about_content:
|
||||
st.session_state.page_about_data['generated_content'] = about_content
|
||||
st.success("About section generated successfully!")
|
||||
st.session_state.page_about_data['show_preview'] = True
|
||||
st.rerun()
|
||||
|
||||
def render_basic_info_tab():
|
||||
"""Render the basic information input fields."""
|
||||
|
||||
st.header("Basic Information")
|
||||
|
||||
# Business Name
|
||||
business_name = st.text_input(
|
||||
"Business/Organization Name",
|
||||
value=st.session_state.page_about_data['business_name'],
|
||||
help="Enter your business or organization name"
|
||||
)
|
||||
st.session_state.page_about_data['business_name'] = business_name
|
||||
|
||||
# Industry
|
||||
industry = st.text_input(
|
||||
"Industry/Category",
|
||||
value=st.session_state.page_about_data['industry'],
|
||||
help="Enter your industry or business category"
|
||||
)
|
||||
st.session_state.page_about_data['industry'] = industry
|
||||
|
||||
# Founded Date
|
||||
founded_date = st.text_input(
|
||||
"Founded Date",
|
||||
value=st.session_state.page_about_data['founded_date'],
|
||||
help="Enter when your business was founded (e.g., '2010' or 'January 2010')"
|
||||
)
|
||||
st.session_state.page_about_data['founded_date'] = founded_date
|
||||
|
||||
# Location
|
||||
location = st.text_input(
|
||||
"Location",
|
||||
value=st.session_state.page_about_data['location'],
|
||||
help="Enter your business location (city, state, country)"
|
||||
)
|
||||
st.session_state.page_about_data['location'] = location
|
||||
|
||||
# Website
|
||||
website = st.text_input(
|
||||
"Website URL",
|
||||
value=st.session_state.page_about_data['website'],
|
||||
help="Enter your website URL"
|
||||
)
|
||||
st.session_state.page_about_data['website'] = website
|
||||
|
||||
# Contact Information
|
||||
st.subheader("Contact Information")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
phone = st.text_input(
|
||||
"Phone Number",
|
||||
value=st.session_state.page_about_data['phone'],
|
||||
help="Enter your business phone number"
|
||||
)
|
||||
st.session_state.page_about_data['phone'] = phone
|
||||
|
||||
email = st.text_input(
|
||||
"Email Address",
|
||||
value=st.session_state.page_about_data['email'],
|
||||
help="Enter your business email address"
|
||||
)
|
||||
st.session_state.page_about_data['email'] = email
|
||||
|
||||
with col2:
|
||||
address = st.text_area(
|
||||
"Physical Address",
|
||||
value=st.session_state.page_about_data['address'],
|
||||
help="Enter your business physical address",
|
||||
height=100
|
||||
)
|
||||
st.session_state.page_about_data['address'] = address
|
||||
|
||||
# Mission Statement
|
||||
mission_statement = st.text_area(
|
||||
"Mission Statement",
|
||||
value=st.session_state.page_about_data['mission_statement'],
|
||||
help="Enter your business mission statement (1-2 sentences)",
|
||||
height=100
|
||||
)
|
||||
st.session_state.page_about_data['mission_statement'] = mission_statement
|
||||
|
||||
def render_brand_voice_tab():
|
||||
"""Render the brand voice and tone selection fields."""
|
||||
|
||||
st.header("Brand Voice & Tone")
|
||||
|
||||
# Tone Selection
|
||||
tone = st.selectbox(
|
||||
"Select Tone",
|
||||
options=['professional', 'friendly', 'casual', 'formal', 'humorous'],
|
||||
index=['professional', 'friendly', 'casual', 'formal', 'humorous'].index(
|
||||
st.session_state.page_about_data['tone']
|
||||
),
|
||||
help="Choose the tone for your About section"
|
||||
)
|
||||
st.session_state.page_about_data['tone'] = tone
|
||||
|
||||
# Brand Personality Traits
|
||||
st.subheader("Brand Personality Traits")
|
||||
|
||||
personality_options = [
|
||||
'Innovative', 'Reliable', 'Creative', 'Professional', 'Friendly',
|
||||
'Authoritative', 'Empathetic', 'Ambitious', 'Authentic', 'Dynamic',
|
||||
'Trustworthy', 'Passionate', 'Efficient', 'Eco-friendly', 'Luxurious'
|
||||
]
|
||||
|
||||
# Initialize brand_personality in session state if not present
|
||||
if 'brand_personality' not in st.session_state.page_about_data:
|
||||
st.session_state.page_about_data['brand_personality'] = []
|
||||
|
||||
# Create a multi-select for brand personality traits
|
||||
selected_traits = st.multiselect(
|
||||
"Select Brand Personality Traits (up to 5)",
|
||||
options=personality_options,
|
||||
default=st.session_state.page_about_data['brand_personality'],
|
||||
help="Choose up to 5 traits that best describe your brand personality"
|
||||
)
|
||||
|
||||
# Limit to 5 traits
|
||||
if len(selected_traits) > 5:
|
||||
st.warning("You can only select up to 5 traits. The first 5 will be used.")
|
||||
selected_traits = selected_traits[:5]
|
||||
|
||||
st.session_state.page_about_data['brand_personality'] = selected_traits
|
||||
|
||||
# Target Audience
|
||||
target_audience = st.text_area(
|
||||
"Target Audience",
|
||||
value=st.session_state.page_about_data['target_audience'],
|
||||
help="Describe your target audience (demographics, interests, needs)",
|
||||
height=100
|
||||
)
|
||||
st.session_state.page_about_data['target_audience'] = target_audience
|
||||
|
||||
# Brand Values
|
||||
st.subheader("Brand Values")
|
||||
|
||||
# Initialize brand_values in session state if not present
|
||||
if 'brand_values' not in st.session_state.page_about_data:
|
||||
st.session_state.page_about_data['brand_values'] = []
|
||||
|
||||
# Create a dynamic list for brand values
|
||||
brand_values = st.session_state.page_about_data['brand_values']
|
||||
|
||||
# Add new value
|
||||
new_value = st.text_input("Add a brand value", key="new_brand_value")
|
||||
if st.button("Add Value") and new_value:
|
||||
if new_value not in brand_values:
|
||||
brand_values.append(new_value)
|
||||
st.session_state.page_about_data['brand_values'] = brand_values
|
||||
st.rerun()
|
||||
|
||||
# Display and allow removal of existing values
|
||||
if brand_values:
|
||||
st.write("Current Brand Values:")
|
||||
for i, value in enumerate(brand_values):
|
||||
col1, col2 = st.columns([4, 1])
|
||||
with col1:
|
||||
st.write(f"{i+1}. {value}")
|
||||
with col2:
|
||||
if st.button("Remove", key=f"remove_value_{i}"):
|
||||
brand_values.pop(i)
|
||||
st.session_state.page_about_data['brand_values'] = brand_values
|
||||
st.rerun()
|
||||
else:
|
||||
st.info("No brand values added yet. Add at least one brand value.")
|
||||
|
||||
def render_key_sections_tab():
|
||||
"""Render the key sections configuration fields."""
|
||||
|
||||
st.header("Key Sections")
|
||||
|
||||
# Content Length
|
||||
content_length = st.selectbox(
|
||||
"Content Length",
|
||||
options=['brief', 'standard', 'detailed'],
|
||||
index=['brief', 'standard', 'detailed'].index(
|
||||
st.session_state.page_about_data['content_length']
|
||||
),
|
||||
help="Choose the length of the generated content"
|
||||
)
|
||||
st.session_state.page_about_data['content_length'] = content_length
|
||||
|
||||
# About Us Section
|
||||
st.subheader("About Us/Our Story")
|
||||
include_about_us = st.checkbox(
|
||||
"Include About Us Section",
|
||||
value=st.session_state.page_about_data['include_about_us'],
|
||||
help="Include a section about your company's history and journey"
|
||||
)
|
||||
st.session_state.page_about_data['include_about_us'] = include_about_us
|
||||
|
||||
if include_about_us:
|
||||
about_us_content = st.text_area(
|
||||
"Custom About Us Content (optional)",
|
||||
value=st.session_state.page_about_data['about_us_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['about_us_content'] = about_us_content
|
||||
|
||||
# Products/Services Section
|
||||
st.subheader("Products/Services")
|
||||
include_products = st.checkbox(
|
||||
"Include Products/Services Section",
|
||||
value=st.session_state.page_about_data['include_products'],
|
||||
help="Include a section about your products or services"
|
||||
)
|
||||
st.session_state.page_about_data['include_products'] = include_products
|
||||
|
||||
if include_products:
|
||||
products_content = st.text_area(
|
||||
"Custom Products/Services Content (optional)",
|
||||
value=st.session_state.page_about_data['products_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['products_content'] = products_content
|
||||
|
||||
# Unique Selling Proposition Section
|
||||
st.subheader("Unique Selling Proposition")
|
||||
include_usp = st.checkbox(
|
||||
"Include USP Section",
|
||||
value=st.session_state.page_about_data['include_usp'],
|
||||
help="Include a section highlighting what sets you apart"
|
||||
)
|
||||
st.session_state.page_about_data['include_usp'] = include_usp
|
||||
|
||||
if include_usp:
|
||||
usp_content = st.text_area(
|
||||
"Custom USP Content (optional)",
|
||||
value=st.session_state.page_about_data['usp_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['usp_content'] = usp_content
|
||||
|
||||
# Team/Leadership Section
|
||||
st.subheader("Team/Leadership")
|
||||
include_team = st.checkbox(
|
||||
"Include Team/Leadership Section",
|
||||
value=st.session_state.page_about_data['include_team'],
|
||||
help="Include a section about your team or leadership"
|
||||
)
|
||||
st.session_state.page_about_data['include_team'] = include_team
|
||||
|
||||
if include_team:
|
||||
team_content = st.text_area(
|
||||
"Custom Team/Leadership Content (optional)",
|
||||
value=st.session_state.page_about_data['team_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['team_content'] = team_content
|
||||
|
||||
# Awards/Recognition Section
|
||||
st.subheader("Awards/Recognition")
|
||||
include_awards = st.checkbox(
|
||||
"Include Awards/Recognition Section",
|
||||
value=st.session_state.page_about_data['include_awards'],
|
||||
help="Include a section about your awards and recognition"
|
||||
)
|
||||
st.session_state.page_about_data['include_awards'] = include_awards
|
||||
|
||||
if include_awards:
|
||||
awards_content = st.text_area(
|
||||
"Custom Awards/Recognition Content (optional)",
|
||||
value=st.session_state.page_about_data['awards_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['awards_content'] = awards_content
|
||||
|
||||
# Customer Testimonials Section
|
||||
st.subheader("Customer Testimonials")
|
||||
include_testimonials = st.checkbox(
|
||||
"Include Customer Testimonials Section",
|
||||
value=st.session_state.page_about_data['include_testimonials'],
|
||||
help="Include a section with customer testimonials"
|
||||
)
|
||||
st.session_state.page_about_data['include_testimonials'] = include_testimonials
|
||||
|
||||
if include_testimonials:
|
||||
testimonials_content = st.text_area(
|
||||
"Custom Testimonials Content (optional)",
|
||||
value=st.session_state.page_about_data['testimonials_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['testimonials_content'] = testimonials_content
|
||||
|
||||
# Call-to-Action Section
|
||||
st.subheader("Call-to-Action")
|
||||
include_cta = st.checkbox(
|
||||
"Include Call-to-Action Section",
|
||||
value=st.session_state.page_about_data['include_cta'],
|
||||
help="Include a call-to-action to encourage visitors to take specific actions"
|
||||
)
|
||||
st.session_state.page_about_data['include_cta'] = include_cta
|
||||
|
||||
if include_cta:
|
||||
cta_content = st.text_area(
|
||||
"Custom Call-to-Action Content (optional)",
|
||||
value=st.session_state.page_about_data['cta_content'],
|
||||
help="Enter custom content or leave blank for AI generation",
|
||||
height=150
|
||||
)
|
||||
st.session_state.page_about_data['cta_content'] = cta_content
|
||||
|
||||
def render_preview_export_tab():
|
||||
"""Render the preview and export options."""
|
||||
|
||||
st.header("Preview & Export")
|
||||
|
||||
# Show preview if content has been generated
|
||||
if st.session_state.page_about_data['show_preview'] and st.session_state.page_about_data['generated_content']:
|
||||
st.subheader("Preview")
|
||||
|
||||
# Toggle between mobile and desktop view
|
||||
view_mode = st.radio("View Mode", ["Desktop", "Mobile"])
|
||||
|
||||
if view_mode == "Desktop":
|
||||
st.markdown("""
|
||||
<div style='background-color: #f0f2f6; padding: 20px; border-radius: 10px;'>
|
||||
<h2 style='color: #1877F2;'>About</h2>
|
||||
<div style='white-space: pre-wrap;'>
|
||||
""", unsafe_allow_html=True)
|
||||
st.write(st.session_state.page_about_data['generated_content'])
|
||||
st.markdown("</div></div>", unsafe_allow_html=True)
|
||||
else:
|
||||
st.markdown("""
|
||||
<div style='max-width: 375px; margin: 0 auto; background-color: #f0f2f6; padding: 15px; border-radius: 10px;'>
|
||||
<h2 style='color: #1877F2; font-size: 18px;'>About</h2>
|
||||
<div style='white-space: pre-wrap; font-size: 14px;'>
|
||||
""", unsafe_allow_html=True)
|
||||
st.write(st.session_state.page_about_data['generated_content'])
|
||||
st.markdown("</div></div>", unsafe_allow_html=True)
|
||||
|
||||
# SEO Score
|
||||
seo_score = calculate_seo_score(st.session_state.page_about_data['generated_content'])
|
||||
st.subheader(f"SEO Score: {seo_score}/10")
|
||||
|
||||
if seo_score < 7:
|
||||
st.warning("Your About section could benefit from SEO improvements. Consider adding more keywords and optimizing your content.")
|
||||
|
||||
# Export options
|
||||
st.subheader("Export Options")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
if st.button("Copy to Clipboard"):
|
||||
st.code(st.session_state.page_about_data['generated_content'], language=None)
|
||||
st.success("Content copied to clipboard!")
|
||||
|
||||
with col2:
|
||||
if st.button("Download as Text"):
|
||||
download_page_about(st.session_state.page_about_data['generated_content'])
|
||||
else:
|
||||
st.info("Generate your About section to see a preview and export options.")
|
||||
|
||||
def validate_page_about_fields() -> bool:
|
||||
"""Validate the required fields for the page about generator."""
|
||||
|
||||
data = st.session_state.page_about_data
|
||||
|
||||
# Check required fields
|
||||
if not data['business_name']:
|
||||
st.error("Business/Organization Name is required.")
|
||||
return False
|
||||
|
||||
if not data['industry']:
|
||||
st.error("Industry/Category is required.")
|
||||
return False
|
||||
|
||||
if not data['mission_statement']:
|
||||
st.error("Mission Statement is required.")
|
||||
return False
|
||||
|
||||
if not data['target_audience']:
|
||||
st.error("Target Audience is required.")
|
||||
return False
|
||||
|
||||
if not data['brand_personality']:
|
||||
st.error("At least one Brand Personality Trait is required.")
|
||||
return False
|
||||
|
||||
if not data['brand_values']:
|
||||
st.error("At least one Brand Value is required.")
|
||||
return False
|
||||
|
||||
# Check if at least one section is included
|
||||
sections_included = (
|
||||
data['include_about_us'] or
|
||||
data['include_products'] or
|
||||
data['include_usp'] or
|
||||
data['include_team'] or
|
||||
data['include_awards'] or
|
||||
data['include_testimonials'] or
|
||||
data['include_cta']
|
||||
)
|
||||
|
||||
if not sections_included:
|
||||
st.error("At least one section must be included.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generate_page_about() -> Optional[str]:
|
||||
"""Generate the page about content using AI."""
|
||||
|
||||
try:
|
||||
data = st.session_state.page_about_data
|
||||
|
||||
# Prepare the prompt for the LLM
|
||||
prompt = f"""
|
||||
Create a Facebook Page About section for {data['business_name']}, a {data['industry']} business.
|
||||
|
||||
Basic Information:
|
||||
- Founded: {data['founded_date']}
|
||||
- Location: {data['location']}
|
||||
- Website: {data['website']}
|
||||
- Mission Statement: {data['mission_statement']}
|
||||
|
||||
Brand Voice & Tone:
|
||||
- Tone: {data['tone']}
|
||||
- Brand Personality Traits: {', '.join(data['brand_personality'])}
|
||||
- Target Audience: {data['target_audience']}
|
||||
- Brand Values: {', '.join(data['brand_values'])}
|
||||
|
||||
Content Length: {data['content_length']}
|
||||
|
||||
Include the following sections:
|
||||
"""
|
||||
|
||||
# Add sections to include
|
||||
if data['include_about_us']:
|
||||
prompt += f"""
|
||||
- About Us/Our Story: {data['about_us_content'] if data['about_us_content'] else 'Generate engaging content about the company history and journey'}
|
||||
"""
|
||||
|
||||
if data['include_products']:
|
||||
prompt += f"""
|
||||
- Products/Services: {data['products_content'] if data['products_content'] else 'Generate engaging content about the products or services offered'}
|
||||
"""
|
||||
|
||||
if data['include_usp']:
|
||||
prompt += f"""
|
||||
- Unique Selling Proposition: {data['usp_content'] if data['usp_content'] else 'Generate engaging content about what sets the business apart'}
|
||||
"""
|
||||
|
||||
if data['include_team']:
|
||||
prompt += f"""
|
||||
- Team/Leadership: {data['team_content'] if data['team_content'] else 'Generate engaging content about the team or leadership'}
|
||||
"""
|
||||
|
||||
if data['include_awards']:
|
||||
prompt += f"""
|
||||
- Awards/Recognition: {data['awards_content'] if data['awards_content'] else 'Generate engaging content about awards and recognition'}
|
||||
"""
|
||||
|
||||
if data['include_testimonials']:
|
||||
prompt += f"""
|
||||
- Customer Testimonials: {data['testimonials_content'] if data['testimonials_content'] else 'Generate engaging content with customer testimonials'}
|
||||
"""
|
||||
|
||||
if data['include_cta']:
|
||||
prompt += f"""
|
||||
- Call-to-Action: {data['cta_content'] if data['cta_content'] else 'Generate an engaging call-to-action'}
|
||||
"""
|
||||
|
||||
prompt += """
|
||||
The About section should be well-structured, engaging, and optimized for Facebook.
|
||||
Use appropriate formatting, emojis, and line breaks for better readability.
|
||||
Make sure the tone is consistent with the selected brand voice.
|
||||
Include relevant keywords for SEO optimization.
|
||||
"""
|
||||
|
||||
# Get response from LLM
|
||||
response = llm_text_gen(prompt)
|
||||
|
||||
if response:
|
||||
return response
|
||||
else:
|
||||
st.error("Failed to generate About section content. Please try again.")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating About section: {str(e)}")
|
||||
st.error("An error occurred while generating the About section. Please try again.")
|
||||
return None
|
||||
|
||||
def calculate_seo_score(content: str) -> int:
|
||||
"""Calculate a simple SEO score for the content."""
|
||||
|
||||
score = 5 # Start with a base score
|
||||
|
||||
# Check for keywords (simple implementation)
|
||||
keywords = ['about', 'mission', 'vision', 'values', 'services', 'products', 'team', 'contact']
|
||||
for keyword in keywords:
|
||||
if keyword.lower() in content.lower():
|
||||
score += 0.5
|
||||
|
||||
# Check for formatting
|
||||
if '\n\n' in content: # Paragraph breaks
|
||||
score += 1
|
||||
|
||||
if '*' in content or '_' in content: # Bold or italic formatting
|
||||
score += 1
|
||||
|
||||
# Check for length
|
||||
if len(content) > 500:
|
||||
score += 1
|
||||
|
||||
# Cap the score at 10
|
||||
return min(score, 10)
|
||||
|
||||
def download_page_about(content: str):
|
||||
"""Download the About section content as a text file."""
|
||||
|
||||
try:
|
||||
# Create a timestamp for the filename
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"facebook_page_about_{timestamp}.txt"
|
||||
|
||||
# Create a download button
|
||||
st.download_button(
|
||||
label="Download Text File",
|
||||
data=content,
|
||||
file_name=filename,
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error downloading About section: {str(e)}")
|
||||
st.error("An error occurred while downloading the About section. Please try again.")
|
||||
@@ -5,6 +5,7 @@ from lib.utils.content_generators import content_planning_tools, ai_writers
|
||||
from lib.utils.alwrity_utils import ai_social_writer
|
||||
from lib.utils.seo_tools import ai_seo_tools
|
||||
from lib.utils.settings_page import render_settings_page
|
||||
|
||||
# Import social media writer functions
|
||||
from lib.ai_writers.ai_facebook_writer.facebook_ai_writer import facebook_main_menu
|
||||
from lib.ai_writers.linkedin_ai_writer import linked_post_writer
|
||||
@@ -319,7 +320,7 @@ def setup_alwrity_ui():
|
||||
|
||||
# Define sub-menu items for AI Social Tools
|
||||
social_tools_submenu = {
|
||||
"Facebook": ("📘", lambda: facebook_post_writer()),
|
||||
"Facebook": ("📘", lambda: facebook_main_menu()),
|
||||
"LinkedIn": ("💼", lambda: linked_post_writer()),
|
||||
"Twitter": ("🐦", lambda: tweet_writer()),
|
||||
"Instagram": ("📸", lambda: insta_writer()),
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 946 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 694 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 879 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 779 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 673 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 591 KiB |
Reference in New Issue
Block a user