Plugin enhances WordPress REST API with additional fields, optimizations, relative URL support, and GA4 Popular Posts integration. Designed specifically for headless WordPress setups (Headless CMS) where WordPress serves as a backend API, while the frontend is built with modern frameworks like Astro, Next.js, Nuxt, or any other JavaScript framework.
- Perfect for headless WordPress architectures
- Optimized for modern frontend frameworks (especially Astro)
- Simplified URL management across environments
- Enhanced data structure for better frontend integration
- Built-in support for multilingual sites (Polylang)
author_data- Extended author information including:- ID, name, nicename
- Relative URL to author page
- Avatar URL
- Author description
featured_image_urls- All registered image sizes with URLsrelative_link- Post URL relative to site rootread_time- Estimated reading time (e.g., "5 min read")categories_data- Enhanced category information:- ID, name, slug
- Description and post count
- Parent category ID
- Relative URL to category archive
tags_data- Enhanced tag information:- ID, name, slug
- Description and post count
- Relative URL to tag archive
All URLs in the API response are converted to relative paths:
- Post permalinks
- Author page URLs
- Category archive URLs
- Tag archive URLs
- Featured image URLs
- Translation URLs (when Polylang is active)
This ensures consistent URL format across different environments (development, staging, production).
- Custom term ordering via
term_orderparameter - Works for both categories and tags
- Default ascending order for categories
- Example:
/wp-json/wp/v2/categories?orderby=term_order
When Polylang is active, adds:
translations_data- Available translations for:- Posts (with title, excerpt, status)
- Categories (with name and slug)
- Tags (with name and slug)
available_languages- List of site languages- Automatic language filtering in API requests
Configurable via admin panel:
- Anonymous Comments - Allow posting comments via REST API without authentication
- Comment Notifications - Automatic email notifications to moderators when new comments are created via REST API
Complete headless WordPress functionality:
- Frontend Redirect - Automatically redirects all visitors to your headless frontend application
- Admin Access - Users with
edit_postscapability can still access WordPress admin - API Access - REST API, GraphQL, WP-CLI, and CRON continue to work normally
- Path Preservation - URL paths are preserved during redirect (e.g.,
/blog/post-slug→https://frontend.com/blog/post-slug) - 301 Redirects - Permanent redirects for SEO
- No External Plugin Needed - Replaces standalone headless mode plugins
Fetch popular posts based on real Google Analytics 4 pageview data:
- Real Analytics Data - Posts ranked by actual pageviews from GA4
- Multilingual Support - Filter by language (Polylang integration)
- Configurable Period - 7, 14, 30, or 90 days
- Smart Caching - Configurable cache duration (1-24 hours)
- Service Account Auth - Secure JWT-based authentication with Google
- No Google SDK Required - Lightweight implementation using WordPress HTTP API
// Fetch posts with enhanced data
fetch('/wp-json/wp/v2/posts')
.then(res => res.json())
.then(posts => {
const post = posts[0];
// Relative URLs
console.log(post.relative_link); // "/blog/post-title"
console.log(post.author_data.url); // "/author/john-doe"
// Enhanced author data
console.log(post.author_data);
// {
// id: 1,
// name: "John Doe",
// nicename: "john-doe",
// slug: "john-doe",
// avatar: "/path/to/avatar.jpg",
// description: "Author bio...",
// url: "/author/john-doe"
// }
// Image sizes
console.log(post.featured_image_urls);
// {
// thumbnail: "/uploads/image-150x150.jpg",
// medium: "/uploads/image-300x200.jpg",
// large: "/uploads/image-1024x768.jpg",
// full: "/uploads/image.jpg"
// }
});// Custom term order for categories
fetch('/wp-json/wp/v2/categories?orderby=term_order')
.then(res => res.json())
.then(categories => {
// Response example:
// [
// {
// "id": 5,
// "count": 12,
// "description": "Main category",
// "link": "/category/main",
// "name": "Main Category",
// "slug": "main",
// "taxonomy": "category",
// "parent": 0,
// "term_order": 1
// },
// ...
// ]
});
// Same works for tags
fetch('/wp-json/wp/v2/tags?orderby=term_order')// Get post with translations
fetch('/wp-json/wp/v2/posts/123')
.then(res => res.json())
.then(post => {
// translations_data example:
// {
// "id": 123,
// "translations_data": {
// "en": {
// "id": 123,
// "title": "English Title",
// "slug": "english-title",
// "link": "/blog/english-title",
// "excerpt": "Post excerpt...",
// "status": "publish",
// "featured_image": 456
// },
// "pl": {
// "id": 124,
// "title": "Polski Tytuł",
// "slug": "polski-tytul",
// "link": "/pl/blog/polski-tytul",
// "excerpt": "Fragment wpisu...",
// "status": "publish",
// "featured_image": 457
// }
// }
// }
// Get category with translations
fetch('/wp-json/wp/v2/categories/45')
.then(res => res.json())
.then(category => {
// translations_data example:
// {
// "id": 45,
// "translations_data": {
// "en": {
// "id": 45,
// "name": "News",
// "slug": "news",
// "link": "/category/news"
// },
// "pl": {
// "id": 46,
// "name": "Aktualności",
// "slug": "aktualnosci",
// "link": "/pl/kategoria/aktualnosci"
// }
// }
// }
});
});
// Get all available languages
fetch('/wp-json/wp/v2/posts/123')
.then(res => res.json())
.then(post => {
console.log(post.available_languages); // ["en", "pl"]
});// Get 12 most popular posts from last 30 days (default)
fetch('/wp-json/wp/v2/posts/popular')
.then(res => res.json())
.then(data => {
// Response example:
// {
// "posts": [
// {
// "id": 123,
// "title": { "rendered": "Most Popular Article" },
// "slug": "most-popular-article",
// "link": "/blog/most-popular-article",
// "date": "2025-01-15T10:30:00+00:00",
// "pageviews": 1542,
// "featured_image_urls": { "thumbnail": "...", "medium": "...", "full": "..." },
// "excerpt": { "rendered": "Article excerpt..." },
// "categories_data": [{ "id": 5, "name": "News", "slug": "news" }],
// "lang": "en"
// },
// ...
// ],
// "total": 12,
// "period": "30d",
// "cached": true,
// "cached_at": "2025-01-20T08:00:00+00:00"
// }
});
// Get popular posts with custom parameters
fetch('/wp-json/wp/v2/posts/popular?limit=6&period=7d&lang=pl')
.then(res => res.json())
.then(data => {
// Returns 6 most popular Polish posts from last 7 days
console.log(data.posts);
});
// Available parameters:
// - limit: 1-50 (default: 12)
// - period: 7d, 14d, 30d, 90d (default: 30d)
// - lang: language slug, e.g., "en", "pl" (requires Polylang)To use the GA4 Popular Posts feature, you need to configure Google Analytics 4 access:
- Go to Google Cloud Console → Service Accounts
- Select your project (or create one)
- Click "Create Service Account"
- Give it a name (e.g., "WordPress GA4 Reader")
- Click "Create and Continue"
- Skip the optional steps and click "Done"
- Click on the newly created service account
- Go to "Keys" tab
- Click "Add Key" → "Create new key"
- Select "JSON" and click "Create"
- Save the downloaded JSON file
- Go to Google Analytics
- Navigate to Admin → Property Access Management
- Click "+" to add a new user
- Enter the service account email (from the JSON file:
client_email) - Set role to "Viewer"
- Click "Add"
- Go to WordPress Admin → SPOKO REST API
- Find "GA4 Popular Posts" section
- Enable the feature
- Enter your GA4 Property ID (numeric, e.g.,
123456789) - Paste the entire JSON credentials content
- Set cache duration (recommended: 6 hours)
- Save settings