=== Blog Sync for WeblySEO ===
Contributors: overstartup
Tags: ai, content, blog, seo, sync
Stable tag: 1.4.13
Requires at least: 5.0
Tested up to: 7.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Sync WeblySEO AI drafts to WordPress via API and webhooks - posts, images, and SEO meta.

== Description ==

Blog Sync for WeblySEO connects your WordPress site to the **WeblySEO** platform. You configure an API base URL, API key, and webhook secret in WordPress. Content is authored and finalized in WeblySEO; WordPress receives events and creates or updates posts, downloads images to the Media Library when applicable, and can sync SEO meta for **Yoast SEO** and **Rank Math** when those plugins are active.

### What the plugin does today

*   **Admin drafts screen:** Top-level menu **WeblySEO Sync** (page title “WeblySEO Blog Sync”) with **Content Sync** submenu — lists drafts from the WeblySEO Content API (server-rendered list with search and pagination). Each row can link out to the WeblySEO web app to continue editing (`AIGenerator` URL with domain and draft id).
*   **Settings (in-page modal):** API Base URL, API Key, Webhook URL (read-only), Webhook Secret; **Test Connection** and **Save Settings** use authenticated admin AJAX.
*   **Health check tab:** WordPress and PHP version checks, whether API options are set, and whether the plugin’s drafts database table exists. API “reachability” is reflected when you use Test Connection on valid credentials.
*   **Incoming webhooks:** `admin-ajax.php?action=weblyseo_blog_sync_webhook` — secured with header `X-Webhook-Secret` matching your stored secret. Handled events include `content.generated` (JSON from `downloadUrl` + optional WP post create/update), `ready.published` / `content.ready` (full publish pipeline: post create/update, report CMS post id, mark draft CMS-done in WeblySEO), `draft.finalized` (logged), `test`, and `get_categories` / `cms.get_categories` (returns WordPress categories for remote callers — uses core `get_categories()`, not the WeblySEO REST API).
*   **Outbound WeblySEO Content API (authenticated):** Test connection, list drafts, get one draft (to resolve existing WordPress post id when the webhook payload and local map do not), post CMS completion, and update stored WordPress post id on the draft. Optional `wp_remote_get` to the `downloadUrl` from `content.generated` payloads (URL is provided by WeblySEO, not a fixed path).
*   **Multilingual helpers:** When language data is present, the plugin can set **Polylang** language on the post if available, and set **WPML** language metadata when WPML is detected.
*   **Optional license overlay:** Frontend CSS for image attribution can be enabled via options (off by default in line with directory guidelines where applicable).

### What this plugin does *not* do

*   It does **not** run topic generation or the full AI editor inside WordPress — that work stays on **weblyseo.com** (or your configured API base). The plugin is sync and admin glue, not a replacement for the WeblySEO app.

### How it works

1.  **Install and activate** the plugin.
2.  **Open** **WeblySEO Sync** → **Content Sync** and open **Settings**.
3.  **Enter** your WeblySEO API Base URL and API Key; set a **Webhook Secret**; save. Copy the **Webhook URL** into your WeblySEO project/domain webhook settings.
4.  **Create and publish** (or generate) content in WeblySEO as you normally do.
5.  **WordPress** receives webhooks, creates or updates posts, syncs media and meta where implemented, and calls back to WeblySEO to store the WordPress post id and mark CMS completion when appropriate.

== Installation ==

1. Upload the plugin files to the `/wp-content/plugins/weblyseo-blog-sync` directory, or install the plugin through the WordPress plugins screen directly.
2. Activate the plugin through the 'Plugins' screen in WordPress.
3. Go to **WeblySEO Sync** → **Content Sync** in wp-admin, open **Settings**, and set **API Base URL**, **API Key**, and **Webhook Secret**.
4. In WeblySEO, configure the **webhook URL** WordPress shows you, and the same **secret** (sent as `X-Webhook-Secret` on requests).

== Frequently Asked Questions ==

= Do I need a WeblySEO account? =
Yes. You need a WeblySEO account, API access, and an API key. Sign up at https://weblyseo.com

= Is it compatible with SEO plugins? =
The integration maps meta and related fields for **Yoast SEO** and **Rank Math** when those plugins are active, based on the payload WeblySEO sends.

= Does it handle images? =
Yes, when the webhook or content flow includes image URLs, the plugin can sideload images into the **Media Library** (behavior depends on payload and WeblySEO settings such as download vs hotlink).

= Does the plugin call WeblySEO when I only browse the site frontend? =
No. Outbound WeblySEO API calls happen from **wp-admin** (drafts page, test connection, etc.) and from **webhook processing** (e.g. loading `downloadUrl`, or resolving/updating drafts). The webhook endpoint is on `admin-ajax.php` and is called by WeblySEO’s servers when you configure it.

== Source Code & Third-party Libraries ==

This plugin includes the following bundled third-party libraries. All are GPL-compatible.

* **Bootstrap 5.3.8** (CSS & JS) — MIT License. Source: https://github.com/twbs/bootstrap
* **Font Awesome 6.4.0** (CSS & webfonts) — Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT. Source: https://github.com/FortAwesome/Font-Awesome

All plugin PHP and JS source code included here is unminified and human-readable.

== External Services ==

This plugin talks to **WeblySEO** and, for some flows, to URLs WeblySEO returns in webhooks.

* **Service:** WeblySEO — https://weblyseo.com (or the host you set as **API Base URL**).
* **Purpose:** List drafts; validate the API key; load a single draft when resolving which WordPress post to update; report the WordPress post id and CMS publish completion back to WeblySEO; optionally download JSON from a `downloadUrl` supplied in a webhook.
* **REST paths used (relative to API Base URL):**  
  `POST /api/v1/contentapi/test-connection`  
  `GET /api/v1/contentapi/drafts` (with pagination/search query parameters)  
  `GET /api/v1/contentapi/drafts/{id}`  
  `POST /api/v1/contentapi/drafts/cms-done`  
  `POST /api/v1/contentapi/drafts/{id}/wordpress-post-id`  
* **Other HTTP:** `GET` to the `downloadUrl` inside `content.generated` webhook payloads (host/path chosen by WeblySEO for that event).
* **Data sent:** API key via `X-API-Key` and `Authorization: Bearer` headers on Content API calls; JSON bodies for POST actions as required by each endpoint; webhook payloads received over HTTPS to your site.
* **When it is called:** When administrators use the drafts/settings UI (including Test Connection), and when WeblySEO invokes your webhook URL. Draft list loading uses the API when you open the drafts admin page with valid credentials.
* **Privacy policy:** https://weblyseo.com/en/privacy  
* **Terms of service:** https://weblyseo.com/en/terms-of-service  

No data is sent to WeblySEO without your configured API Base URL and API key (except webhook responses your site sends back to the same base URL you configured).

When WeblySEO provides an Unsplash stock image in a webhook payload, the plugin hotlinks the image directly from **Unsplash** (`images.unsplash.com`) rather than copying it into the WordPress Media Library. This is required by the Unsplash API Terms (images must be served from Unsplash CDN for attribution tracking). No personal data is sent to Unsplash; the browser or server fetches the image URL in the same way as any other public image. Unsplash privacy policy: https://unsplash.com/privacy

== Screenshots ==

1. Content Sync drafts list — WeblySEO drafts with search and pagination.
2. Settings modal — API Base URL, API Key, Webhook URL, and Webhook Secret.

== Upgrade Notice ==

= 1.4.13 =
Compliance: Updated Tested up to WordPress version. Recommended for all sites.

== Changelog ==

= 1.4.13 =
* Compliance: Updated "Tested up to" WordPress version to 7.0.

See changelog.txt (bundled with this plugin) for the full release history.
