Module reference

AEO Audit for Magento 2 — module reference

Covers angeo/module-aeo-audit 4.2.4 · Checked 16 October 2026 · MIT licensed

AEO Audit checks how ready a Magento 2 store is for AI answer engines such as ChatGPT, Gemini, Claude and Perplexity. One command scores 20 signals per store view. For every failed signal it tells you what is wrong and how to fix it.

The module only reads. It does not change your store. You can run it on production, on staging, or in a CI pipeline.

What it checks

The audit has two layers. Configuration signals check that the store is set up for AI engines. Evidence signals (added in 4.0.0) check that AI crawlers can really reach the store.

#SignalCodeWeightWhat it checks
1robots.txt — AI botsrobots_txt1.012 AI bots, syntax errors, conflicting rules
2llms.txtllms_txt1.0llms.txt v2 structure, locale and currency, links
3llms.jsonlllms_jsonl0.75Valid JSON Lines, required fields
4sitemap.xmlsitemap0.8XML, lastmod, catalog size
5Product schemaproduct_schema1.0JSON-LD on a real product page, offers
6Merchant policiesmerchant_policies0.9Return policy and shipping details in the offer
7Organization schemaorganization_schema0.8Organization on the homepage, logo, sameAs
8UCP profileucp_profile0.9/.well-known/ucp, signing keys, leaked private keys
9AI product feedai_product_feed1.0Feed file and REST endpoint
10JSON-LD qualityjsonld_quality0.7Breadcrumbs, ItemList, duplicate schemas
11Canonical and hreflangcanonical0.7Canonical agrees with og:url and JSON-LD
12Open Graphopen_graph0.7All five OG tags
13FAQ schemafaq_schema0.5FAQPage on the homepage or a CMS page
14Well-known fileswell_known0.5ucp, ai-plugin.json, security.txt, mcp
15Core Web Vitalscore_web_vitals0.5LCP, INP, CLS from Google CrUX (needs an API key)
16WAF reality checkwaf_reality0.9Does your CDN or firewall block bots that robots.txt allows?
17AI crawler activityai_crawler_activity0.5Which AI crawlers really visited
18A2A Agent Cardagent_card0.6/.well-known/agent-card.json, only when UCP declares A2A
19llms.txt link relationslink_relations0.7rel="alternate" and rel="describedby" links
20agents.mdagents_md0.7Delivery, returns and privacy pages reachable

You can switch each signal on or off in the configuration. A switched-off signal is not part of the score.

Bots are judged by purpose

The audit knows three kinds of AI bot:

  • Search bots (OAI-SearchBot, PerplexityBot, Claude-SearchBot) index pages for AI answers. Blocking one is a fail, because the store drops out of AI answers.
  • Training bots (GPTBot, ClaudeBot, CCBot) collect pages to train models. Blocking one is your licensing choice. It is reported, but it does not lower the score.
  • Opt-out tokens (Google-Extended, Applebot-Extended) never crawl. They are shown as notices.

The evidence layer

waf_reality and ai_crawler_activity work together:

WAF checkCrawler activityWhat it means
Edge blocks the probeNo visitsA real block. Allow AI crawlers in your WAF or CDN.
Edge blocks the probeHealthy visitsYour CDN blocks fake bots and lets real ones in. No action.
ConsistentNo visitsThe store is probably not discovered yet.
ConsistentSearch visitsThe store is fully visible to AI.

Crawler activity comes from built-in counting at the PHP level (on by default). You can add your web server access log, or your own source through BotHitSourceInterface. Only daily totals per bot are stored. No IP addresses, URLs or user agents.

Pages served from full-page cache or a CDN never reach PHP, so the built-in counter under-counts. The report says so.

Requirements

Magento2.4.x (Open Source, Mage-OS or Adobe Commerce) — magento/framework ^103.0
PHP8.1 – 8.5 — ~8.1.0||~8.2.0||~8.3.0||~8.4.0||~8.5.0

The audit works best with the other angeo modules installed, because most fix hints point to one of them. It also works alone.

Installation

composer require angeo/module-aeo-audit
bin/magento module:enable Angeo_AeoAudit
bin/magento setup:upgrade
bin/magento setup:di:compile                # production mode only
bin/magento setup:static-content:deploy     # production mode only
bin/magento cache:flush

Running the audit

# All store views
bin/magento angeo:aeo:audit

# One store view
bin/magento angeo:aeo:audit --store=en_us

# JSON for dashboards, Markdown for reports
bin/magento angeo:aeo:audit --format=json
bin/magento angeo:aeo:audit --format=markdown --output=/var/www/html/aeo-report.md

# Only fast technical checks, no external APIs
bin/magento angeo:aeo:audit --category=technical

# Fail a CI build below a score, or on any critical failure
bin/magento angeo:aeo:audit --fail-on=80
bin/magento angeo:aeo:audit --fail-on-severity=critical

# Do not save the result to the database
bin/magento angeo:aeo:audit --no-save
OptionMeaning
--storeStore view code. Default: all store views.
--formattable (default), json or markdown
--outputWrite the report to a file
--categoryOnly run checks of these categories, comma separated: technical, feed, external_api, live_signal
--fail-onExit code 1 when the score is below this number
--fail-on-severityExit code 1 when a check of this severity fails, for example critical
--no-saveDo not store the result

The score reads like this:

ScoreLabelTypical store
0–25 %CriticalDefault Magento. AI crawlers blocked, no schema.
26–75 %Needs improvementSome fixes done. Feed, policies or UCP missing.
76–90 %GoodStrong base. Small gaps.
91–100 %ExcellentAll signals in place.

Admin panel

  • Marketing → Angeo AEO → AEO Audit Results shows every past audit.
  • Marketing → Angeo AEO → Score Trend shows the score over time.
  • Run Audit Now starts an audit from the admin. It is a POST action with a form key, and it needs the Angeo_AeoAudit::run_audit permission.

Configuration reference

All settings are under Stores → Configuration → Angeo → AEO Audit. The table shows each field, its config path (for bin/magento config:set) and its default value.

Signals (Checks) (18)
SettingConfig pathDefault
robots.txt — AI bot accessangeo_aeo/signals/robots_txtYes
llms.txtangeo_aeo/signals/llms_txtYes
llms.jsonl — machine-readable catalogangeo_aeo/signals/llms_jsonlYes
sitemap.xml — AI crawler discoveryangeo_aeo/signals/sitemapYes
Product JSON-LD schemaangeo_aeo/signals/product_schemaYes
Merchant return & shipping policiesangeo_aeo/signals/merchant_policiesYes
Organization JSON-LD schemaangeo_aeo/signals/organization_schemaYes
UCP profile (/.well-known/ucp)angeo_aeo/signals/ucp_profileYes
AI product feedangeo_aeo/signals/ai_product_feedYes
JSON-LD qualityangeo_aeo/signals/jsonld_qualityYes
Canonical & hreflangangeo_aeo/signals/canonicalYes
Open Graph tagsangeo_aeo/signals/open_graphYes
FAQPage schemaangeo_aeo/signals/faq_schemaYes
well-known endpoint matrixangeo_aeo/signals/well_knownYes
Core Web Vitals (CrUX)angeo_aeo/signals/core_web_vitalsYes
A2A Agent Cardangeo_aeo/signals/agent_cardYes
Edge vs robots.txt consistency (WAF reality)angeo_aeo/signals/waf_realityYes
AI crawler activity (observed)angeo_aeo/signals/ai_crawler_activityYes
General (1)
SettingConfig pathDefault
Show fix suggestionsangeo_aeo/general/show_fix_suggestionsYes
Live Signal (Observed Crawler Activity) (4)
SettingConfig pathDefault
Built-in instrumentationangeo_aeo/live_signal/instrumentation_enabledYes
Webserver access log path (optional)angeo_aeo/live_signal/access_log_path—
Evidence window (days)angeo_aeo/live_signal/window_days30
Counter retention (days)angeo_aeo/live_signal/retention_days90
Scheduled Audit (1)
SettingConfig pathDefault
Cron scheduleangeo_aeo/cron/schedule0 3 * * 1
Sitemap Checker (2)
SettingConfig pathDefault
Placeholder slug handlingangeo_aeo/sitemap/placeholder_slug_modescore
Placeholder slug thresholdangeo_aeo/sitemap/placeholder_slug_threshold1
Core Web Vitals (CrUX API) (1)
SettingConfig pathDefault
CrUX API Keyangeo_aeo/crux/api_key— (stored encrypted)

The CrUX API key is free. Create it in the Google Cloud console and enable the Chrome UX Report API. Without a key, the Core Web Vitals check is skipped.

To read an access log, point the module at a file the PHP user can read. Do not chmod the live log. Give targeted access instead, for example setfacl -m u:www-data:r /var/log/nginx/access.log. Only the last 8 MB of the file is read.

Cron and stored data

The scheduled audit runs every Monday at 03:00 by default. It keeps the last 50 results per store. Old bot counters are removed after the retention period.

JobCron groupSchedule
angeo_aeo_auditdefault0 3 * * 1 by default, set in angeo_aeo/cron/schedule
TableWhat it holdsColumns
angeo_aeo_audit_resultAngeo AEO Audit Resultsid, store_code, store_url, score, score_label, pass_count, warn_count, fail_count, checks_json, triggered_by, created_at
angeo_aeo_bot_hitAngeo AEO Bot Hit Countersid, bot_code, bot_class, store_id, hit_date, hits, last_seen

Adding your own check

Implement Angeo\AeoAudit\Api\CheckerInterface, or extend Angeo\AeoAudit\Model\Checker\AbstractChecker (it gives you the HTTP cache, URL sampling and JSON-LD parsing). Then register it in di.xml:

<type name="Angeo\AeoAudit\Model\AuditRunner">
    <arguments>
        <argument name="checkers" xsi:type="array">
            <item name="my_check" xsi:type="object">Vendor\Module\Model\Checker\MyChecker</item>
        </argument>
    </arguments>
</type>

A checker returns its name, code, weight (0–1), category, severity and a fix command, and runs check(StoreInterface $store). One failing checker does not stop the audit.

FAQ

Does the audit change anything on my store?

No. It only reads pages and configuration. It writes only its own result rows, and you can turn that off with --no-save.

Why does blocking GPTBot not lower my score?

GPTBot collects pages for model training. Blocking it is a licensing choice and does not remove you from AI search. Blocking a search bot such as OAI-SearchBot does, so that one fails the audit.

Can I use it in CI?

Yes. Use --format=json for machine-readable output and --fail-on or --fail-on-severity to fail the build. Add --category=technical for a fast run without external APIs.

Why is Core Web Vitals skipped?

The check needs a free Google CrUX API key. Add it under Core Web Vitals (CrUX API) in the configuration. Small stores may also have no CrUX data yet.

Does it work with Hyvä?

Yes. The product schema check detects Hyvä, and the module has no storefront code.

This page was written from the README.md, composer.json and etc/*.xml files of tag 4.2.4, read on 16 October 2026. Settings, commands and defaults come straight from that code. If a newer release is out, the README on GitHub wins.