Seo-Tool / app.py
mroccuper's picture
Update app.py
ba1880d verified
# -*- coding: utf-8 -*-
"""
SEO Blog Generator with Gemini 1.5 Pro API
Enhanced: Internal Links + Extra Keywords + HTML File Download + WordPress Optimization
New Features: SEO Score, Title Variations, Readability Analysis, Social Media Snippets, Citations, Uniqueness Check
"""
#pip install -r requirements.txt
import gradio as gr
import requests
import markdown2
import os
import re
from datetime import datetime
class BlogGenerator:
@staticmethod
def clean_output(content):
return re.sub(r'```html|```', '', content).strip()
@staticmethod
def call_gemini(prompt, api_key):
response = requests.post(
f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={api_key}",
json={"contents": [{"parts": [{"text": prompt}]}]},
headers={"Content-Type": "application/json"}
)
return BlogGenerator.clean_output(response.json()["candidates"][0]["content"]["parts"][0]["text"])
@staticmethod
def generate_meta(keyword, transcript, api_key):
prompt = f"""
Create an SEO-friendly meta title (max 60 chars) and meta description (max 160 chars) for a blog about {keyword}.
Use this content as reference: {transcript}
Format:
Title: ...
Description: ...
"""
return BlogGenerator.call_gemini(prompt, api_key)
@staticmethod
def generate_slug_tags(keyword, api_key):
prompt = f"""
Suggest a URL-friendly slug and 3-5 relevant blog tags for the topic: {keyword}.
Format:
Slug: ...
Tags: tag1, tag2, tag3...
"""
return BlogGenerator.call_gemini(prompt, api_key)
@staticmethod
def generate_schema(keyword, api_key):
prompt = f"""
Create JSON-LD structured data for an article about {keyword}, including FAQPage and HowTo if applicable.
"""
return BlogGenerator.call_gemini(prompt, api_key)
@staticmethod
def generate_faq(keyword, api_key):
prompt = f"""
Create 3-5 beginner-friendly FAQ questions and answers about {keyword}.
Requirements:
- Use question format "Q: [question]"
- Answer in 2-3 simple sentences
- Include the keyword naturally
- Format as HTML with <div class='faq-item'>
"""
return BlogGenerator.call_gemini(prompt, api_key)
@staticmethod
def generate_step_by_step(keyword, api_key):
prompt = f"""
Create a simple step-by-step guide about {keyword} for beginners.
Format:
<h2>{keyword}: A Simple Step-by-Step Guide</h2>
<ul><li>Item 1</li><li>Item 2</li></ul>
<ol><li><strong>Step 1:</strong> Start by...</li></ol>
"""
return BlogGenerator.call_gemini(prompt, api_key)
@staticmethod
def generate_blog(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key):
word_count = {
"Short": "800",
"Standard": "1500-1700",
"Long": "2000+"
}[length]
links_formatted = ""
if internal_links:
links = internal_links.split("\n")
links_formatted = "\n".join([f"- <a href='{link.strip()}'>{link.strip()}</a>" for link in links if link.strip()])
extra_keywords_list = ""
if extra_keywords:
keywords = extra_keywords.split("\n")
extra_keywords_list = ", ".join([kw.strip() for kw in keywords if kw.strip()])
prompt = f"""
Create an SEO-optimized beginner-friendly blog post about: {keyword}
Transcript: {transcript}
Requirements:
- POV: {pov}, Tone: {tone}
- Word Count: {word_count} words
- Structure:
- Engaging title with keyword
- First sentence as SEO meta description (max 160 chars)
- Short intro (~100 words)
- 3-5 H2 sections with bullet points and practical advice
- Short paragraphs (2-3 sentences)
- Keyword density ~1-2%
- HTML format only with WordPress Gutenberg compatibility
{f"- Naturally include these internal links: {links_formatted}" if links_formatted else ""}
{f"- Sprinkle naturally these extra keywords: {extra_keywords_list}" if extra_keywords_list else ""}
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Content Optimization Score
@staticmethod
def analyze_seo_score(content, keyword, api_key):
prompt = f"""
Analyze this blog content for SEO quality and provide a score from 0-100:
Keyword: {keyword}
Content: {content}
Provide a breakdown with these components:
- Keyword density score (0-20)
- Readability score (0-20)
- Structure score (0-20)
- Meta data score (0-20)
- Internal linking score (0-20)
Format:
Overall Score: XX/100
Keyword Density: XX/20 (explanation)
Readability: XX/20 (explanation)
Structure: XX/20 (explanation)
Meta Data: XX/20 (explanation)
Internal Linking: XX/20 (explanation)
Top 3 Improvement Suggestions:
1. ...
2. ...
3. ...
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Title Variations
@staticmethod
def generate_title_variations(keyword, transcript, api_key):
prompt = f"""
Generate 5 engaging and SEO-friendly title variations for a blog post about "{keyword}".
Use this content as reference: {transcript[:500]}
Requirements:
- Include the keyword naturally
- Keep each title under 60 characters
- Use a mix of question, how-to, and list-based titles
- Add emotional triggers where appropriate
- Ensure WordPress compatibility
Format:
1. [Title 1]
2. [Title 2]
3. [Title 3]
4. [Title 4]
5. [Title 5]
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Readability Analysis
@staticmethod
def analyze_readability(content, api_key):
prompt = f"""
Analyze the readability of this blog content:
{content[:2000]}...
Provide:
1. Estimated Flesch-Kincaid reading level
2. Average words per sentence
3. Percentage of complex words
4. Passive voice percentage
5. Overall readability score (0-100)
Specific suggestions to improve:
- 3 sentences that could be simplified
- Words that could be replaced with simpler alternatives
- Structure improvements for WordPress readability
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Social Media Snippets
@staticmethod
def generate_social_snippets(content, keyword, api_key):
prompt = f"""
Create social media post snippets promoting a blog about "{keyword}" for:
1. Twitter/X (max 280 chars, include hashtags)
2. Facebook (100-250 words with call to action)
3. LinkedIn (professional tone, 150-250 words)
4. Instagram (caption with relevant hashtags)
5. Pinterest (short description with SEO keywords)
Reference content:
{content[:1000]}...
Format each snippet ready for copy-paste into WordPress social sharing plugins.
Include emojis where appropriate.
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Citation Generator
@staticmethod
def generate_citations(keyword, api_key):
prompt = f"""
Generate 5 relevant citation sources for a blog about "{keyword}".
For each source provide:
1. Author name(s)
2. Publication title
3. Publication date (within last 2 years)
4. URL
5. Brief description of why this source is valuable
6. A formatted citation in APA style
Focus on authoritative sources like:
- Peer-reviewed journals
- Government publications
- Industry reports
- Expert blogs with high domain authority
Format in HTML ready for WordPress insertion.
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: Content Uniqueness Check
@staticmethod
def check_uniqueness(content, api_key):
prompt = f"""
Analyze this content for potential plagiarism or duplicate content issues:
{content[:3000]}...
Provide:
1. Uniqueness score (estimated percentage of original content)
2. Highlight 3-5 phrases that might be common or potentially duplicative
3. Suggestions to make the content more unique
4. WordPress-specific recommendations for avoiding duplicate content penalties
Note: This is an AI-based estimation and not a replacement for professional plagiarism detection tools.
"""
return BlogGenerator.call_gemini(prompt, api_key)
# New Feature: WordPress Optimization
@staticmethod
def format_for_wordpress(content, keyword, api_key):
prompt = f"""
Optimize this HTML content for WordPress:
{content}
Make these WordPress-specific adjustments:
1. Format headings with proper Gutenberg compatibility
2. Add <!-- wp:paragraph --> tags where appropriate
3. Optimize image placeholders with WordPress figure blocks
4. Format lists for proper WordPress display
5. Add Yoast SEO compatible meta tags
6. Ensure responsive design elements
7. Add jump links for table of contents
Keep the keyword "{keyword}" optimized throughout.
"""
return BlogGenerator.call_gemini(prompt, api_key)
def process_input(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key,
enable_wp_format, enable_title_variations, enable_seo_score, enable_readability,
enable_social_snippets, enable_citations, enable_uniqueness):
if not api_key:
return "⚠️ Please enter your Gemini API key", "", None
results = {}
# Generate main blog content
main_blog = BlogGenerator.generate_blog(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key)
results["main_blog"] = main_blog
# Generate standard components
results["faq_section"] = BlogGenerator.generate_faq(keyword, api_key)
results["steps_section"] = BlogGenerator.generate_step_by_step(keyword, api_key)
results["meta_data"] = BlogGenerator.generate_meta(keyword, transcript, api_key)
results["slug_tags"] = BlogGenerator.generate_slug_tags(keyword, api_key)
# Generate optional components based on user selection
if enable_wp_format:
results["wp_formatted"] = BlogGenerator.format_for_wordpress(main_blog, keyword, api_key)
if enable_title_variations:
results["title_variations"] = BlogGenerator.generate_title_variations(keyword, transcript, api_key)
if enable_seo_score:
results["seo_score"] = BlogGenerator.analyze_seo_score(main_blog, keyword, api_key)
if enable_readability:
results["readability"] = BlogGenerator.analyze_readability(main_blog, api_key)
if enable_social_snippets:
results["social_snippets"] = BlogGenerator.generate_social_snippets(main_blog, keyword, api_key)
if enable_citations:
results["citations"] = BlogGenerator.generate_citations(keyword, api_key)
if enable_uniqueness:
results["uniqueness"] = BlogGenerator.check_uniqueness(main_blog, api_key)
# Compile the final output
final_output = f"""
{results.get('wp_formatted', results['main_blog'])}
{results['steps_section']}
<h2>Common Questions About {keyword}</h2>
{results['faq_section']}
<hr>
<h2>πŸ”Ž SEO Metadata</h2>
<pre>{results['meta_data']}</pre>
<h2>πŸ”— URL Slug & Tags</h2>
<pre>{results['slug_tags']}</pre>
"""
# Add optional components to output
if enable_title_variations:
final_output += f"""
<h2>πŸ“ Title Variations</h2>
<pre>{results['title_variations']}</pre>
"""
if enable_seo_score:
final_output += f"""
<h2>πŸ“Š SEO Score Analysis</h2>
<pre>{results['seo_score']}</pre>
"""
if enable_readability:
final_output += f"""
<h2>πŸ“– Readability Analysis</h2>
<pre>{results['readability']}</pre>
"""
if enable_social_snippets:
final_output += f"""
<h2>πŸ“± Social Media Snippets</h2>
<div class="social-snippets">
{results['social_snippets']}
</div>
"""
if enable_citations:
final_output += f"""
<h2>πŸ“š Citations & References</h2>
<div class="citations">
{results['citations']}
</div>
"""
if enable_uniqueness:
final_output += f"""
<h2>πŸ” Content Uniqueness Analysis</h2>
<pre>{results['uniqueness']}</pre>
"""
# Generate file
filename = f"{keyword.replace(' ', '_')}_{datetime.now().strftime('%Y%m%d%H%M%S')}.html"
filepath = os.path.join("/tmp", filename)
with open(filepath, "w", encoding="utf-8") as f:
f.write(final_output)
return final_output, markdown2.markdown(final_output), filepath
# UI Implementation with new features
with gr.Blocks(theme=gr.themes.Soft(), title="Enhanced SEO Blog Generator for WordPress") as app:
gr.Markdown("""
# πŸš€ Enhanced SEO Blog Generator for WordPress
Generate SEO-optimized content with advanced features including WordPress compatibility!
""")
with gr.Row():
with gr.Column():
api_key = gr.Textbox(label="Gemini API Key", type="password", placeholder="Enter your API key")
keyword = gr.Textbox(label="Primary Keyword", placeholder="e.g., 'sourdough bread'")
pov = gr.Radio(label="Point of View", choices=["First Person", "Second Person", "Third Person"], value="Second Person")
tone = gr.Dropdown(
label="Blog Tone",
choices=["Neutral", "Engaging", "Professional", "Informative", "News", "Promotional", "Conversational", "Storytelling", "Educational", "How-to", "Review", "Humorous", "Casual", "Inspirational"],
value="Engaging"
)
length = gr.Radio(label="Content Length", choices=["Short", "Standard", "Long"], value="Standard")
transcript = gr.Textbox(label="Transcript/Notes", lines=6, placeholder="Paste your reference content...")
internal_links = gr.Textbox(label="Internal Links (one URL per line)", lines=4, placeholder="https://yourblog.com/article1\nhttps://yourblog.com/article2")
extra_keywords = gr.Textbox(label="Extra Keywords (one per line)", lines=4, placeholder="kefir health benefits\nhomemade kefir tips")
gr.Markdown("### πŸ†• Advanced Features")
with gr.Row():
with gr.Column():
enable_wp_format = gr.Checkbox(label="WordPress Formatting", value=True)
enable_title_variations = gr.Checkbox(label="Title Variations", value=True)
enable_seo_score = gr.Checkbox(label="SEO Score Analysis", value=True)
enable_readability = gr.Checkbox(label="Readability Analysis", value=True)
with gr.Column():
enable_social_snippets = gr.Checkbox(label="Social Media Snippets", value=True)
enable_citations = gr.Checkbox(label="Citations & References", value=True)
enable_uniqueness = gr.Checkbox(label="Content Uniqueness Check", value=True)
btn = gr.Button("Generate WordPress-Ready Blog", variant="primary")
with gr.Column():
tabs = gr.Tabs()
with tabs:
with gr.TabItem("Preview"):
html_output = gr.HTML(label="Full SEO Article Preview")
with gr.TabItem("Markdown"):
md_output = gr.Code(label="Markdown Version", language="markdown")
with gr.TabItem("Download"):
file_output = gr.File(label="⬇️ Download HTML File")
gr.Markdown("""
### WordPress Import Instructions
1. Download the HTML file
2. In WordPress, create a new post
3. Click the three dots in the top-right and select "Code Editor"
4. Paste the HTML content
5. Switch back to "Visual Editor" to make any final adjustments
6. Update your meta data using Yoast or other SEO plugins
""")
btn.click(
fn=process_input,
inputs=[
transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key,
enable_wp_format, enable_title_variations, enable_seo_score, enable_readability,
enable_social_snippets, enable_citations, enable_uniqueness
],
outputs=[html_output, md_output, file_output]
)
app.launch(share=True)