Acid AEO — AI Readiness, Citations & Rich Data

Description

Search is turning into answering. ChatGPT, Perplexity, Claude, Gemini and Google AI Overviews read your site, summarise it and decide whether to cite you. Acid AEO gives them exactly what they need to understand and quote you, and gives you the controls, the score and the proof.

Two minutes, no code. Install, answer a short wizard, read your AI readiness score. Watch the whole run, from the directory install to the first audit:

Documentation, from install to the developer reference: https://acidstudios.ro/acid-aeo/docs/

What you get in two minutes

  • A site AI assistants can read in one request. llms.txt with your key pages, offerings and FAQ, plus llms-full.txt with the full text: the files answer engines look for first.
  • One AI crawler policy, applied everywhere. Pick a preset from “citable” to “closed” or decide per crawler; the same policy is written to robots.txt, ai.txt, the Content-Signal header and llms.txt, so they can never disagree.
  • Rich data that does not fight your SEO plugin. One JSON-LD graph (Organization, WebSite, WebPage, BreadcrumbList, Article, Person, FAQPage, Speakable). Yoast, Rank Math, SEOPress, AIOSEO, The SEO Framework and Slim SEO are detected, and the plugin steps aside for what they already emit.
  • Found faster. IndexNow tells Bing and its partners the moment you publish.
  • Proof it works. A readiness score from 0 to 100, the fixes that matter (most of them one click), and AI citation tracking: which crawlers fetched what, and which answer engines sent you visitors. No cookies, no stored IP addresses.

Who it is for

Site owners and agencies who want the AI-readiness stack done right without reading the specs. Developers who want every output filterable, a REST API and WP-CLI commands for the same operations.

Why people trust it

  • One source of truth: identity and policy are set once in the wizard, and every file and every schema node is generated from it.
  • Nothing leaves your server except IndexNow pings (on by default, one switch to turn off). No analytics, no phone-home, no external fonts.
  • Honest by design: the audit reports what is actually served, not what is configured, and never overwrites a file you placed yourself.
  • Free and open source (GPL), listed in the WordPress.org directory, with public documentation.

Everything it generates

AI readiness files

  • llms.txt — a curated map of your site for language models, plus llms-full.txt with the full text.
  • humans.txt — the people behind the site, with roles and profiles.
  • ai.txt — machine readable usage terms for AI crawlers.
  • ai-context.json — a compact JSON brief: who you are, what you offer, how to cite you.
  • .well-known/security.txt — the RFC 9116 security contact.

One AI crawler policy

  • Presets from “citable” to “closed”, or per-bot control over every known AI crawler.
  • Emitted consistently to robots.txt, ai.txt, the Content-Signal header and the policy section of llms.txt.
  • Optional licence and permissions contact so publishers can find you.

Rich data

  • A single JSON-LD @graph: Organization, WebSite, WebPage, BreadcrumbList, Article, Person, FAQPage, Speakable and image metadata.
  • Detects Yoast, Rank Math, SEOPress, AIOSEO, The SEO Framework and Slim SEO, and steps aside for the pieces they already emit.

Reach and measurement

  • IndexNow: a key, the key endpoint and automatic submission when you publish.
  • AI citation tracking: which AI crawlers fetched what, and which answer engines sent you visitors — without cookies and without storing personal data.
  • Content tools: TL;DR, FAQ and key-takeaway blocks, per-post summaries, “last updated” and Markdown for agents.
  • An audit score that tells you exactly what is missing and fixes most of it for you.

External services

The plugin talks to one third-party service. IndexNow is on by default; switch it off in the setup wizard’s Discovery step or on the settings screen, and nothing is sent, not even by an explicit wp acid-aeo indexnow submit or POST /indexnow/submit.

IndexNow (https://www.indexnow.org/). When the IndexNow module is enabled, the plugin sends an HTTPS POST to https://api.indexnow.org/indexnow containing your site’s host name, the IndexNow key the plugin generated for your site, the URL of the key file and the list of URLs that were just published, updated, deleted, or that you chose to submit. It is sent when content changes (if automatic submission is on), when you press Submit in the admin or the CLI, and when you finish the setup wizard with Submit every URL ticked. Nothing else is transmitted — no visitor data, no content. IndexNow terms of use: https://www.indexnow.org/terms. IndexNow is operated by Microsoft; privacy statement: https://privacy.microsoft.com/privacystatement. The endpoint can be changed with the acid_aeo_indexnow_endpoint filter. Turn the IndexNow module off and no request is made, whoever asks: automatic submission stops, and the CLI command and the REST route refuse with a message.

Everything else stays on your own server:

  • The readiness audit fetches your own site’s URLs (home page, robots.txt, llms.txt and the other generated files) with wp_remote_get(), as a crawler would, to check they are served correctly. These are loopback requests to your own domain.
  • The optional citation beacon is a first-party script that posts to your own site’s REST API, as described in the FAQ.
  • The plugin does not contact Acid Studios, does not phone home, does not check for updates outside wordpress.org and does not load any remote script, font or image.

Two kinds of URL appear in the source without ever being requested. They are named here explicitly, because an automated scan reads the constant and not the paragraph:

  • AiContextGenerator::SCHEMA_URL = https://acidstudios.ro/schemas/ai-context/1.0.json. This string is written into the $schema key of the ai-context.json the plugin generates, the way any JSON document names the schema it follows. It is never fetched, at generation time or later.
  • The docs URLs in includes/Bots/Registry.php (23 of them, for example https://developer.amazon.com/amazonbot and https://platform.openai.com/docs/bots). These are link targets printed in the per-crawler settings table, for you to open in your own browser if you want to read what a crawler does. The plugin never requests them, and no crawler documentation is fetched, parsed or cached.

Fonts

The admin screens use Inter (https://github.com/rsms/inter, v4.1) and Space Mono (https://github.com/googlefonts/spacemono), both under the SIL Open Font License 1.1. The files and their licences are in assets/fonts/. They are served from your own site and load only on Acid AEO’s admin screens.

Screenshots

Blocks

This plugin provides 3 blocks.

  • AI Summary (TL;DR)
  • AI FAQ
  • Key takeaways

Installation

  1. Upload the acid-aeo folder to /wp-content/plugins/, or install the ZIP through Plugins Add New Upload Plugin.
  2. Activate the plugin through the Plugins screen.
  3. The setup wizard opens automatically. It takes about three minutes.
  4. Visit /llms.txt on your site to confirm the files are being served.

If your files return a 404, go to Settings Permalinks and press Save Changes once to refresh the rewrite rules.

FAQ

Does it conflict with Yoast, Rank Math or another SEO plugin?

No. Acid AEO detects the SEO plugins listed above and turns off the structured data pieces they already emit (Organization, WebSite, Breadcrumb, Open Graph and Twitter tags). What stays on is what SEO plugins do not do: FAQPage, Speakable, extended Person data, AI-specific files and the crawler policy. You can force any piece on or off yourself.

Where are the files served from?

They are virtual by default: llms.txt, humans.txt, ai.txt, ai-context.json and security.txt are produced on request through WordPress rewrite rules, so they are always current. If a real file with the same name already exists in your webroot, that file wins and the plugin tells you about it in the audit.

There is already a robots.txt, llms.txt or ai.txt file on my server. What happens?

The web server answers with the file on disk before WordPress runs, so the copy this plugin generates is never seen for that path. The audit reports it (“No robots.txt on disk”, “No conflicting llms.txt on disk”) rather than overwriting anything: a file the plugin did not write is never touched. Delete or rename the file and the generated one takes over immediately. robots.txt is a special case — the plugin never writes it to disk; it only filters the virtual one WordPress serves.

I use a page cache. Will the citation tracking still work?

Server-side tracking sees only the requests that reach PHP, so a page served from a full-page cache is invisible to it. The wizard detects the common cache plugins and offers the browser beacon: one small first-party script that reports a visit arriving from an AI answer to your own site’s REST endpoint (/wp-json/acid-aeo/v1/beacon). It sends the page URL, the referrer and the utm_source parameter, once per page per browser session, and nothing else. No third party is involved.

Does it slow the site down?

No. Generated files are cached in transients and invalidated only when content or settings change. Front-end output is a single JSON-LD block plus a few header tags; there is no JavaScript on the front end unless you switch the optional citation beacon on.

Is the citation tracking GDPR-safe?

It is designed to be. No cookies are set, no personal data is stored: visitor IPs are hashed with a salt that rotates daily and truncated, and user agents are reduced to a bot name. Rows are deleted automatically after the retention period you choose.

Can I write physical files instead of virtual ones?

Yes. Switch Static files on and pick which of llms.txt, llms-full.txt, humans.txt, ai.txt, ai-context.json and .well-known/security.txt are written into your webroot through the WordPress filesystem API. You need this on hosts that answer /*.txt and /.well-known/* from disk and only fall through to PHP when the file is missing — a CDN, an edge cache or a static export in front of WordPress.

The writer is deliberately conservative. It never writes robots.txt, which belongs to WordPress core and to your SEO plugin. Every file it generates carries a marker (generated by Acid AEO, or the "generator" field in ai-context.json), and a file without that marker is never overwritten and never deleted — so an llms.txt that was already in your webroot stays exactly as it is. Writing needs the direct filesystem method: if WordPress would have to ask for FTP credentials, the audit says so instead of asking. The files are rewritten when the settings change, when you publish, and once a day. Each write also prunes: a file the plugin wrote that you have since unticked — or whose module you switched off — is deleted by the same pass, so your server stops answering with a copy the settings no longer stand behind. Switching the module off removes the ones the plugin wrote, and so does uninstalling it. See docs/hosting-notes.md for server and cache configuration.

What is removed on uninstall?

Deleting the plugin removes its settings, the events table, its cron events, the post and user meta it added, its transients and any file in the webroot that carries the plugin’s own marker. Files it did not write are left alone. Tick Keep my data on uninstall under Settings Advanced before deleting if you want to keep everything for a later reinstall.

Does it work on multisite?

Multisite: activate per site or network-wide; each site keeps its own settings, table and cron. A network activation prepares every site that already exists, and a site created afterwards is prepared as it is created.

Is there a WP-CLI interface?

Yes, every screen has a command behind it:

  • wp acid-aeo audit [--fresh] [--format=<table|json>] — runs the readiness audit and exits with status 1 when the score is below 50, so a deployment pipeline can gate on it.
  • wp acid-aeo regenerate — drops every cached file and rebuilds the rewrite rules.
  • wp acid-aeo static write|remove — writes the generated files to disk, or removes the ones the plugin wrote.
  • wp acid-aeo indexnow submit [<url>...] [--all] and wp acid-aeo indexnow log.
  • wp acid-aeo export [--file=<path>] and wp acid-aeo import <file> — move settings between staging and production.
  • wp acid-aeo citations stats [--days=<n>] and wp acid-aeo citations purge [--older-than=<days>].
  • wp acid-aeo preview <llms|llms_full|robots|humans|ai_txt|ai_context|security> — prints what a file would say right now, even when its module is switched off.

How do I stop the “Updated on” line appearing on my posts?

It is off until you switch it on. Acid AEO -> Settings -> Content tools -> Show a “last updated” line on posts controls it for the whole site; the setup wizard
offers the same switch in its writing tools step.

To keep the line but drop it from one page, tick Hide the “last updated” line on this
post
in the AI readiness box in the editor sidebar. A theme can take it over entirely
with the acid_aeo_last_updated_html filter: return an empty string to remove the line,
or your own markup to replace it. acid_aeo_last_updated_threshold changes how long after
publishing a revision has to come before the line appears, in seconds; the default is one day.

Are there any known limitations?

Two worth knowing about in 1.0.0:

  • IndexNow does not read your SEO plugin’s per-post noindex setting. It stops at the site-wide Discourage search engines option, so a public site that has marked one individual post noindex in Yoast, Rank Math or another SEO plugin will still submit that post’s URL to IndexNow. Until a later version reads the per-post flag, the way round it is to untick that post type under IndexNow, or to turn automatic submission off and submit by hand with wp acid-aeo indexnow submit <url>.
  • Static files need the direct filesystem method. If your host makes WordPress ask for FTP or SSH credentials before writing, nothing can write the files — a scheduled task has nobody to ask. The audit reports it as a finding rather than prompting, and the virtual files keep working exactly as before; only the physical copies are unavailable.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“Acid AEO — AI Readiness, Citations & Rich Data” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

1.0.4

Released 2026-10-08.

  • Changed: with the IndexNow module switched off, nothing is sent any more, whoever asks: wp acid-aeo indexnow submit and POST /indexnow/submit now refuse with a clear message instead of sending.
  • Changed: the Documentation link on the Plugins screen opens the documentation, not the product page.
  • Fixed: the Content tools option read “On ?format=md only”; the query value is ?format=markdown.
  • Fixed: the setup wizard and the admin notice said “five short steps”; there are seven.

1.0.3

Released 2026-10-08.

  • Changed: the admin screens and the setup wizard are redrawn in the Acid Studios light style: Inter and Space Mono, black on white, one green used as a fill under black text. Nothing was moved and no setting changed.
  • Changed: two typefaces now ship with the plugin (Inter and Space Mono, SIL Open Font License 1.1, in assets/fonts/ with their licences). They load on the plugin’s own admin screens only; nothing is requested from another server.
  • Fixed: text that was white on green (the mark, the step numbers, the yes/no buttons, the success message) did not meet WCAG AA contrast. It is black on green now.
  • Fixed: a switch that is off was drawn too faintly to see against the page.
  • Fixed: in a right-to-left language the wizard’s switches slid the wrong way.
  • Fixed: the wizard’s yes/no buttons showed their radio circles on top of the labels.
  • Fixed: at phone width the settings screen, the crawler table and the Tools screen scrolled sideways.
  • Fixed: the “AI readiness” widget on the WordPress dashboard showed its score as plain text.

1.0.2

Released 2026-09-18.

  • Changed: the line crediting Acid Studios in humans.txt is off by default. It was on, which put a link to the plugin author’s site in a public file on every install that did not go looking for the switch. The switch is still in the wizard and in Settings for anyone who wants to leave it on.
  • Fixed: on a site given its own directory for WordPress — core’s supported layout, where siteurl is home plus a folder — the optional static files were written into the WordPress folder while every address the plugin publishes pointed at the folder above it. The files were invisible, and the audit then reported them missing. They are now written where the site is actually served from, and an uninstall removes them from there.
  • Fixed: on a multisite network, switching the static files on from a site other than the main one overwrote the main site’s llms.txt, humans.txt and ai-context.json with that site’s content, published at the network’s address. Network sites now decline to write to the shared directory and say why; virtual delivery is unchanged, so every site still answers its own files.
  • Fixed: the Allow: lines in robots.txt named /llms.txt and its neighbours even on sites where those addresses do not answer — with plain permalinks the files are served through a query variable, and on a site in a subdirectory every path carries that directory. The lines are now taken from the addresses the files are actually served at.
  • Fixed: the audit’s loopback requests called the core https_local_ssl_verify filter with one argument where core passes two. A site with a callback written to core’s documented signature took a fatal error on every audit.
  • Fixed: the sitemap probe accepted any HTTP 200 as a sitemap, so a host that answers unknown paths with the home page had an HTML page stored and then advertised to every crawler as its sitemap. The answer now has to read as a sitemap.
  • Fixed: a fresh audit settled which sitemap answers before dropping its cached responses, so the probe read answers up to ten minutes old and then fetched every address a second time. It now happens after, once, inside the run.
  • Fixed: a summary taken from a post’s excerpt was published with the page builder’s shortcodes still in it, while the same text taken from the content had them removed.
  • Fixed: the headings the AI blocks print — “In short”, “Frequently asked questions”, “Key takeaways” — were English on every site, whatever its language, because the defaults were never translated. They now follow the site language like the rest of the interface.
  • Added: the acid_aeo_llms_full_documents filter. llms-full.txt considered at most two hundred documents with no way to change it and nothing saying so; the byte budget beside it was already a setting.
  • Fixed: the audit read authors from post alone, so a site whose content is entirely in a custom post type was told every author profile was empty. It now reads the post types the plugin publishes; the same goes for the key pages fallback, which now recognises every page-like post type, and for the published counts behind the wizard’s guess at what kind of site this is.
  • Fixed: the Documentation link on the Plugins screen pointed at a page that did not exist; it now opens the plugin’s page on acidstudios.ro.
  • Changed: the readme now names, one by one, the URLs that appear in the source without ever being requested, so an automated scan can match the constant it reads against a sentence about that constant.
  • Changed: Contributors now lists the wordpress.org account that owns the plugin.
  • Fixed: uninstalling now also removes the per-post “hide the last updated line” flag introduced in 1.0.1, instead of leaving it behind in the database.
  • Changed: the readiness audit’s loopback requests now respect the https_local_ssl_verify filter, the same switch WordPress core uses for its own loopbacks.
  • Fixed: on a site running Yoast SEO, robots.txt named the same sitemap twice. The AI crawler block is now the last thing added to the file, so the line another plugin contributes is seen and not repeated.
  • Fixed: on a site built with a page builder — WPBakery, Divi, Elementor — llms.txt, llms-full.txt and the Markdown endpoint printed the builder’s own shortcodes instead of the text inside them. The tags are now removed whether or not the builder registered them for the request, and the prose they wrap is kept.
  • Fixed: a page kept out of search by the site’s SEO plugin was still advertised in llms.txt and ai-context.json. The noindex set in Yoast SEO, Rank Math, SEOPress, All in One SEO, The SEO Framework or Slim SEO is now read, each in that plugin’s own vocabulary, and the page is left out. The acid_aeo_is_noindex filter answers for anything else.
  • Fixed: on a WooCommerce store the generated files led with Cart, Checkout and My account — three pages that read as a form to anyone who fetches them. They are left out; the shop page, which is the catalogue, stays.
  • Fixed: a page built with Elementor, Bricks or Oxygen was published as a bare link, because those builders keep the content in post meta and leave post_content empty. The rendered content is read instead, so the page gets a summary like any other.
  • Fixed: the audit reported llms.txt as “written by something else” on most sites — it looked for the signature in the first two kilobytes, and llms.txt signs its last line. It now asks the same question, of both ends of the file, as the module that writes it.
  • Fixed: the sitemap address the files point at was worked out from which SEO plugin is installed, which is not the same question — Rank Math, SEOPress and All in One SEO ship the sitemap as a module that can be off, and The SEO Framework and Slim SEO answer at their own address while core’s stops. The audit now settles it by asking the site, and robots.txt adds no sitemap line when another plugin has already written one.

1.0.1

Released 2026-09-17.

  • Fixed: the “Updated on” line gave its <time datetime> attribute in UTC while printing the visible date in the site’s own timezone, so the two could name different days on any site that is not on UTC. Both halves are now the site’s local time, and the visible date is localised rather than always English.
  • Added: Hide the “last updated” line on this post, a per-post checkbox in the AI readiness box, for the pages the site-wide line does not suit.
  • Added: the acid_aeo_last_updated_html and acid_aeo_last_updated_threshold filters, so a theme can move, restyle, replace or remove the line and choose how old a revision has to be.

1.0.0

Released 2026-09-15.

  • Initial release: AI crawler policy (robots.txt, ai.txt, Content-Signal), llms.txt and llms-full.txt, humans.txt, ai-context.json, security.txt, JSON-LD rich data, AI head tags and HTTP headers, IndexNow, AI citation tracking, content tools with Markdown for agents, optional static files, the readiness audit, the setup wizard, a REST API and WP-CLI commands.