A smart Streamlit application that discovers internal linking opportunities for Ghost CMS websites by analyzing article tags, content relationships, and semantic relevance.
- Extracts tags from Ghost CMS meta tags
- Parses schema.org JSON-LD markup
- Identifies article keywords and topics
- Builds content relationship maps
- Tag Overlap Analysis (70%): Direct tag matching between articles
- URL Path Similarity (30%): Keyword similarity in URL structure
- Combined relevance score for accurate recommendations
- Outbound Opportunities: Pages your article should link to
- Inbound Opportunities: Pages that should link to your article
- Detailed scoring breakdown
- Export results as CSV
- Clean, intuitive Streamlit UI
- Real-time progress tracking
- Multiple result views (table + detailed)
- Actionable recommendations
- Python 3.9+
- pip or conda
- Ghost CMS website with sitemap.xml
# Clone the repository
git clone https://github.com/madusankapremaratne/backlink-analyzer-ghost.git
cd backlink-analyzer-ghost
# Install dependencies
pip install -r requirements.txt
# Run the app
streamlit run app.py# Create virtual environment (optional)
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Run locally
streamlit run app.pyVisit http://localhost:8501 in your browser.
Your sitemap is typically located at:
https://your-domain.com/sitemap.xml
Paste the full URL of the article you want to analyze:
https://your-domain.com/new-article-title/
- Low (0-30%): Broad analysis, many suggestions
- Medium (30-50%): Balanced recommendations
- High (50-100%): Highly targeted suggestions
Start with 30% and adjust based on results.
The app will:
- Fetch all URLs from your sitemap
- Extract tags from each article
- Calculate relevance scores
- Display recommendations
- Outbound: Pages to link FROM your new article
- Inbound: Pages to link TO your new article
- Export as CSV for implementation
Create a .streamlit/secrets.toml file for sensitive data:
[connections]
database_url = "your-database-url"
# Add any other secrets hereEdit app.py to customize:
# Adjust default relevance score
DEFAULT_RELEVANCE_SCORE = 30
# Customize timeout
DEFAULT_TIMEOUT = 5
# Add/remove common words
COMMON_WORDS = {
'index', 'page', 'article', ...
}The app extracts tags from three sources:
-
Meta Keywords Tag
<meta name="keywords" content="seo, ghost cms, blogging">
-
Schema.org JSON-LD
{ "@context": "https://schema.org", "keywords": ["seo", "ghost cms"] } -
HTML Tag Links
<a class="tag-link">#seo</a>
Relevance Score = (Tag Score × 0.7) + (Path Score × 0.3)
Tag Score = 30 + (Common Tags × 25), capped at 100
Path Score = Jaccard Similarity of URL words
Article A tags: [seo, ghost cms, blogging]
Article B tags: [seo, content marketing]
- Common tags:
[seo](1 match) - Tag Score: 30 + (1 × 25) = 55%
- Path Score: ~10% (minimal URL overlap)
- Final Score: (55 × 0.7) + (10 × 0.3) = 41%
-
Push to GitHub
git push origin main
-
Go to share.streamlit.io
- Sign in with GitHub
- Click "New app"
- Select your repository, branch, and
app.py - Deploy!
Live URL: https://your-app-name.streamlit.app
- Connect GitHub repository
- Railway auto-detects and deploys
- Custom domain support
- Auto-scaling included
Cost: $5-20/month
# Build image
docker build -t backlink-analyzer .
# Run locally
docker run -p 8501:8501 backlink-analyzer
# Deploy to DigitalOcean App Platform
# (See Dockerfile for deployment config)See DEPLOYMENT.md for detailed instructions.
- Domain: example.com
- Sitemap URLs: 150 articles
- New Article Tags:
[seo, internal linking, ghost cms] - Relevance Threshold: 30%
Outbound Opportunities (16 found)
| Title | Score | Common Tags |
|---|---|---|
| SEO Best Practices | 80% | seo, ghost cms |
| Link Building Guide | 65% | internal linking, seo |
| Ghost CMS Setup | 55% | ghost cms |
Inbound Opportunities (12 found)
| Title | Score | Common Tags |
|---|---|---|
| Content Strategy Guide | 75% | seo, content marketing |
| Blogging Tips | 60% | blogging, ghost cms |
Problem: All articles show 0 tags
Solutions:
- Verify Ghost CMS SEO settings
- Check meta tag configuration
- Ensure meta tags are in HTML head
- Verify page is publicly accessible
Problem: Few linking opportunities found
Solutions:
- Add more tags to your articles
- Use consistent tag naming
- Lower the relevance threshold
- Ensure tags are semantically related
Problem: "Request timeout" errors during analysis
Solutions:
- Increase fetch timeout in Advanced Options
- Check server response times
- Verify internet connection
- Reduce number of URLs analyzed
Problem: Streamlit crashes or freezes
Solutions:
- Check logs in terminal
- Reduce number of URLs
- Restart the app
- Update dependencies:
pip install --upgrade -r requirements.txt
-
Standardize Tags
- Use consistent naming (singular/plural)
- Create a tag taxonomy
- Document tag usage
-
Add Rich Metadata
<meta name="keywords" content="primary, secondary, topic"> <meta name="description" content="Article summary">
-
Implement Schema.org
{ "@type": "Article", "keywords": ["topic1", "topic2"], "description": "Article summary" }
-
Link Strategically
- Focus on top 3-5 outbound links per article
- Use descriptive anchor text
- Link to semantically related content
-
Maintain Site Structure
- Organize by topic clusters
- Respect content hierarchy
- Keep silo structure intact
-
Monitor Results
- Track ranking improvements
- Monitor click-through rates
- Adjust strategy based on metrics
Contributions are welcome! Here's how to contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone repository
git clone https://github.com/yourusername/backlink-analyzer-ghost.git
cd backlink-analyzer-ghost
# Create virtual environment
python -m venv venv
source venv/bin/activate
# Install dev dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Run tests
pytest tests/
# Format code
black app.py
# Lint
flake8 app.py- Add support for multiple sitemap formats
- Implement content clustering analysis
- Add competitor linking analysis
- Support for other CMS platforms (WordPress, Webflow)
- Machine learning-based relevance scoring
- API endpoint for programmatic access
- Batch analysis for multiple articles
- Custom tag weighting system
A: The app can handle 100-500+ URLs depending on server resources. Start with smaller sitemaps and scale up.
A: Not currently, but we're working on WordPress support. Plugins are welcome!
A: Yes! It's MIT licensed. See LICENSE file for details.
A: ~70-80% accuracy. Always manually review suggestions before implementing.
A: Not built-in, but you can use Streamlit Cloud scheduling or set up cron jobs with the app API.
- No data is stored or logged
- URLs are only accessed with explicit permission
- No authentication required for local use
- HTTPS recommended for production
MIT License - see LICENSE file for details
Madusanka Premaratne
- GitHub: @madusankapremaratne
- Email: rmmpremaratne@gmail.com
- Streamlit for the amazing framework
- Ghost CMS for the platform inspiration
- All contributors and users
Need help?
- Check the Troubleshooting section
- Open an Issue
- Start a Discussion
- Email: rmmpremaratne@gmail.com
Star this repo ⭐ if you find it helpful!
Last Updated: 2025