=== AIGeschikt Connector ===
Contributors: aigeschikt
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.4
Tags: ai search, seo, schema, ai crawlers, llms-txt
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connects your site to the AIGeschikt platform: AI-crawler tracking, content edits and schema.org markup for visibility in AI search.

== Description ==

AIGeschikt is a paid service that measures how visible a business is in AI answers (ChatGPT, Gemini, Perplexity, ...) and improves it. This plugin is the connector between your WordPress site and that service. **It needs an AIGeschikt account to do anything useful** — see "External services" below for exactly what is sent where.

What the plugin does on your site:

* **Content edits** — AIGeschikt can send a list of small text corrections for a page. The plugin applies them to the rendered HTML when the page is output (your content in the database is not changed), so they can be undone at any time. Text edits can only change visible text and the `alt`, `title` and `aria-label` attributes; scripts, styles and the page head are never touched.
* **schema.org markup** — outputs JSON-LD that AIGeschikt provides for a page, next to (or instead of) the markup of your SEO plugin.
* **Blog posts and pages** — AIGeschikt can create blog posts and pages as **drafts**. Nothing is published without your approval. The plugin also fills the SEO description fields of Rank Math / Yoast, supports Polylang, and ships one page template ("AIGeschikt full width").
* **Structured data fixes for Rank Math** — optional and off by default: when AIGeschikt enables it for a site, the plugin corrects and completes the schema.org graph that Rank Math outputs (your business details as they appear on your site, no Article markup on pages that are not articles) and can name the real author, with the profile you agreed on with AIGeschikt, on the blog posts AIGeschikt publishes. It only changes what is output; nothing is written to the settings of Rank Math or WordPress.
* **Blog styling** — optional and off by default: a stylesheet that makes the blog posts AIGeschikt publishes match your theme (table of contents, call-out box, tables). It is only printed on those posts, cannot load anything from outside your site, and your theme and your own posts are untouched.
* **Theme text fields (Advanced Custom Fields)** — AIGeschikt can correct a text in an ACF text field (for example a price or opening hours). Only plain text fields, only when the current value is exactly what AIGeschikt expects, all-or-nothing, and a change can never add scripts or other code.
* **AI crawler tracking** — measures which AI crawlers (GPTBot, ClaudeBot, PerplexityBot, ...) visit which pages. Visits are stored in a small table in your database and sent to AIGeschikt once the plugin is connected.
* **llms.txt and IndexNow key** — serves an `llms.txt` file and an IndexNow key file when AIGeschikt provides them.
* **Cache purge** — clears the page caches of well-known cache plugins after a change.

The plugin is passive: it makes no changes by itself. Everything is done on request of the connected AIGeschikt account, authenticated with a WordPress Application Password of a user that has the matching capabilities (edit rights per page; Editor rights for site-wide actions; Administrator rights to set up the connection).

= Measuring AI crawlers on cached pages (optional, off by default) =

A page cache can serve a page without WordPress starting, so a plugin cannot see those visits. If you turn on "Measure AI bots on cached pages" on the settings page, the plugin does what caching plugins do:

* it places a small `wp-content/advanced-cache.php` (WordPress' own early-loading hook) that only reads the request's user agent and, for a known AI crawler, writes one line to a spool folder in your uploads directory;
* it adds one line `define( 'WP_CACHE', true );` to `wp-config.php` if `WP_CACHE` is not defined anywhere yet.

If another plugin already has its own `advanced-cache.php`, ours is placed in front and that file is loaded right after it, unchanged (we move it to `advanced-cache-aigeschikt-origineel.php` and move it back when you turn the feature off). Any error in our part is caught, so it can never take your site or your cache down. Turning the feature off, deactivating or deleting the plugin removes both pieces again. You can also do the two steps by hand; the settings page shows the exact text. The feature is never enabled automatically.

== External services ==

This plugin connects to the following services.

**AIGeschikt platform** (https://aigeschikt.nl) — the paid service this plugin is the connector for. The plugin only contacts it after you (or the AIGeschikt onboarding) have entered the API URL and API key on the settings page; before that it makes no requests to it. When connected, it sends:

* AI crawler visits, in batches, once an hour: the crawler's name and category, its IP address, the visited URL (including query string), the ID, type and title of the visited post (only if it is published), the HTTP status, and the time. Regular visitors are never sent.
* If you press "Request removal" on the settings page: the options you ticked, your note, your site URL and the e-mail address of your WordPress user.
* Answers to requests that AIGeschikt makes to your site's REST API (for example a list of your pages, or the text structure of a page it is going to edit). These are only answered for an authenticated user with the matching capabilities.

Terms of service: https://aigeschikt.nl/voorwaarden — Privacy policy: https://aigeschikt.nl/privacy

**OpenAI crawler IP ranges** (https://openai.com/gptbot.json, https://openai.com/chatgpt-user.json, https://openai.com/searchbot.json) — once a day the plugin downloads OpenAI's publicly published lists of crawler IP addresses, to check that a visitor who claims to be an OpenAI crawler really is one. This is a read-only request; no data about your site or your visitors is sent. OpenAI terms of use: https://openai.com/policies/row-terms-of-use/ — Privacy policy: https://openai.com/policies/row-privacy-policy/

== Privacy ==

The plugin stores, in a table `{prefix}aigeschikt_bot_events` of your database, one row per AI crawler visit: crawler name, IP address, URL, post ID/type/title, HTTP status and time. Rows are deleted after 90 days. The table and all other data of the plugin are removed when you delete the plugin. The plugin adds a suggested text to Tools → Privacy → Policy Guide that you can use in your privacy policy.

== Installation ==

1. Upload the `aigeschikt-connector` folder to `/wp-content/plugins/`, or install the plugin from the Plugins screen, and activate it.
2. Open **AIGeschikt** in the admin menu and enter the API URL and API key you received from AIGeschikt (or let the AIGeschikt onboarding do this for you).
3. Under Users → Profile, create an Application Password for the AIGeschikt integration. Do this as an **Administrator**: setting up the connection and rolling changes back require administrator rights.

== Frequently Asked Questions ==

= Do I need an AIGeschikt account? =

Yes. The plugin is the connector for the AIGeschikt service (https://aigeschikt.nl). Without a connection it only keeps a local list of AI crawler visits and shows them on the settings page.

= Does it change my content in the database? =

No. Text edits and schema are applied when the page is output and can be removed at any time. Blog posts and pages that AIGeschikt creates are drafts until you approve them.

= How do I remove everything AIGeschikt changed? =

Use "Request removal" on the settings page: AIGeschikt then rolls its changes back for you. Deleting the plugin also stops all edits and removes its data.

= My cache serves pages without PHP. Are AI crawlers still measured? =

Only if "Measure AI bots on cached pages" is turned on, and not when a server-level cache (for example some host-level caches) answers before PHP starts; the settings page tells you which case applies.

= Does early measurement work on a multisite network? =

No. All sites of a network share one `wp-content` folder, so a visit cannot be attributed to the right site before WordPress has started. Everything else works per site; AI crawler visits that reach WordPress are measured on every site.

= Can I clear my own server cache after a change? =

Yes. Hook into `aigeschikt_purged_url` (fires with the URL after each single-page purge) or `aigeschikt_purged_all` (bulk purge, no arguments).

== Changelog ==

= 1.0.4 =
* First release with the full feature set in the WordPress.org directory: schema.org corrections for Rank Math (off by default), the real author in the schema of published blogs (off by default), blog styling (off by default) and corrections in ACF text fields.
* Hardened: text edits can no longer be applied inside script and style blocks, overlays need Editor rights, and REST routes check the capability for the specific page they act on.
* Page caches of Seraphinite Accelerator are cleared too.

= 0.8.9 =
* First release in the WordPress.org directory.
* A new or edited blog post now also clears the cache of the blog overview, the homepage (if it lists posts) and category archives.
* Added uninstall clean-up and a privacy policy suggestion.
* Hardened: text edits can no longer be applied inside script and style blocks, edits need Editor rights, and all REST routes check the capability for the specific page they act on.
* The settings page and its messages are now in English and translatable.
