Last active
October 17, 2025 19:58
-
-
Save wojtekadams/4e799c96554e170ac2ad24c3f012e4f4 to your computer and use it in GitHub Desktop.
This Python script connects to the Ghost Admin API, retrieves all blog posts in batches, and automatically adds a specified tag to each post that doesn’t already have it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import jwt | |
| import time | |
| import requests | |
| # Instalation | |
| ## python3 -m venv ~/python-dev-env | |
| ## source ~/python-dev-env/bin/activate | |
| ## pip install requests PyJWT | |
| ## download ghost_cms_add_tag.py | |
| ## edit ghost_cms_add_tag.py -> add url, tag and admin key | |
| # Configuration | |
| api_url = "https://yourblog.com/ghost/api/admin" | |
| admin_key = "YOUR_ADMIN_API_KEY" | |
| new_tag = "wojtekadams_tag" | |
| # JWT token generation | |
| key_id, secret = admin_key.split(":") | |
| iat = int(time.time()) | |
| header = {"alg": "HS256", "kid": key_id} | |
| payload = {"iat": iat, "exp": iat + 5 * 60, "aud": "/admin/"} | |
| token = jwt.encode(payload, bytes.fromhex(secret), algorithm="HS256", headers=header) | |
| headers = {"Authorization": f"Ghost {token}"} | |
| # Fetch all posts with pagination | |
| all_posts = [] | |
| page_number = 1 | |
| while True: | |
| r = requests.get(f"{api_url}/posts/?limit=100&page={page_number}", headers=headers) | |
| r.raise_for_status() | |
| posts = r.json()["posts"] | |
| if not posts: | |
| break | |
| all_posts.extend(posts) | |
| print(f"Fetching page {page_number} ({len(all_posts)} posts total)") | |
| page_number += 1 | |
| print(f"Found {len(all_posts)} posts in total") | |
| # Add a tag to each post if missing | |
| for post in all_posts: | |
| tags = post.get("tags", []) | |
| tag_names = [t["name"] for t in tags if "name" in t] | |
| if new_tag not in tag_names: | |
| tags.append({"name": new_tag}) | |
| post_data = { | |
| "posts": [{ | |
| "id": post["id"], | |
| "updated_at": post["updated_at"], | |
| "tags": tags | |
| }] | |
| } | |
| update = requests.put(f"{api_url}/posts/{post['id']}/", headers=headers, json=post_data) | |
| if update.ok: | |
| print(f"Added tag '{new_tag}' to post: {post['title']}") | |
| else: | |
| print(f"Error updating post {post['title']}: {update.text}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment