New: AI SEO tools, Rich snippet, AI product description
This commit is contained in:
@@ -1 +1,7 @@
|
||||
https://pypi.org/project/textstat/
|
||||
https://github.com/greghub/website-launch-checklist
|
||||
https://github.com/marcobiedermann/search-engine-optimization
|
||||
https://developers.google.com/speed/docs/insights/v5/get-started
|
||||
https://developers.google.com/search/apis/indexing-api/v3/prereqs
|
||||
https://developer.chrome.com/docs/lighthouse/overview/#cli
|
||||
|
||||
|
||||
127
lib/ai_seo_tools/content_title_generator.py
Normal file
127
lib/ai_seo_tools/content_title_generator.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import time #Iwish
|
||||
import os
|
||||
import json
|
||||
import streamlit as st
|
||||
from tenacity import (
|
||||
retry,
|
||||
stop_after_attempt,
|
||||
wait_random_exponential,
|
||||
)
|
||||
import google.generativeai as genai
|
||||
|
||||
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
|
||||
def ai_title_generator():
|
||||
""" Use AI to personalize content title generation """
|
||||
st.title("✍️ Alwrity - AI Blog Title Generator")
|
||||
|
||||
# Input section
|
||||
with st.expander("**PRO-TIP** - Follow the steps below for best results.", expanded=True):
|
||||
col1, col2 = st.columns([5, 5])
|
||||
|
||||
with col1:
|
||||
input_blog_keywords = st.text_input(
|
||||
'**🔑 Enter main keywords of your blog!**',
|
||||
placeholder="e.g., AI tools, digital marketing, SEO",
|
||||
help="Use 2-3 words that best describe the main topic of your blog."
|
||||
)
|
||||
input_blog_content = st.text_area(
|
||||
'**📄 Copy/Paste your entire blog content.** (Optional)',
|
||||
placeholder="e.g., Content about the importance of AI in digital marketing...",
|
||||
help="Paste your full blog content here for more accurate title suggestions. This is optional."
|
||||
)
|
||||
|
||||
with col2:
|
||||
input_title_type = st.selectbox(
|
||||
'📝 Blog Type',
|
||||
('General', 'How-to Guides', 'Tutorials', 'Listicles', 'Newsworthy Posts', 'FAQs', 'Checklists/Cheat Sheets'),
|
||||
index=0
|
||||
)
|
||||
input_title_intent = st.selectbox(
|
||||
'🔍 Search Intent',
|
||||
('Informational Intent', 'Commercial Intent', 'Transactional Intent', 'Navigational Intent'),
|
||||
index=0
|
||||
)
|
||||
language_options = ["English", "Spanish", "French", "German", "Chinese", "Japanese", "Other"]
|
||||
input_language = st.selectbox(
|
||||
'🌐 Select Language',
|
||||
options=language_options,
|
||||
index=0,
|
||||
help="Choose the language for your blog title."
|
||||
)
|
||||
if input_language == "Other":
|
||||
input_language = st.text_input(
|
||||
'Specify Language',
|
||||
placeholder="e.g., Italian, Dutch",
|
||||
help="Specify your preferred language."
|
||||
)
|
||||
|
||||
# Generate Blog Title button
|
||||
if st.button('**Generate Blog Titles**'):
|
||||
with st.spinner("Generating blog titles..."):
|
||||
if input_blog_content == 'Optional':
|
||||
input_blog_content = None
|
||||
|
||||
if not input_blog_keywords and not input_blog_content:
|
||||
st.error('**🫣 Provide Inputs to generate Blog Titles. Either Blog Keywords OR content is required!**')
|
||||
else:
|
||||
blog_titles = generate_blog_titles(input_blog_keywords, input_blog_content, input_title_type, input_title_intent, input_language)
|
||||
if blog_titles:
|
||||
st.subheader('**👩🧕🔬 Go Rule search ranking with these Blog Titles!**')
|
||||
with st.expander("**Final - Blog Titles Output 🎆🎇🎇**", expanded=True):
|
||||
st.markdown(blog_titles)
|
||||
else:
|
||||
st.error("💥 **Failed to generate blog titles. Please try again!**")
|
||||
|
||||
|
||||
# Function to generate blog metadesc
|
||||
def generate_blog_titles(input_blog_keywords, input_blog_content, input_title_type, input_title_intent, input_language):
|
||||
""" Function to call upon LLM to get the work done. """
|
||||
# If keywords and content both are given.
|
||||
if input_blog_content and input_blog_keywords:
|
||||
prompt = f"""As a SEO expert, I will provide you with main 'blog keywords' and 'blog content'.
|
||||
Your task is write 5 SEO optimised blog titles, from given blog keywords and content.
|
||||
|
||||
Follow the below guidelines for generating the blog titles:
|
||||
1). As SEO expert, follow all best practises for SEO optimised blog titles.
|
||||
2). Your response should be optimised around given keywords and content.
|
||||
3). Optimise your response for web search intent {input_title_intent}.
|
||||
4). Optimise your response for blog type of {input_title_type}.
|
||||
5). Your blog titles should in {input_language} language.\n
|
||||
|
||||
blog keywords: '{input_blog_keywords}'\n
|
||||
blog content: '{input_blog_content}'
|
||||
"""
|
||||
elif input_blog_keywords and not input_blog_content:
|
||||
prompt = f"""As a SEO expert, I will provide you with main 'keywords' of a blog.
|
||||
Your task is write 5 SEO optimised blog titles from given blog keywords.
|
||||
|
||||
Follow the below guidelines for generating the blog titles:
|
||||
1). As SEO expert, follow all best practises for SEO optimised blog titles.
|
||||
2). Your response should be optimised around given keywords and content.
|
||||
3). Optimise your response for web search intent {input_title_intent}.
|
||||
4). Optimise your response for blog type of {input_title_type}.
|
||||
5). Your blog titles should in {input_language} language.\n
|
||||
|
||||
blog keywords: '{input_blog_keywords}'\n
|
||||
"""
|
||||
elif input_blog_content and not input_blog_keywords:
|
||||
prompt = f"""As a SEO expert, I will provide you with a 'blog content'.
|
||||
Your task is write 5 SEO optimised blog titles from given blog content.
|
||||
|
||||
Follow the below guidelines for generating the blog titles:
|
||||
1). As SEO expert, follow all best practises for SEO optimised blog titles.
|
||||
2). Your response should be optimised around given keywords and content.
|
||||
3). Optimise your response for web search intent {input_title_intent}.
|
||||
4). Optimise your response for blog type of {input_title_type}.
|
||||
5). Your blog titles should in {input_language} language.\n
|
||||
|
||||
blog content: '{input_blog_content}'\n
|
||||
"""
|
||||
|
||||
try:
|
||||
response = llm_text_gen(prompt)
|
||||
return response
|
||||
except Exception as err:
|
||||
st.error(f"Exit: Failed to get response from LLM: {err}")
|
||||
84
lib/ai_seo_tools/meta_desc_generator.py
Normal file
84
lib/ai_seo_tools/meta_desc_generator.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import time #Iwish
|
||||
import os
|
||||
import json
|
||||
import streamlit as st
|
||||
from tenacity import (
|
||||
retry,
|
||||
stop_after_attempt,
|
||||
wait_random_exponential,
|
||||
)
|
||||
import google.generativeai as genai
|
||||
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
|
||||
def metadesc_generator_main():
|
||||
|
||||
# Title and description
|
||||
st.title("✍️ Alwrity - AI Blog Meta Description Generator")
|
||||
|
||||
# Input section
|
||||
with st.expander("**PRO-TIP** - Read the instructions below. 🚀", expanded=True):
|
||||
col1, col2, space = st.columns([5, 5, 0.5])
|
||||
with col1:
|
||||
keywords = st.text_input("🔑 Target Keywords (comma-separated):",
|
||||
placeholder="e.g., content marketing, SEO, social media, online business",
|
||||
help="Enter your target keywords, separated by commas. 📝")
|
||||
|
||||
tone_options = ["Informative", "Engaging", "Humorous", "Intriguing", "Playful"]
|
||||
tone = st.selectbox("🎨 Desired Tone (optional):",
|
||||
options=["General"] + tone_options,
|
||||
help="Choose the overall tone you want for your meta description. 🎭")
|
||||
with col2:
|
||||
search_type = st.selectbox('🔍 Search Intent:',
|
||||
('Informational Intent', 'Commercial Intent', 'Transactional Intent', 'Navigational Intent'),
|
||||
index=0)
|
||||
|
||||
language_options = ["English", "Spanish", "French", "German", "Other"]
|
||||
language_choice = st.selectbox("🌐 Preferred Language:",
|
||||
options=language_options,
|
||||
help="Select the language for your meta description. 🗣️")
|
||||
if language_choice == "Other":
|
||||
language = st.text_input("Specify Other Language:",
|
||||
placeholder="e.g., Italian, Chinese",
|
||||
help="Enter your preferred language. 🌍")
|
||||
else:
|
||||
language = language_choice
|
||||
|
||||
# Generate Blog Title button
|
||||
if st.button('**✨ Generate Meta Description ✨**'):
|
||||
with st.spinner("Crafting your Meta descriptions... ⏳"):
|
||||
|
||||
# Validate input fields
|
||||
if not keywords:
|
||||
st.error('**🫣 Blog Keywords are required!**')
|
||||
else:
|
||||
blog_metadesc = generate_blog_metadesc(keywords, tone, search_type, language)
|
||||
if blog_metadesc:
|
||||
st.subheader('**🎉 Your SEO-Boosting Blog Meta Descriptions! 🚀**')
|
||||
with st.expander("**Final - Blog Meta Description Output 🎆🎇**", expanded=True):
|
||||
st.markdown(blog_metadesc)
|
||||
else:
|
||||
st.error("💥 **Failed to generate blog meta description. Please try again!**")
|
||||
|
||||
|
||||
# Function to generate blog metadesc
|
||||
def generate_blog_metadesc(keywords, tone, search_type, language):
|
||||
""" Function to call upon LLM to get the work done. """
|
||||
prompt = f"""
|
||||
Craft 3 engaging and SEO-friendly meta descriptions for a blog post based on the following details:
|
||||
|
||||
Blog Post Keywords: {keywords}
|
||||
Search Intent Type: {search_type}
|
||||
Desired Tone: {tone}
|
||||
Preferred Language: {language}
|
||||
|
||||
Output Format:
|
||||
|
||||
Respond with 3 compelling and concise meta descriptions, approximately 155-160 characters long, that incorporate the target keywords, reflect the blog post content, resonate with the target audience, and entice users to click through to read the full article.
|
||||
"""
|
||||
with st.spinner("Calling Gemini to craft 3 Meta descriptions for you... 💫"):
|
||||
try:
|
||||
response = llm_text_gen(prompt)
|
||||
return response
|
||||
except Exception as err:
|
||||
st.error(f"Exit: Failed to get response from LLM: {err}")
|
||||
115
lib/ai_seo_tools/twitter_opengraph_generator.py
Normal file
115
lib/ai_seo_tools/twitter_opengraph_generator.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import streamlit as st
|
||||
import openai
|
||||
from bs4 import BeautifulSoup
|
||||
import requests
|
||||
import os
|
||||
|
||||
# Set up OpenAI API key
|
||||
openai.api_key = os.getenv('OPENAI_API_KEY') # Assuming you have it in a .env file
|
||||
|
||||
# Placeholder function for web scraping the URL (to be replaced with your mechanism)
|
||||
def scrape_webpage(url):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response.raise_for_status() # Raise an exception for bad status codes
|
||||
soup = BeautifulSoup(response.content, 'html.parser')
|
||||
|
||||
# Extract the title
|
||||
title = soup.find('title').text.strip() if soup.find('title') else None
|
||||
|
||||
# Extract the description
|
||||
description = soup.find('meta', attrs={'name': 'description'})['content'] if soup.find('meta', attrs={'name': 'description'}) else None
|
||||
|
||||
# Extract the image URL
|
||||
image_url = soup.find('meta', attrs={'property': 'og:image'})['content'] if soup.find('meta', attrs={'property': 'og:image'}) else None
|
||||
|
||||
return title, description, image_url
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
st.error(f"An error occurred while scraping the webpage: {e}")
|
||||
return None, None, None
|
||||
|
||||
# Function to generate OpenGraph meta tags
|
||||
def generate_opengraph_meta_tags(url, html_content=None, title=None, description=None, image_url=None):
|
||||
ai_prompt = f"""
|
||||
Generate OpenGraph meta tags for a Twitter Card for the following webpage: {url}
|
||||
|
||||
Here is the HTML content of the page:
|
||||
```html
|
||||
{html_content}
|
||||
```
|
||||
|
||||
Optional Customizations:
|
||||
* Title: {title if title else "Infer from the page content"}
|
||||
* Description: {description if description else "Infer from the page content"}
|
||||
* Image URL: {image_url if image_url else "Infer from the page content"}
|
||||
|
||||
Best practices:
|
||||
- Title: Should be concise and informative.
|
||||
- Description: Provide a brief summary of the content.
|
||||
- Image URL: Use a high-quality image.
|
||||
- URL: Ensure the URL is correct.
|
||||
- Type: Specify the content type (e.g., article, website).
|
||||
- Site Name: Provide the name of the site.
|
||||
|
||||
Output the generated OpenGraph meta tags as a series of HTML meta tags in the following format:
|
||||
|
||||
<meta property="og:title" content="Extracted or provided title" />
|
||||
<meta property="og:description" content="Extracted or provided description" />
|
||||
<meta property="og:image" content="Extracted or provided image URL" />
|
||||
<meta property="og:url" content="{url}" />
|
||||
<meta property="og:type" content="Infer from the URL" />
|
||||
<meta property="og:site_name" content="Extract site name from the URL" />
|
||||
"""
|
||||
|
||||
response = openai.Completion.create(
|
||||
engine="text-davinci-003",
|
||||
prompt=ai_prompt,
|
||||
max_tokens=150
|
||||
)
|
||||
|
||||
return response.choices[0].text.strip()
|
||||
|
||||
# Function to display the Streamlit UI
|
||||
def display_ui():
|
||||
st.title('OpenGraph Meta Tags Generator for Twitter 🐦')
|
||||
st.write('Generate OpenGraph meta tags for Twitter cards with ease. Just provide a URL and let our tool do the rest!')
|
||||
|
||||
# User inputs
|
||||
url = st.text_input('Content URL', help="🔗 Paste the URL of the page you want to share on Twitter.", placeholder="e.g., https://example.com")
|
||||
title = st.text_input('Title (optional)', help="📝 Optionally, provide a custom title for your Twitter card.", placeholder="e.g., Amazing Blog Post")
|
||||
description = st.text_area('Description (optional)', help="✍️ Optionally, provide a custom description for your Twitter card.", placeholder="e.g., This blog post covers...")
|
||||
image_url = st.text_input('Image URL (optional)', help="📸 Optionally, provide a URL to an image for your Twitter card.", placeholder="e.g., https://example.com/image.jpg")
|
||||
|
||||
if st.button('Generate Meta Tags'):
|
||||
if url:
|
||||
# Scrape the webpage for missing information if not provided
|
||||
if not title or not description or not image_url:
|
||||
scraped_title, scraped_description, scraped_image_url = scrape_webpage(url)
|
||||
title = title or scraped_title
|
||||
description = description or scraped_description
|
||||
image_url = image_url or scraped_image_url
|
||||
|
||||
# Fetch HTML content
|
||||
html_content = requests.get(url).text
|
||||
|
||||
# Generate OpenGraph meta tags
|
||||
meta_tags = generate_opengraph_meta_tags(url, html_content=html_content, title=title, description=description, image_url=image_url)
|
||||
|
||||
st.subheader('Generated OpenGraph Meta Tags')
|
||||
st.code(meta_tags, language='html')
|
||||
else:
|
||||
st.error('Please provide a content URL.')
|
||||
|
||||
# Instructions and preview
|
||||
st.write('### Instructions')
|
||||
st.write('1. Enter the URL of the content you want to share on Twitter.')
|
||||
st.write('2. Optionally, provide a custom title, description, and image URL.')
|
||||
st.write('3. Click "Generate Meta Tags" to see the generated OpenGraph meta tags.')
|
||||
|
||||
st.write('### Preview')
|
||||
st.write('A preview of how the Twitter card will look with the generated meta tags will be shown here (Feature to be implemented).')
|
||||
|
||||
# Run the Streamlit UI
|
||||
if __name__ == '__main__':
|
||||
display_ui()
|
||||
Reference in New Issue
Block a user