=== Notado ===
Contributors: wporg-username-pending
Tags: seo, ai, schema, robots-txt, llms-txt
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 0.11.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connects your site to Notado and applies, with your approval, the fixes Notado finds when it checks how AI engines answer about your business.

== Description ==

Notado measures whether AI engines (ChatGPT, Gemini, Perplexity, Claude, Google AI Overviews and AI Mode) recommend your business. This plugin lets Notado apply the fixes you approve on your WordPress site.

Every published fix comes with its proof: we compare visibility in the 14 days before and the 14 days after, engine by engine. Every Monday we check that the redirects, the FAQ, the structured data and the llms.txt we published are still on the site.

The WordPress REST API does not expose everything Notado needs to fix. The plugin adds what is missing:

* **Managed robots.txt**: serves the approved robots.txt, open to AI crawlers such as GPTBot, ClaudeBot and PerplexityBot, through the WordPress virtual robots.txt. It refuses to write when the site has a physical robots.txt file, and says so.
* **llms.txt**: serves and withdraws the llms.txt file built from the facts about your business. When Hostinger Tools or Yoast SEO with their llms.txt switch on, or Website LLMs.txt once it has generated its file, are active, the plugin leaves the address to them: it keeps the approved content without serving it and tells Notado which plugin publishes the file. It also yields to an llms.txt file at the site root, which the web server serves before WordPress, and tells Notado that the file exists.
* **SEO title and meta description**: reads and writes the title and meta description kept by Yoast SEO, Rank Math, AIOSEO, SEOPress, SureRank or The SEO Framework, which the REST API does not expose. It writes into that plugin's own fields, so the page keeps a single title tag and a single description tag.
* **Page content**: reads and writes the content of an existing page (post_content), with the heading structure fixed. Each write leaves an automatic revision in the WordPress history, so you can always restore the previous version from wp-admin.
* **Structured data on the right page**: stores a schema.org JSON-LD block for an existing page and prints it in the head of that page and no other. It does not create pages or touch the content. It refuses a block that is not a schema.org object, and refuses a page the connected account cannot edit. Removing the block returns the head to what it was.
* **301 redirects**: when an AI engine shows an address on your site that no longer exists, Notado can redirect it to the matching page, with your approval. The plugin redirects only while WordPress answers 404 for that address.
* **AI crawler visits**: logs requests from AI citation and training crawlers (GPTBot, OAI-SearchBot, PerplexityBot, ClaudeBot and others) in its own table, created on activation, kept for 30 days. Notado pulls them so you can see when GPTBot visited, beyond what robots.txt allows. You can turn this off in wp-config.php with `define( 'NOTADO_DESLIGAR_REGISTO_BOTS', true );`.
* **Visits from AI answers**: counts, per day, engine and landing page, the visits of people who arrive from ChatGPT, Perplexity, Gemini, Copilot, Claude, Grok, DeepSeek or Le Chat, recognised by where the visit came from. To decide whether a visit counts, it reads the referrer, the requested page and the browser identifier (to leave out robots), and checks whether someone has signed in to WordPress (to leave out the people who run the site). It stores none of that: only the day, the engine, the page and the number of visits, for 90 days, with no IP addresses, browser identifiers or cookies. A page served from a full-page cache never reaches PHP, so the plugin does not count it. You can turn this off in wp-config.php with `define( 'NOTADO_DESLIGAR_CONTAGEM_IA', true );`. Counting restarts the day after you remove it, and the day after you reactivate the plugin, so days when it was off never read as days without visits.

The plugin authenticates with Application Passwords, the same ones the rest of the Notado connection uses, and creates no accounts or passwords. The plugin itself sends no requests to outside servers: Notado reads and writes on the site through the routes above, and each route touches only its own field.

== External services ==

The plugin is only useful with a Notado account (https://notado.pt), the service run by Voidstep, Lda. that measures how visible a business is in AI engines and proposes fixes. Without that connection, the plugin logs AI crawler visits and counts visits from AI answers in the site's own database, and nothing leaves the site.

Once you connect the site at notado.pt with the user and the Application Password you created, Notado's servers use the plugin routes and the WordPress REST API:

* When connecting, they read the user of the Application Password, to confirm the connection works.
* To prepare and check fixes, they read: the front page set in Reading Settings, the page that matches each address on the site, the SEO title and meta description, the content and the structured data block of the pages a fix will change, and the robots.txt, llms.txt and redirects the plugin manages.
* They write only the fixes you approve in Notado, each in its own field.
* They create a new page when the approved fix is a page the site does not have yet (a FAQ page, for example) and, if you revert that fix, they move the page to the trash, where you can restore it.
* Once a day they pull the AI crawler visits (date, crawler name, crawler browser identifier, request path and method, no IP address) and the daily counts of visits from AI answers (day, engine, page and number of visits, no personal data).

To stop every read and write, delete the Application Password in your WordPress profile or disconnect the site at notado.pt.

* Terms of service: https://notado.pt/termos
* Privacy policy: https://notado.pt/privacidade

== Installation ==

1. In wp-admin, go to Plugins, Add New, and install Notado, or upload the ZIP under Upload Plugin.
2. Activate the plugin.
3. In your WordPress profile, create an Application Password.
4. At notado.pt, connect the site under Settings with its address, the user and the Application Password.

== Frequently Asked Questions ==

= Do I need a Notado account? =

Yes. Without it, the plugin only keeps the AI crawler log and the counts of visits from AI answers in your own database.

= What happens when I uninstall the plugin? =

Uninstalling removes the plugin's tables, its options (including the managed robots.txt and llms.txt) and the structured data blocks it stored on your pages. Deactivating keeps them.

== Changelog ==

= 0.11.0 =
* Readme in English, ready for the WordPress.org plugin directory, with a section on the Notado service.
* From WordPress 6.5 the plugin prints the JSON-LD block with wp_print_inline_script_tag. On 6.2 to 6.4 it prints the tag itself, because there WordPress wraps the block in a CDATA comment when the theme does not declare html5 script support, and the JSON stops being valid. Table names reach SQL through the %i placeholder of $wpdb->prepare, so the plugin now requires WordPress 6.2.
* The plugin unslashes and sanitizes every request value it reads from the server.
* Uninstalling also removes the managed robots.txt and llms.txt and the structured data blocks stored on pages, on every site of a multisite network.

= 0.10.1 =
* The seo route refuses to write (409) when two SEO plugins are active, and names them. On a real WordPress site with Yoast and AIOSEO, the page printed two meta descriptions and served the AIOSEO title, so the title written in Yoast never showed.
* The llms route yields to an llms.txt file at the site root, which the web server serves before WordPress, and reports that it exists (root_file). Hostinger Tools leaves its file at the root when you deactivate it.
* The plugin yields to Website LLMs.txt only after that plugin has generated its file. Until then it answers 404, and the site was left without an llms.txt.

= 0.10.0 =
* The seo route also writes the title and meta description with AIOSEO, SEOPress, SureRank and The SEO Framework, in each plugin's own fields. With more than one active, the first in the list wins, the same one the site already serves. With AIOSEO, only from version 4.9.8: earlier versions erased the page's other fields when saving the title alone.

= 0.9.0 =
* The llms route says which plugins serve their own llms.txt (Hostinger Tools and Yoast SEO with llms.txt switched on, Website LLMs.txt) and, with any of them active, the plugin leaves the address to it.

= 0.8.0 =
* The content route also says which page builder lays out the page (Elementor, Divi, WPBakery, Beaver Builder or Oxygen), read from the meta each one saves. With a builder, Notado does not write headings into post_content: it hands over the fixed content to apply in the builder.

= 0.7.0 =
* 301 redirects: the redirects route reads (GET), writes (POST) and removes (DELETE) a redirect from an old address on the site to a page on the same site, stored in the notado_redirects option.
* The redirect acts only when WordPress answers 404 for that address: a page that exists again, or another redirect plugin that acts first, always wins.
* Refuses (409) an address that has a published page, a target on another site, a target equal to the source, a target that already redirects and a full map (500 entries).
* Uninstalling removes the notado_redirects option.

= 0.6.0 =
* Counts visits from AI answers: its own notado_ai_referrals table, created on activation and also on a ZIP update, with one row per day, engine and page and the number of visits. Stores no IP address, browser identifier or cookies.
* Counting restarts the day after each activation and after removing the constant that turns it off. If the table does not exist (for example, without permission to create it), the route says counting is off, and the plugin tries to create it again on the next request.
* The plugin recognises the source by the referrer (chatgpt.com, perplexity.ai, gemini.google.com, copilot.microsoft.com, claude.ai, grok.com, chat.deepseek.com, chat.mistral.ai) or, on a visit without a referrer, by the utm_source mark ChatGPT adds to links.
* Does not count visits from bots, logged-in accounts, prefetches, 404 pages or requests other than GET.
* GET route notado/v1/referrals: every complete day since the requested date, days without visits included, so Notado can tell a measured zero from a day nobody counted.
* 90-day retention, and uninstalling removes the table and the options.

= 0.5.0 =
* json-ld/{id} route: reads (GET), writes (POST) and removes (DELETE) the JSON-LD block of an existing page, stored in the _notado_json_ld meta and printed in wp_head on that page only.
* The plugin accepts the block only as an object with a schema.org @context and an @type (or an @graph of entities with @type), up to 64 KB. The plugin prints it with the < and > characters escaped, so it can never close the script tag.
* resolve route: says which page serves a public address on the site, the static front page included, so Notado writes on the right page. With or without www, the address counts as the same site.
* The three json-ld routes answer 403 to an account that cannot edit the page, before saying whether it exists. Only an account that edits other people's pages gets 404 for a page that no longer exists.
* The route refuses a revision number (400) when reading, writing and removing: the block always stays on the page itself.

= 0.4.0 =
* Logs AI crawler visits: its own notado_bot_visits table created on activation (dbDelta), filled on shutdown from the User-Agent of citation and training crawlers and pruned daily with 30-day retention. A constant in wp-config.php turns it off.
* GET route notado/v1/bots: visits paged by id cursor (since) with a per_page ceiling, authenticated by the same Application Password as the other routes.
* Uninstalling removes the table; deactivating keeps the history.

= 0.3.0 =
* Page content: content/{id} route that reads the raw post_content and writes it through wp_update_post; each write creates an automatic WordPress revision, an extra safety net on top of reverting in Notado.
* Refuses with 409 (notado_sem_permissao_edicao) when the authenticated account cannot edit the page.

= 0.2.0 =
* Managed (virtual) robots.txt, refused when there is a physical file.
* llms.txt served and withdrawn through a route.
* Plugin version in every response.
* Renamed from Notado SEO to Notado: it is no longer only about SEO.

= 0.1.0 =
* First version: reads and writes the title and meta description (Yoast SEO, Rank Math).
