=== Rank Authority SEO Connector ===
Contributors: rankauthority
Tags: seo, ai, ai-seo, generative-engine-optimization, schema
Requires at least: 5.3
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.1.5
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

AI-powered SEO on autopilot: publish optimized content and get found on Google and AI search — ChatGPT, Perplexity, and Google AI Overviews.

== Description ==

**Rank Authority puts your WordPress SEO on autopilot.** Connect your site once, and the [Rank Authority](https://rankauthority.com) platform researches, writes, optimizes, and publishes search-ready content straight to WordPress — built to get you found on Google **and** on AI search engines like ChatGPT, Perplexity, Gemini, and Google AI Overviews.

This plugin is the free connector for the Rank Authority Dashboard, a paid third-party service that requires an account. The plugin handles secure publishing and on-site optimization; strategy, content generation, and recommendations happen in the dashboard. Every remote endpoint the plugin contacts is documented in the External Services section below.

= Why site owners pick Rank Authority =

Most SEO plugins hand you a checklist and leave the actual work to you. Rank Authority does the work:

* **You don't write — it publishes for you.** SEO-optimized blog posts are created in the dashboard and published to your site automatically, complete with featured images, categories, meta descriptions, and JSON-LD structured data.
* **You show up where people search now.** GEO (Generative Engine Optimization) pages are purpose-built so AI assistants — ChatGPT, Perplexity, Gemini, Google AI Overviews — can find, understand, and cite your business.
* **Your existing pages get optimized without you lifting a finger.** Approved recommendations (titles, meta tags, content improvements, internal links, schema) are applied server-side, directly in your page HTML. Every crawler sees them — no JavaScript required, no flicker, no third-party script slowing down your visitors.
* **Your technical SEO stays healthy.** IndexNow instant indexing, managed robots.txt fixes, 301 redirects for consolidated content, clean 410 responses for removed pages, and update-friendly feeds — handled automatically.

= Key features =

* **Automated publishing** – Create, update, and unpublish posts and pages from the Rank Authority Dashboard over a secure, token-authenticated REST API
* **GEO / AI search visibility** – Dedicated Generative Engine Optimization pages with clean, readable templates that work on any theme, light or dark
* **Server-side optimization (SSR)** – Optimized titles, meta descriptions, canonicals, Open Graph tags, content, and internal/external links are written into the HTML on the server, so Google, Bing, and AI crawlers all see the final version
* **Structured data done right** – JSON-LD schema with your real site name, logo, and post author; publisher logos scaled to Google's guidelines
* **IndexNow and robots.txt** – Serves your IndexNow key file for instant URL submission and supports one-click managed robots.txt fixes
* **A real dashboard in wp-admin** – See exactly which Blog Engine posts and GEO pages Rank Authority published, with View/Edit links and site health checks (HTTPS, permalinks, IndexNow) at a glance
* **Firewall-friendly** – If a web application firewall blocks inbound publishing, a pull-based fallback keeps your scheduled content flowing
* **Safe by design** – Deletions unpublish to restorable drafts, page-builder layouts are snapshotted before changes, and one-click self-update keeps the connector current

= Plays well with your stack =

* **SEO plugins**: Yoast SEO, Rank Math, All in One SEO — meta descriptions and focus keyphrases are written to the plugin you already use, so nothing conflicts
* **Page builders**: Elementor, Divi, WPBakery, Beaver Builder, Bricks
* **Caching**: WP Rocket, W3 Total Cache, LiteSpeed Cache — the optimized output is what gets cached, and caches are purged automatically when settings change

= Private and lightweight by default =

* No visitor tracking: the plugin sets no cookies and sends no visitor IPs or personal data anywhere
* No scripts are loaded in your visitors' browsers
* Optimization is off by default — nothing is applied or fetched until you enable it
* Bearer-token authentication and HTTPS are required for every API request
* Everything published is a normal WordPress post or page — your content stays yours, even if you disconnect

= How it works =

1. Install and activate the plugin
2. Go to WordPress Admin → Rank Authority and copy your connection token
3. Paste the token in your [Rank Authority Dashboard](https://rankauthority.com) to link the site
4. Publish your first optimized post — it appears on your site fully formatted, with images, schema, and meta tags

== External Services ==

This plugin relies on the Rank Authority service to optimize your content. The endpoints below are every remote host the plugin contacts, what is sent to each, and when.

**1. Rank Authority snippet CDN — https://dc23q3bsr9o1t.cloudfront.net/snippets**

* Purpose: retrieve the approved SEO recommendations and JSON-LD for the page currently being rendered.
* Data sent: your Rank Authority website ID and a SHA-256 hash of the current page URL (as part of the request path). No visitor data, IP logging, or cookies are sent by the plugin.
* When: on a front-end page render, only when "Enable SEO Tracking" is on and a website ID is connected. The result is cached in a transient for one hour (15 minutes for a miss), so it does not run on every page view.

**2. Rank Authority snippet API — https://backend.rankauthority.com/public/snippet**

* Purpose: fallback lookup used only when the CDN has no snippet for the page.
* Data sent: your website ID and the cleaned page URL as query parameters (`website_id`, `page_id`). Tracking parameters such as `utm_*`, `gclid`, `fbclid`, and `msclkid` are removed first.
* When: same conditions and caching as the CDN lookup above.

**3. Rank Authority Dashboard — https://rankauthority.com**

* Purpose: the dashboard that publishes and updates your content. It calls into your site's `ra/v1` REST endpoints using the bearer token you copy from the plugin settings; the content you publish and the metadata returned by those endpoints (post bodies, permalinks, SEO title and meta description) travel over that connection.
* Data sent: only what your dashboard requests, and only after you connect the site with the token.
* When: on demand, when you act in the dashboard.

**4. Google Fonts — https://fonts.googleapis.com**

* Purpose: the Inter webfont used by the plugin's own settings screen in wp-admin.
* Data sent: the request is made by the administrator's browser, which exposes their IP address and user agent to Google.
* When: only while viewing the Rank Authority settings screen in wp-admin. It is not loaded on the front end.

**5. Rank Authority pull-fallback publishing — https://backend.rankauthority.com/wp-pull/pending and https://backend.rankauthority.com/wp-pull/report**

* Purpose: when the dashboard cannot publish to your site over the inbound REST API (for example a Web Application Firewall blocks the request), the plugin instead pulls the blog and GEO content you scheduled in the dashboard and publishes it locally, then reports the result back. This is a receive-only fallback for content you already scheduled.
* Data sent: your connected bearer token (as the `Authorization` header) and website ID to request pending items; and, when reporting, your website ID plus, for each item, its Rank Authority content ID, a one-time claim ID, the publish status, the resulting permalink, and the JSON-LD schema that was applied. No visitor data is sent.
* When: on a WordPress cron schedule (approximately every 10 minutes) while the site is connected with a token, and immediately when the dashboard calls the authenticated `POST /ra/v1/pull-now` route. Both are skipped entirely when the site is not connected.

Rank Authority is a third-party paid service operated by Rank Authority. By connecting your site you agree to its terms:

* Terms of Service: https://rankauthority.com/terms-of-service/
* Privacy Policy: https://rankauthority.com/privacy-policy/

The plugin also declares a WebSub hub (`https://pubsubhubbub.appspot.com/`) in your RSS feed so feed subscribers can discover updates faster. The plugin itself sends no data to that hub; it only advertises the link in the feed.

== Installation ==

= Automatic Installation =

1. Log in to your WordPress admin panel
2. Navigate to Plugins → Add New
3. Search for "Rank Authority"
4. Click "Install Now" and then "Activate"

= Manual Installation =

1. Download the plugin ZIP file
2. Log in to your WordPress admin panel
3. Navigate to Plugins → Add New
4. Click "Upload Plugin"
5. Choose the ZIP file and click "Install Now"
6. Activate the plugin

= After Installation =

1. Go to WordPress Admin → Rank Authority
2. Copy your connection token
3. Use this token in your Rank Authority Dashboard to connect your site

== Frequently Asked Questions ==

= Do I need a Rank Authority account? =

Yes. This plugin is the free connector for [Rank Authority](https://rankauthority.com), a paid platform where content is generated, optimized, and scheduled. The plugin does nothing on its own until you connect it with your account. See rankauthority.com for plans and details.

= What is GEO (Generative Engine Optimization)? =

GEO is optimization for AI search: making sure assistants and answer engines — ChatGPT, Perplexity, Gemini, Google AI Overviews — can discover, understand, and cite your business. Rank Authority publishes dedicated GEO pages to your site that are structured for exactly that, alongside classic Google-focused SEO content.

= Can I use it together with Yoast SEO, Rank Math, or All in One SEO? =

Yes. The connector is designed to work alongside them, not replace them. Meta descriptions and focus keyphrases published from the dashboard are written into the SEO plugin you already use (Yoast SEO, Rank Math, or All in One SEO), so your existing setup keeps working and nothing conflicts.

= Will it slow down my site? =

No. Optimizations are applied on the server while the page is rendered — no third-party JavaScript is loaded in your visitors' browsers. Recommendation lookups are cached, and the plugin integrates with full-page caches (WP Rocket, W3 Total Cache, LiteSpeed Cache) so the optimized page is what gets cached and served.

= Does it work with page builders like Elementor or Divi? =

Yes. The plugin understands Elementor, Divi, WPBakery, Beaver Builder, and Bricks. When content is updated it snapshots the builder layout first, so the layout can always be restored.

= Does the plugin track my visitors? =

No. The plugin sets no cookies and sends no visitor IP addresses or personal data anywhere. Optimization is off by default; once you enable it, the only lookup is for the page's own approved recommendations, with tracking parameters (`utm_*`, `gclid`, `fbclid`) stripped and results cached. See the External Services section for every request the plugin can make.

= What happens to my content if I disconnect or uninstall? =

Your content stays. Everything Rank Authority publishes is a normal WordPress post or page in your database — nothing is hosted elsewhere. Disconnecting simply stops optimization lookups and publishing; your posts, pages, images, and metadata remain yours.

= How do I get my connection token? =

After installing the plugin, go to WordPress Admin → Rank Authority. Your unique token is displayed with a copy button, together with a step-by-step connect guide.

= Is my site secure with this plugin? =

Yes. Every API request requires HTTPS and Bearer-token authentication — only your connected dashboard can publish. Deletions unpublish to restorable drafts rather than permanently deleting, and administrators can regenerate the token at any time, which immediately invalidates the old one.

= Can I regenerate my token? =

Yes. Any administrator with the manage_options capability can regenerate the token from the plugin settings page. This invalidates the old token immediately.

= Can multiple users connect to the same site? =

The plugin supports site-level connection. The last user to connect will overwrite the previous website ID. For team collaboration, consider using a shared account.

= Privacy & Tracking =

Applying SEO recommendations is **disabled by default**. Until you enable the optimization toggle in the plugin settings and connect the site with a website ID, the plugin makes no requests to the Rank Authority snippet CDN or API.

Once enabled, each front-end page render looks up recommendations for that page. The lookup sends your website ID and the page URL (a SHA-256 hash of it on the CDN path, the URL itself on the API fallback). Tracking parameters such as `utm_*`, `gclid`, and `fbclid` are stripped before the lookup, results are cached for one hour, and no visitor IP addresses, cookies, or personal data are sent by the plugin. Unchecking the option or disconnecting the site stops the lookups immediately.

Note that the plugin settings screen in wp-admin loads a webfont from Google Fonts. That request is made by your browser when you view that one screen, and it happens regardless of the tracking setting. See the External Services section for details.

== Screenshots ==

1. Overview — connection status, Blog Engine and GEO content counts, and site health checks (HTTPS, permalinks, IndexNow) at a glance
2. Content — every post and page Rank Authority published on this site, with one-click View and Edit links
3. Settings — control server-side AI SEO optimization with a single toggle and manage your connection token
4. Site Info — WordPress environment, content totals, and search engine files, read directly from your install
5. Get Started — the three-step connect guide shown until your site is linked

== Changelog ==

= 1.1.5 =
* New Get Started view in the wp-admin dashboard: until the site is connected, the plugin opens on a three-step connect guide (copy token, open dashboard, link the site) instead of Settings, so first-time setup is self-explanatory
* Added a review request notice in wp-admin that appears only after several successful publishes on a connected site; it can be snoozed for two weeks or dismissed permanently, and it never appears for unconnected sites
* Uninstall now also removes the managed robots.txt options and the new review-request options, so no plugin rows are left behind
* Rewrote the WordPress.org listing (description, FAQ, screenshots, tags) to describe what the platform does instead of listing version history; no REST API or publishing behavior changes

= 1.1.4 =
* The SSR optimizer now treats a well-formed snippet response with no recommendations as an authoritative answer and caches it for the full TTL (default 1 hour). Previously an empty payload was handled like a failed fetch: it was cached for only 15 minutes and every expiry re-queried the CDN and then the Rank Authority API, so pages with nothing to apply polled the API forever
* A CDN response that is well-formed but empty no longer triggers the API fallback at all; the API is only consulted when the CDN fetch genuinely fails (network error, missing object, malformed body)

= 1.1.3 =
* Added a pull-fallback publisher for sites behind a Web Application Firewall: when the dashboard's inbound publish push is blocked, the plugin pulls scheduled blog/GEO content from the Rank Authority backend and publishes it locally, so the payload never crosses the firewall inbound
* Runs on a 10-minute WordPress cron floor that survives a full inbound IP block, plus an authenticated `POST /ra/v1/pull-now` route the dashboard can call to trigger a cycle immediately
* The pull publisher reuses the existing publish path (schema, local featured-image upload, Rank Authority content labeling) and reports each result back over the authenticated API; a transient lock prevents an on-demand kick from overlapping a scheduled run
* Admin dashboard now opens on the Settings section by default, and Settings is the first item in the sidebar navigation

= 1.1.2 =
* Added authenticated redirect management endpoints for internal content consolidation, with recoverable draft unpublishing and optional republishing
* Configured source paths now serve permanent 301 redirects before stale 410 handling
* Publish and update responses now report custom-slug collisions; callers can keep WordPress suffixing or reject conflicts before content is created
* Content lookups now report page hierarchy, front-page, and navigation-menu signals for safer consolidation eligibility checks
* Redirect registration rejects loops and bounds the managed map at 500 entries; served redirects preserve the visitor's query string and slug rejection never alters existing content

= 1.1.1 =
* The admin page is now a sidebar dashboard (Overview, Content, Site Info, Settings) instead of a single card. Sections switch client-side via URL hash so a refresh keeps the current view
* Overview leads with what Rank Authority produced on this site — Blog Engine post count and GEO page count — plus connection status with a deep link to the dashboard and a site-health list (applied-optimization toggle, HTTPS, pretty permalinks, IndexNow)
* Content published through the connector is labeled with a private "Rank Authority" taxonomy (Blog Engine / GEO) so staff can identify and filter it in wp-admin. The taxonomy is not public: no front-end archive, invisible to visitors
* Added an authenticated `POST /ra/v1/label-content` route so the Rank Authority Dashboard can backfill that label onto content published before this release. It accepts `{"items": [{"post_id": 123, "type": "blog"}, {"slug": "path", "type": "geo"}]}` and applies the same hidden meta + taxonomy term (Blog Engine / GEO) that new publishes get. Idempotent and safe to re-run; only posts and pages are labeled
* The Content section lists the Blog Engine posts and GEO pages published here, each with View (front-end) and Edit (wp-admin) links plus a "see all" link into the filtered posts/pages list
* Site Info now carries the site-wide totals (published/draft posts and pages) alongside WordPress/PHP/theme versions, multisite, timezone, IndexNow key location and date, and whether a physical robots.txt shadows the managed one
* All dashboard values are read locally from this install (no network calls, no new data sent). The API token, reset, and applied-optimization toggle keep their existing behavior under Settings
* Requires WordPress 5.3+ (uses wp_date/wp_timezone_string); tested up to 7.1

= 1.0.63 =
* SSR optimizer now applies `og-tags` recommendations: creates or updates the targeted `og:*` meta tag (property parsed from the recommendation selector); `og:image`/`og:url` values pass URL sanitization

= 1.0.62 =
* Added authenticated `GET /ra/v1/robots` and `PUT /ra/v1/robots` routes. The dashboard can store a managed `robots.txt` body (`{"content": "..."}`) or clear it (`{"reset": true}`), enabling one-click robots.txt fixes
* The managed body is served through WordPress's `robots_txt` filter at priority 99 so it wins over SEO plugins (Yoast/Rank Math/AIOSEO)
* `GET /ra/v1/robots` reports `physical_file`/`writable` so the dashboard knows when a physical `robots.txt` shadows the virtual file and falls back to manual guidance

= 1.0.61 =
* Security: removed the `post_meta` parameter from the update endpoint. It accepted any meta key outside a short blocklist and wrote the value unchanged, which let an authenticated request set meta that themes and page builders render on the frontend. The `rank_authority_post_meta_blocklist` filter is removed with it
* Security: restoring a page builder layout no longer writes values from the request. When the plugin clears builder meta it now keeps its own copy on the post, and a restore reads that copy, so request input never reaches keys such as `_wpb_shortcodes_custom_css`, `_wpb_post_custom_css`, or `_elementor_data`, which builders emit as CSS or render as widgets
* The update endpoint still accepts `builder_meta` and the response still reports `cleared_builder_meta`, so existing integrations keep working; the submitted values are ignored in favour of the stored copy
* The stored builder copy is removed once a restore applies it, and on uninstall
* The update response reports `builder_restored`: true when a restore applied the stored copy, false when this site had none to restore from (layouts cleared by an earlier version), and null when no restore was requested

= 1.0.60 =
* Removed arbitrary CSS handling: the publishing endpoint no longer extracts `<style>` blocks from submitted HTML into post meta, and the plugin no longer prints stored CSS into `wp_head`. Rows written by earlier versions are deleted on upgrade
* Security: markup supplied by the recommendation service is now filtered through `wp_kses_post()` before it is inserted into a page, so script tags, event-handler attributes, and disallowed protocols cannot reach the rendered HTML
* Security: recommendations may only set attributes on an allow list. Event handlers, `style`, `srcdoc`, and `formaction` are refused outright, and `href` / `src` values are restricted to http, https, mailto, and tel
* Security: element re-tagging is limited to layout and text tags, so a recommendation can no longer rename an element to `script`
* Security: JSON-LD is emitted with `JSON_HEX_TAG`, `JSON_HEX_AMP`, `JSON_HEX_APOS`, and `JSON_HEX_QUOT`, so no schema value can terminate the surrounding script block
* Removed a step that rewrote `\u003C`-style escapes in the raw snippet response before decoding it; `json_decode()` already resolves them, so the rewrite only undid escaping the transport had applied
* Schema supplied as HTML is now decoded and validated at save time, so post meta holds JSON data instead of `<script>` markup
* Fixed SSR page titles losing a literal `&`: the title was written by assigning `nodeValue`, which libxml reads as entity references, so "Tips & tricks" was rendered as "Tips  tricks". Titles are now written as a text node
* Fixed element re-tagging acting on the wrong tag: a `new_selector` such as `h2.title` took the last token and produced a `<title>` element inside the body (and `div.wrapper` produced `<wrapper>`). Re-tagging now applies only to recognised layout and text tags and is skipped otherwise, leaving the original element untouched
* Coding standards: `json_encode()` calls replaced with `wp_json_encode()`, admin banner output escaped, and the `ra_highlight` query flag unslashed and sanitized

= 1.0.59 =
* Renamed the plugin display name to "Rank Authority SEO Connector" so it describes the plugin itself rather than the wider platform, and removed the `Plugin URI` header, which pointed at a page that no longer exists
* Security: bearer-token authentication now rejects the request when the stored token is empty, instead of treating an empty `Authorization: Bearer` header as a match
* Documented every external service the plugin contacts (snippet CDN, snippet API, dashboard, Google Fonts) in a dedicated External Services section, including what is sent and when
* Corrected the feature list and privacy notes to match current behaviour: recommendations are applied server-side and no third-party script is loaded for visitors
* Coding standards: swapped `parse_url()`, `strip_tags()`, and `unlink()` for their WordPress equivalents, unslashed and sanitized every `$_SERVER` read, escaped the IndexNow key-file body, and set explicit versions on the registered admin assets
* Tested against WordPress 7.0

= 1.0.58 =
* SSR: link recommendations now fall back to the visible anchor text when their CSS selector does not match the live DOM (parity with content/heading recommendations), improving reliability on CMS-connected sites

= 1.0.57 =
* Added authenticated `GET /ra/v1/content?slug=<slug>` route: returns a published post/page body plus SEO metadata (effective `seo_title`, `meta_description`, `canonical`, `yoast_keyword`) in one call, so the Rank Authority scanner can audit title/meta-description tags for CMS-connected sites (the public `wp/v2` body does not carry `<head>` metadata)
* `GET /ra/v1/post/{id}` (and `/ra/v1/page/{id}`) responses now also include `seo_title` and `canonical`, resolving Yoast / RankMath / AIOSEO meta with a post-title / permalink fallback
* SEO title falls back to the post title when the stored value is an unexpanded template (e.g. Yoast `%%title%%`, RankMath `%title%`)

= 1.0.56 =
* RA-driven post/page deletion now unpublishes to draft (restorable) instead of permanent delete, while the URL still serves 410
* Added authenticated `GET /ra/v1/inventory` route returning paginated published permalinks across all public post types, for authoritative URL inventory

= 1.0.55 =
* GEO page template (`page-geo.php`): the article now has its own light surface — white background, dark base text color, padding, and rounded corners — so dark-themed sites (or themes whose custom header forces `body { background: #000 }`) can no longer render the generated GEO content invisible
* GEO category template (`category-geo.php`): archive content wrapped in the same light surface; post titles and the page title get explicit dark colors instead of inheriting theme colors designed for a dark background
* Links without inline colors inside GEO content get a dark fallback color so theme link colors meant for dark backgrounds stay readable on the light surface

= 1.0.54 =
* Fixed `POST /ra/v1/upgrade` leaving the plugin deactivated after a successful self-update: WordPress' `Plugin_Upgrader` silently deactivates the plugin before replacing its files (`deactivate_plugin_before_upgrade` on non-cron contexts), and the REST path had no admin redirect to reactivate it
* The endpoint now captures the pre-upgrade active state (including network-activation on multisite) and silently re-activates the plugin after the files are swapped, matching how a normal admin update preserves an active plugin
* If re-activation fails, the endpoint returns an error instead of reporting success, so the dashboard never shows a healthy connection while the plugin is actually inactive

= 1.0.53 =
* SSR robustness: inline `<script>`, `<style>`, `<svg>`, and `<noscript>` blocks are stashed behind comment tokens before the `DOMDocument` load/save round-trip and spliced back verbatim afterward, so libxml can no longer mangle page-builder HTML widgets whose scripts embed markup (template literals containing `</div>`, etc.) — this was leaking raw JS into the rendered page on Elementor homepages
* JSON-LD `<script type="application/ld+json">` is deliberately left in the DOM so it is still located and updated in place; no change to title/meta/canonical/content/link recommendation behavior

= 1.0.52 =
* Fixed `POST /ra/v1/upgrade` falsely reporting "already up to date" on sites that were genuinely behind: the self-update now queries wordpress.org directly via `plugins_api()` and compares with `version_compare()` instead of relying on WP's cached `update_plugins` transient (which stays empty when the plugin folder slug differs from `rank-authority` or the update cron check is stale/blocked)
* The wp.org package is injected into the update transient keyed by the actual installed plugin file before running `Plugin_Upgrader`, so the upgrade proceeds even when WP's own update check never flagged it

= 1.0.51 =
* Added authenticated `POST /ra/v1/posts/bulk-delete` endpoint: removes multiple posts/pages by slug in a single request, resolving each slug via the site's permalink structure (`url_to_postid()`), hierarchical page path, then `post_name` fallback, and returning per-slug `deleted` / `not_found` / `failed` results
* Deleted URLs are now recorded and served an HTTP `410 Gone` response on the front end (via `template_redirect` at priority 0, before canonical redirects and 404 handling) instead of a `404`, signaling a permanent/intentional removal to search engines for faster, cleaner deindexing — the homepage is never marked gone
* The gone marker is recorded BEFORE deletion (since `get_permalink()` is empty afterward) for both single and bulk deletes, and is automatically cleared on publish/update when a URL is reused by a live post so it serves `200` again

= 1.0.50 =
* Added optional `slug` parameter on publish (`POST`): when the Rank Authority Dashboard sends a custom slug, it is applied via `post_name` (sanitized with `sanitize_title()`); omitted slug still derives from the title as before, and WordPress handles collision suffixing automatically

= 1.0.49 =
* Added authenticated `POST /ra/v1/upgrade` endpoint so the Rank Authority Dashboard can trigger a one-click plugin self-update from wordpress.org (runs WP's `Plugin_Upgrader`; reports the resulting version, or reports "already up to date" when no update is pending)
* Self-update now pre-checks the filesystem method and returns a clear error when the site requires FTP/SSH credentials (instead of failing opaquely), and guards against concurrent upgrade requests with a short-lived lock
* Reverse-proxy/load-balancer compatibility: HTTPS detection on authenticated and bootstrap endpoints now honors the `X-Forwarded-Proto`/`X-Forwarded-SSL` headers so sites that terminate TLS upstream are no longer wrongly rejected

= 1.0.48 =
* Added author selection: publish (`POST`) and update (`PUT`) handlers now honor an explicit `author` field from the Rank Authority Dashboard, applying it only when it resolves to a real, publish-capable user (otherwise the create default or the live post author is preserved)
* Added authenticated `GET /ra/v1/authors` endpoint returning all publish-capable users (id, name, slug, email) for author selection in the dashboard
* Hardened post creation: `wp_insert_post()` is now called with `$wp_error = true` so a failed insert returns a `WP_Error` instead of silently passing a `0` post ID

= 1.0.47 =
* Server-side rendering (SSR): approved SEO recommendations are now applied to the rendered page HTML on the server (new `includes/class-ra-ssr-optimizer.php`), so optimized title/meta/content/links are present in the raw source for all crawlers — a faithful port of the previous client-side script
* Body-level recommendations are confined to the WordPress post content region (via `the_content` markers, with a content-container fallback) so theme chrome (header/nav/footer) is never modified
* Dashboard toggle repurposed: "AI SEO Optimization" now controls whether recommendations are applied server-side rather than whether a tracking script is injected; the legacy client-side script is no longer enqueued
* Full-page cache integration: SSR output is applied through the `rocket_buffer` filter so it is what WP Rocket caches, with an idempotency marker (`<!--ra-ssr-applied-->`) to prevent double application across nested buffers/caches
* Caches are purged automatically when the toggle (or website_id) changes so the new state takes effect immediately
* Data source is unchanged from the client script: CDN snippet first (sha256 of the cleaned URL), public API fallback, cached in a transient

= 1.0.46 =
* Internal: Stored schema markup rendering (HTML script blocks, raw JSON, and array-of-schemas) is consolidated back into `output_schema_markup()`; the `render_stored_schema_markup()` helper was removed with no change to emitted JSON-LD or RankLink supplemental graph output

= 1.0.45 =
* Front-end: RankLink content is now scanned once per request and the result is shared between the JSON-LD schema graph and the `<meta name="ra-ranklink">` summary, eliminating a duplicate `preg_match_all` pass on every singular page render
* Front-end: Site host and scheme are computed once per request when normalizing internal RankLink URLs instead of calling `home_url()` / `parse_url()` for every anchor
* Front-end: Placement counts (`exact_phrase`, `paragraph_sentence`, `related_reading`) are now attributed per anchor based on the enclosing wrapper block (with anchor-level `data-ra-placement` taking precedence), replacing the previous attribute-occurrence heuristic so multi-link wrappers and self-tagged anchors are counted correctly
* Internal: `output_schema_markup` split into a smaller entry point plus a dedicated `render_stored_schema_markup` helper for readability; behavior of stored HTML / JSON / array-of-schemas rendering is unchanged

= 1.0.44 =
* RankLink HTML markers (`data-ra-link-id`, `data-ra-block-id`, `data-ra-placement`) are allowed in post content through `wp_kses` so Rank Authority internal links survive editor saves
* REST API: Added `GET` and `PUT` `/ra/v1/page/{id}` as aliases of the existing post read/update handlers
* JSON-LD: When content contains RankLink anchors, outputs supplemental WebPage `@graph` schema with `relatedLink` and `significantLink` for same-site URLs (capped at 20); refactored JSON-LD script output into a shared helper; RankLink graph can emit even when stored post schema meta is empty
* Front-end: `wp_head` emits an HTML comment and `<meta name="rank-authority-ranklink">` with internal link and placement counts; `?ra_highlight=1` (or `true`) adds highlight styling for quick visual QA

= 1.0.43 =
* Updated the plugin display name for the WordPress.org listing and WordPress admin plugin screen

= 1.0.42 =
* Added `POST /ra/v1/bootstrap` for first-time Rank Authority Dashboard connection setup after WordPress administrator authorization
* Bootstrap responses include the plugin bearer token, website ID, IndexNow setup metadata, permalink status, and plugin version
* Bootstrap connection setup requires HTTPS and `manage_options` capability

= 1.0.41 =
* Added authenticated IndexNow configuration and status endpoints for Rank Authority Dashboard setup
* Serves the stored IndexNow key at `/{key}.txt` only on an exact path match, without requiring rewrite-rule flushes
* Connection and IndexNow status responses now include plugin version and IndexNow setup metadata

= 1.0.40 =
* Added POST `/ra/v1/posts/bulk-delete` endpoint to delete multiple posts or pages by slug in one authenticated request

= 1.0.39 =
* Fixed the Rank Authority settings page layout so WordPress admin navigation and top-level admin chrome keep their normal positioning
* Scoped the settings page background and spacing to the plugin content area instead of applying layout styles to the whole admin body
* Hid unrelated third-party admin notices on the Rank Authority settings page and restyled plugin-generated success messages for consistent alignment

= 1.0.38 =
* Schema: Site-level placeholder tokens (`[SITE NAME]`, `[SITE URL]`, `[LOGO URL]`, `[PAGE URL]`) emitted by the LLM are now resolved to real WordPress values at publish time
* `[LOGO URL]` falls back to the site icon (favicon) when no Customizer logo is set; left as a literal token if neither exists to avoid emitting an empty-URL ImageObject
* Placeholder substitution runs after field-specific replacements on both POST and PUT, recursively walking decoded JSON-LD as well as raw JSON / HTML schema strings
* Render-time normalization: `wp_head` now re-applies site-placeholder substitution and refreshes `mainEntityOfPage.@id` with the current permalink so structured data stays in sync after slug, site name, URL, or logo changes

= 1.0.37 =
* RSS 2.0 feeds: added WebSub (PubSubHubbub) hub discovery (`atom:link rel="hub"`) pointing to the public hub at `https://pubsubhubbub.appspot.com/` so hubs and subscribers can receive push-style feed notifications when you publish or update posts
* Complements 1.0.36 feed behavior (sort by modified date, up to 50 items per feed request)

= 1.0.36 =
* RSS / Atom feeds: main site feed orders posts by last modified date (newest changes first) instead of publish date only
* Feed requests up to 50 items per request so recently updated posts surface faster for crawlers and subscribers

= 1.0.35 =
* PUT response now always includes schema (stored schema or null)
* Previously schema was only included when schema was sent in the request

= 1.0.34 =
* Schema publisher.name now replaced with WordPress site name (Settings > General)
* Schema author fully replaced with WordPress post author as Person (@type Person, name, url)
* Ensures schema uses your site's publisher name and post author for consistent structured data

= 1.0.33 =
* PUT update: Page builder meta (Elementor, WPBakery, Divi, Beaver Builder, Bricks) now cleared when updating content so frontend uses post_content
* PUT response includes cleared_builder and cleared_builder_meta (saved builder data for restore)
* PUT accepts builder_meta to restore page builder layout (send cleared_builder_meta back to re-apply)
* PUT accepts post_meta for arbitrary post meta updates (blocklist protects sensitive keys)
* Elementor CSS file (post-{id}.css) deleted when clearing Elementor meta to avoid orphaned CSS loading
* Filters: rank_authority_page_builder_meta_keys, rank_authority_post_meta_blocklist

= 1.0.32 =
* GEO page template: Increased top padding to 10rem for better clearance of theme fixed headers
* Ensures GEO content is fully visible below sticky headers on all themes

= 1.0.31 =
* GEO page template: Increased top padding for theme fixed/sticky headers in public view
* Fixes content being cut off at top when viewing GEO pages as non-logged-in visitor
* Applies to both page-geo.php and category-geo.php templates

= 1.0.30 =
* PUT response now includes full updated content (title, content, excerpt, etc.)
* Auto-clear post cache after POST/PUT so public view shows new content immediately
* Supports WP Rocket, W3 Total Cache, LiteSpeed Cache; hook `rank_authority_post_cache_cleared` for custom cache plugins

= 1.0.29 =
* Added GET /ra/v1/post/{id} endpoint to retrieve post or page by ID
* Returns content, meta_description, schema, yoast_keyword, featured_image, categories, tags, is_geo
* Works with same Bearer token; supports draft, private, and pending posts/pages

= 1.0.28 =
* GEO page template: Added padding for admin bar so content is not covered when logged in
* Prevents WordPress toolbar from overlapping page content on GEO pages

= 1.0.27 =
* GEO: When yoast_keyword is not provided, use page title as Yoast focus keyphrase
* Enables Yoast SEO score display for prompt-based GEO content (no explicit keyword)
* Applies to both publish and update endpoints

= 1.0.26 =
* GEO content now published as WordPress pages instead of posts
* Use `is_geo: true` or include Geo category ID in `categories` to publish as page
* GET /ra/v1/geo-category now returns `publish_as_page: true` for Dashboard compatibility
* Added templates/page-geo.php for GEO page display (text-focused, no thumbnails)
* Geo pages marked with _rank_authority_geo meta for identification
* Delete endpoint works for both posts and pages (unchanged behavior)

= 1.0.25 =
* Fixed admin page layout - scoped CSS reset to plugin content only
* Prevents WordPress admin nav and sidebar from being misaligned on Rank Authority settings page

= 1.0.24 =
* Publisher logo dimensions now scaled to fit Google guideline (max 600px width)
* Prevents Search Console structured data validation warnings for oversized logos

= 1.0.23 =
* Schema mainEntityOfPage.@id now replaced with actual published post URL
* Publish and update post API responses now include final schema (JSON) in response
* Ensures schema references the correct permalink for SEO and rich results

= 1.0.22 =
* Schema mainEntityOfPage.@id now replaced with actual published post URL
* Publish and update post API responses now include final schema (JSON) in response
* Ensures schema references the correct permalink for SEO and rich results

= 1.0.21 =
* Schema mainEntityOfPage.@id now replaced with actual published post URL
* Publish and update post API responses now include final schema (JSON) in response
* Ensures schema references the correct permalink for SEO and rich results

= 1.0.20 =
* Schema image replacement - replaces placeholder images with actual uploaded URLs
* Supports featured_image_url, images, and images_urls parameters for schema image swap
* Schema logo replacement - replaces publisher.logo with WordPress site logo from Customizer when available
* Keeps ImageObject structure for logo (url, width, height)
* Full support for @graph schema format (BlogPosting, FAQPage, etc.)

= 1.0.19 =
* Fixed Geo exclusion on /blog and custom Blog pages
* Applies to pages whose slug contains "blog" or "news" (e.g. /blog, /blog-2, /news, /news-en)
* Filters: `ra_geo_exclude_page_slugs` (exact match), `ra_geo_exclude_slug_contains` (partial match)
* Applies to main query and secondary queries (custom page templates, page builders)

= 1.0.18 =
* Exclude Geo category posts from main blog/posts page
* Blog page now shows only non-Geo posts - Geo posts visible only at /category/geo/
* Prevents image-less GEO content from appearing in blog listing

= 1.0.17 =
* Added Geo category for Generative Engine Optimization (GEO) content
* Auto-creates "Geo" category on plugin install and update
* Geo category archive uses custom template - text-only list without thumbnails
* Added GET /ra/v1/geo-category API endpoint to fetch Geo category ID for Dashboard
* Use Geo category for AI-optimized posts without featured images

= 1.0.16 =
* Added loading overlay and progress indicator for token reset functionality
* Improved user experience during token regeneration - prevents accidental button clicks
* Enhanced visual feedback with animated spinner and status messages
* Better UX with disabled buttons during reset process to prevent user errors

= 1.0.15 =
* Added new `/ra/v1/check` REST API endpoint for connection verification
* Connection check endpoint validates website_id without registration
* Improved connection verification workflow - can now check if a site is connected without modifying settings
* Enhanced API functionality with dedicated connection verification endpoint

= 1.0.14 =
* Token reset functionality now available to all administrators with manage_options capability
* Removed owner-only restriction for token regeneration
* Improved flexibility for team environments where multiple administrators need token management access
* Enhanced security by maintaining manage_options capability requirement

= 1.0.13 =
* Added full HTML document parsing support - automatically extracts title, meta tags, schema, and styles
* Enhanced schema support to handle HTML format with multiple script tags
* Added automatic meta tag extraction from HTML head (description, canonical, Open Graph, Twitter Card)
* Added automatic style tag extraction and output in wp_head
* Improved schema merging - combines schemas from HTML and schema parameter
* Added JSON validation for schema content before output
* Improved security by validating JSON-LD content extraction
* Support for multiple schema types in single HTML string format
* Better handling of complex schema structures with @id references
* Backward compatible - still supports previous format without full HTML documents

= 1.0.12 =
* Added support for schema parameter in publish and update post endpoints
* Added JSON-LD structured data output in wp_head for SEO
* Enhanced schema compatibility with multiple SEO plugins (Yoast SEO, Rank Math, All in One SEO)
* Improved structured data support for better search engine visibility

= 1.0.11 =
* Added support for meta_description parameter in publish and update post endpoints
* Added support for keyword parameter to set Yoast SEO focus keyphrase
* Enhanced SEO plugin compatibility (Yoast SEO, Rank Math, All in One SEO)
* Improved API functionality with SEO metadata support

= 1.0.10 =
* Moved version information from header to footer above "Powered by" text
* Improved UI layout by removing version from company name row
* Enhanced footer styling with dedicated version display

= 1.0.9 =
* Updated support email address to support@rankauthority.com

= 1.0.8 =
* Changed default admin menu icon color to #9BA2A6 (light gray-blue)
* Improved icon color consistency using CSS mask instead of filters
* Enhanced icon visibility with better color contrast

= 1.0.7 =
* Improved Reset button form styling with CSS classes instead of inline styles
* Fixed button width alignment issue by adding dedicated CSS class for reset form
* Enhanced code maintainability with cleaner CSS structure
* Improved "What Gets Tracked" card layout with better flex alignment
* Added custom hover color (#72AEE6) for admin menu icon

= 1.0.6 =
* Fixed Copy Token and Reset button widths to be perfectly equal
* Improved button flex layout with min-width and white-space properties
* Enhanced button alignment and visual consistency

= 1.0.5 =
* Fixed Reset button width to match Copy button width
* Improved admin menu icon styling - default gray color for better consistency
* Enhanced icon visibility with adjusted brightness and opacity

= 1.0.4 =
* Fixed AI SEO Tracking toggle functionality - now works correctly when clicking toggle button
* Improved toggle button interaction - both banner and toggle button clicks now work properly
* Enhanced visual feedback for active/inactive states
* Fixed toggle button label implementation for better accessibility
* Improved form submission handling for status changes

= 1.0.3 =
* Complete UI redesign with modern, beautiful interface
* Added interactive status toggle banner for SEO tracking
* Improved user experience with card-based layout
* Enhanced visual feedback with animations and transitions
* Better information display with icon-based info cards
* Streamlined settings page with improved accessibility

= 1.0.2 =
* Fixed custom SVG icon display issue in WordPress admin menu
* Improved menu icon CSS with better fallback support
* Enhanced icon rendering reliability

= 1.0.1 =
* Added custom SVG icon for admin menu
* Improved uninstall cleanup to remove all plugin options
* Enhanced admin menu styling with custom Rank Authority logo

= 1.0.0 =
* Initial release
* Secure REST API endpoints for publishing, updating, and deleting posts
* Token-based authentication
* SEO script injection
* Owner-based token management
* Disconnect functionality

== Upgrade Notice ==

= 1.1.5 =
Adds a first-run Get Started guide for unconnected sites and a dismissible review request after successful publishes. No dashboard or REST API changes required.

= 1.0.62 =
Adds managed robots.txt support (`GET`/`PUT /ra/v1/robots`) so the Rank Authority Dashboard can apply one-click robots.txt fixes. Served via the `robots_txt` filter at priority 99; falls back to manual guidance when a physical robots.txt file exists.

= 1.0.61 =
Security release. The update endpoint no longer accepts the `post_meta` parameter, and restoring a page builder layout now uses a copy the plugin saved when it cleared the layout instead of values sent with the request. No dashboard changes are required.

= 1.0.60 =
Security release. Arbitrary CSS handling is removed, markup from the recommendation service is filtered with wp_kses_post(), recommendations may only set allow-listed attributes, and JSON-LD is hex-escaped. Style blocks in submitted HTML are no longer stored or rendered.

= 1.0.59 =
Display name and Plugin URI updated for WordPress.org guideline compliance, bearer-token authentication hardened against an empty stored token, and all external services documented. No dashboard or REST API changes required.

= 1.0.47 =
SEO recommendations are now applied server-side, so they appear in the raw page HTML for every crawler. The dashboard toggle enables or disables them and the client-side script is retired. No REST API changes required.

= 1.0.46 =
Maintenance release consolidating schema markup output code paths. No dashboard or REST API changes required.

= 1.0.45 =
Performance and accuracy improvements to RankLink front-end output: single-pass content scan, cached site host on URL normalization, and wrapper-aware placement counts. No dashboard or REST API changes required.

= 1.0.44 =
Adds RankLink discovery (JSON-LD, head meta, and REST page aliases) and keeps internal-link markers intact through content sanitization.

= 1.0.43 =
Updates the plugin display name for WordPress.org and the WordPress admin plugin screen.

= 1.0.42 =
Adds an HTTPS-only dashboard bootstrap endpoint for WordPress administrators to complete first-time connections and retrieve site setup metadata.

= 1.0.41 =
Adds authenticated IndexNow setup support and serves the verified key file at `/{key}.txt`.

= 1.0.40 =
Adds an authenticated bulk delete endpoint for deleting multiple posts or pages by slug.

= 1.0.39 =
Fixes the Rank Authority settings page admin layout so the WordPress sidebar/top bar remain aligned and unrelated admin notices no longer clutter the page.

= 1.0.38 =
Schema placeholders like [SITE NAME], [SITE URL], [LOGO URL], and [PAGE URL] are now automatically replaced with your real WordPress site values at publish and render time. No dashboard or API changes required.

= 1.0.37 =
RSS feeds now advertise a standard WebSub hub link for PubSubHubbub-compatible discovery. No Rank Authority Dashboard or REST API changes required.

= 1.0.36 =
RSS and Atom feeds now sort by modified date with a higher default item count so updates are discovered sooner. No dashboard or API changes required.

= 1.0.35 =
PUT response now always includes schema for consistency. Use the response to verify stored structured data regardless of whether schema was sent in the request.

= 1.0.34 =
Schema enhancements: publisher name and author now use your WordPress site name and post author. Structured data will reflect your site's branding and authorship.

= 1.0.33 =
PUT now clears page builder meta when updating content (Elementor, WPBakery, Divi, etc.) so changes appear on frontend. Response includes builder data for restore; send builder_meta to re-apply. Added post_meta param for custom meta updates.

= 1.0.32 =
GEO page top padding increased to 10rem for better compatibility with themes that use tall fixed headers.

= 1.0.31 =
GEO page template now has increased top padding for theme fixed headers. Fixes content being cut off in public view.

= 1.0.30 =
PUT now returns full updated content and auto-clears cache so public view updates immediately without manual cache purge.

= 1.0.29 =
New GET endpoint to fetch post/page content by ID. Use the same Bearer token to retrieve published, draft, and private content.

= 1.0.28 =
GEO page template now accounts for admin bar height so content is not covered when viewing while logged in.

= 1.0.27 =
GEO content now auto-uses page title as Yoast focus keyphrase when none provided, so Yoast SEO score is visible for prompt-based content.

= 1.0.26 =
GEO content is now published as WordPress pages instead of posts. Use `is_geo: true` or include Geo category ID in the publish request. Existing geo posts remain unchanged; new GEO content will appear under Pages.

= 1.0.24 =
Publisher logo dimensions now conform to Google's 600px max width guideline. Fixes Search Console structured data validation warnings.

= 1.0.23 =
Schema mainEntityOfPage now uses actual post URL. API responses include the final schema for verification.

= 1.0.22 =
Schema mainEntityOfPage now uses actual post URL. API responses include the final schema for verification.

= 1.0.21 =
Schema mainEntityOfPage now uses actual post URL. API responses include the final schema for verification.

= 1.0.20 =
Schema enhancements: placeholder images are now replaced with actual uploaded URLs, and publisher logo uses your WordPress site logo when available.

= 1.0.19 =
Fixed Geo exclusion on /blog and custom Blog pages. Now works with page templates and page builders that use custom queries.

= 1.0.18 =
Geo category posts are now excluded from the main blog page. GEO content (image-less posts) will only appear at /category/geo/, keeping your blog listing clean.

= 1.0.16 =
Improved token reset user experience with loading overlay and progress indicator. Users will now see a clear visual feedback when resetting tokens, and all buttons are disabled during the process to prevent accidental clicks.

= 1.0.15 =
Added new connection check endpoint (`/ra/v1/check`) that allows you to verify if a website_id is connected without modifying any settings. This provides better workflow for connection verification.

= 1.0.14 =
Token reset functionality is now available to all administrators. Any user with manage_options capability can regenerate the connection token, providing better flexibility for team environments.

= 1.0.13 =
Added full HTML document parsing - automatically extracts and processes meta tags, schemas, styles, and content from complete HTML documents. Enhanced schema merging to combine schemas from HTML and API parameters.

= 1.0.12 =
Added schema/structured data support - now you can set JSON-LD schema markup via API for better SEO.

= 1.0.11 =
Added SEO metadata support - now you can set meta descriptions and focus keywords via API.

= 1.0.10 =
Improved UI layout - version information now displayed in footer for better visual hierarchy.

= 1.0.9 =
Updated support contact information.

= 1.0.8 =
Updated default admin menu icon color to #9BA2A6 for better visual consistency.

= 1.0.7 =
Improved button styling and card layout. Reset button form now uses CSS classes for better maintainability.

= 1.0.6 =
Fixed button width alignment - Copy Token and Reset buttons now have perfectly equal widths.

= 1.0.5 =
Minor UI improvements: Reset button width fix and improved admin menu icon styling.

= 1.0.4 =
Fixed toggle functionality bug. The AI SEO Tracking toggle now works correctly when clicking the toggle button.

= 1.0.3 =
Major UI update with modern design. All functionality remains the same - only visual improvements.

= 1.0.2 =
Fixed admin menu icon display issue for better compatibility.

= 1.0.1 =
Minor update with custom menu icon and improved cleanup functionality.

= 1.0.0 =
Initial release of Rank Authority.

== Support ==

For support, please visit https://rankauthority.com or email support@rankauthority.com

== Credits ==

Developed by Rank Authority
Website: https://rankauthority.com

