Skip to content

astbnboy/seo-blog-pipeline

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

seo-blog-pipeline

An open-source, automated WordPress SEO blog content pipeline. It rotates through configurable content silos, researches low-competition questions using SERP data, deduplicates against a local CSV topic ledger, generates an answer-first draft post, publishes to WordPress via REST API, and logs every run for topic tracking and backlink prospecting.

No credentials, no proprietary business logic, no hard-coded site names. Everything is configurable through a single JSON file and standard environment variables.


What it does

  1. Reads your list of content silos (categories) from config.json and determines which category is next in the rotation.
  2. Queries a SERP provider (Apify by default, swappable) for People-Also-Ask questions in that category.
  3. Filters out questions already in ledger/topic-ledger.csv.
  4. Picks the lowest-competition uncovered question as the post topic.
  5. (Optional) Finds a relevant YouTube video to embed.
  6. Provides a prompt structure for generating an answer-first post with FAQ and optional YMYL (Your Money or Your Life) scaffolding — citations + disclaimer.
  7. Verifies every internal slug you plan to link resolves to a live WordPress post before the post is submitted.
  8. Uploads a featured image with alt text and creates the post via the WordPress REST API (as draft or published, your choice).
  9. Appends a row to ledger/topic-ledger.csv and any external citation domains to ledger/backlink-opportunities.csv.

Requirements

  • Python 3.9+
  • pip install requests
  • A WordPress site (self-hosted or WordPress.com Business) with the REST API enabled and an Application Password created under your user profile.
  • An Apify account and API token for SERP research. Free tier is sufficient for low-volume usage. You can replace Apify with any SERP data source by editing dispatch_serp_query() in scripts/serp_research.py.

Installation

git clone https://github.com/your-org/seo-blog-pipeline.git
cd seo-blog-pipeline
pip install requests
cp config.example.json config.json
# Edit config.json with your settings

Configuration

Edit config.json. Key fields:

Field Description
site_url Base URL of your WordPress site
categories Array of silo objects with name and optional ymyl flag
rotation_strategy "sequential" or "random"
target_word_count Approximate length of generated posts
publish_status "draft", "publish", or "private"
serp.provider "apify" (default) or your custom provider name
serp.actor_id Apify actor ID for Google SERP scraping
ledger.topics_csv Path to topic ledger CSV
ledger.backlinks_csv Path to backlink opportunities CSV
image.provider "dalle", "pexels", "stable-diffusion", or "none"

See config.example.json for the full annotated structure.


Credentials — environment variables

Never put credentials in config.json or on the command line.

Set these before running:

export WP_URL="https://yoursite.com"
export WP_USER="your_wp_username"
export WP_APP_PASSWORD="xxxx xxxx xxxx xxxx xxxx xxxx"
export APIFY_TOKEN="apify_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export YOUTUBE_API_KEY="AIza..."   # optional, only if embed_youtube is true

On Windows (PowerShell):

$env:WP_URL            = "https://yoursite.com"
$env:WP_USER           = "your_wp_username"
$env:WP_APP_PASSWORD   = "xxxx xxxx xxxx xxxx xxxx xxxx"
$env:APIFY_TOKEN       = "apify_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

For persistent configuration on Windows use System Properties > Environment Variables. On Linux/macOS add exports to ~/.profile or use a secrets manager such as direnv.


Usage

Research the next topic

python scripts/serp_research.py --category "personal-finance" --config config.json

Add --dry-run to preview without writing to the ledger.

Check internal slugs before publishing

python scripts/wp_publish.py check-slugs \
  --slugs "best-savings-accounts,emergency-fund-guide,debt-snowball-method"

Exits with code 1 and lists any slug that does not resolve to a live post.

Publish a post

python scripts/wp_publish.py publish \
  --title "Why an Emergency Fund Matters More Than Investing" \
  --content post_body.html \
  --category "personal-finance" \
  --image featured.jpg \
  --image-alt "Glass jar labeled emergency fund sitting on a wooden desk"

Inspect the ledger

python scripts/topic_ledger.py --list-topics --config config.json
python scripts/topic_ledger.py --next-category --config config.json

Scheduling

cron (Linux / macOS)

Add to your crontab (crontab -e):

0 7 * * 2,4 cd /path/to/seo-blog-pipeline && bash run_pipeline.sh >> logs/pipeline.log 2>&1

Windows Task Scheduler

Create a Basic Task triggered Weekly (e.g. Tuesday and Thursday, 07:00) with the action powershell.exe -NonInteractive -File C:\path\to\run_pipeline.ps1. Set WP_URL, WP_USER, WP_APP_PASSWORD, and APIFY_TOKEN as System environment variables so the scheduled process can read them.


Ledger files

Both CSV files are auto-created on first use.

ledger/topic-ledger.csv columns: timestamp, category, topic, post_id, slug, status

ledger/backlink-opportunities.csv columns: timestamp, domain, anchor_context, post_id, category


Disclaimer

This tool publishes content to your WordPress site automatically. You are responsible for reviewing drafts before they go live (set "publish_status": "draft" during initial setup), ensuring generated content meets your editorial standards, and complying with the terms of service of any SERP data provider or API you use. The authors of this repository make no warranties about search ranking outcomes.


License

MIT License. See LICENSE file.

About

Config-driven WordPress SEO content pipeline — research, draft, and publish posts on a schedule.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages