angeo / module-aeo-brand-visibility
Live AI brand visibility audit for Magento 2. Queries ChatGPT, Claude, Perplexity, Gemini and Groq with brand-probing prompts and scores real-world AI recall, citation rate and recommendation presence. Extends angeo/module-aeo-audit v3 via CheckerInterface as the 16th signal, alongside the 15 built-in technical checks.
angeo/module-aeo-brand-visibility
Live AI brand visibility audit for Magento 2 — queries ChatGPT, Claude, Perplexity, Gemini and Groq with brand-probing prompts and scores real-world AI recall, citation rate and recommendation presence. Multilingual since 1.3: detects recommendations and sentiment in English, Dutch, German, French and Ukrainian answers, and probes models in your market's language via the {{language}} placeholder.
angeo/module-aeo-brand-visibility is an open-source Magento 2 module that answers one question: when someone asks ChatGPT "where should I buy X?", does your store appear in the answer? It runs configurable prompts across all major AI providers, detects brand signals in responses, and scores your visibility from 0 to 100 with a letter grade.
Table of contents
- What it measures
- Supported AI providers
- Requirements
- Installation
- Quick start
- Admin Panel
- CLI usage
- Full configuration reference
- Setup guides
- Scoring explained
- How to improve your score
- Integration with angeo/module-aeo-audit
- Related modules
What it measures
Each AI query result is analysed for five signals:
| Signal | Description |
|---|---|
| Mentioned | Your brand name appears in the AI response |
| Recommended | AI actively suggests your store as a destination |
| URL Cited | Your domain is included in the answer |
| 1st Position | Your store is the first recommendation |
| Positive Sentiment | Response tone about your brand is positive |
Each signal has a configurable weight. The overall score is a weighted average across all successful query results, converted to 0–100 and graded A–F.
Two measurement modes (since 2.0)
AI assistants answer in two fundamentally different ways, and they measure different things:
- Training recall (default) — the model answers from what it memorised during training. Fast and cheap, but months out of date and blind to your latest content and backlinks.
- Live web search (grounded toggle) — the model actually searches the web before answering, exactly like a real ChatGPT / Gemini / Claude user's session. This is what "AI search visibility" really means.
Enable Live Web Search per provider (ChatGPT, Claude, Gemini; Perplexity is always live, Groq never is). Every result records which mode produced it, and the report reports the mix rather than averaging the two silently.
Share of voice (since 2.0)
A visibility score in isolation is hard to act on. Add competitors to the watch-list (Name | domain.tld per line) and every answer to "what are the best stores for X?" — which already names the competition — is mined for who else shows up. The report ranks your brand against each competitor: you appear in 20% of answers, competitor X in 80% names the actual problem an abstract "40/100" hides.
Supported AI providers
| Provider | Models | Cost | Notes |
|---|---|---|---|
| Groq | llama-3.3-70b-versatile, mixtral-8x7b | Free | Best starting point — 14,400 req/day, no card |
| Perplexity | sonar, sonar-pro, sonar-deep-research | Paid | Always live web search — most realistic signal |
| OpenAI | gpt-4.1, gpt-4.1-mini, gpt-4o | Paid | Optional live search via Responses API web_search |
| Anthropic Claude | claude-sonnet-4-6, claude-haiku-4-5 | Paid | Optional live search via web_search tool |
| Google Gemini | gemini-2.5-flash-preview, gemini-2.0-flash | Free tier + paid | Optional Grounding with Google Search |
Extending providers (since 2.0): providers are wired as a di.xml array. Add your own (Mistral, DeepSeek, a local Ollama, …) by implementing
Angeo\AeoBrandVisibility\Api\AiProviderInterfaceand appending one<item>to theprovidersargument ofBrandVisibilityService— no core changes.
Per-store, alerting, API (since 3.0)
- Per-store-view scoping — brand identity, competitors and languages are read at store scope, so a multi-market Magento install gets an independent score, trend and alerting baseline per locale. The scheduled cron runs once per enabled store view.
- Email alerts — a scheduled run that drops past a threshold, or a competitor newly overtaking you in share of voice, emails your team. Configured under Brand Visibility → Alerting; fires on cron/CLI only.
- REST API —
GET /V1/angeo/brand-visibility/latest(and…/latest/store/:storeId) returns the newest summary for headless storefronts and dashboards. - LLM-judge sentiment — optionally let the cheapest configured model classify sentiment in context instead of phrase packs; falls back automatically on failure.
- Evidence tie-in with
angeo/module-aeo-auditv4 — when visibility is weak and your store's own instrumentation shows AI search crawlers never arrived, the audit checker points you at the WAF instead of at your content.
Enable one or more providers. Each active provider runs all configured prompts, and results are aggregated into a single score.
Requirements
- PHP 8.2, 8.3, or 8.4
- Magento 2.4.6 / 2.4.7 / 2.4.8 (Adobe Commerce / Mage-OS supported)
angeo/module-aeo-audit^4.0 (the v3 evidence tie-in uses the v4 bot-hit layer)ext-curl
Compatibility note: 3.x requires
angeo/module-aeo-audit^4.0 for the evidence tie-in. If you are on the audit module's v3.x, pin this module to^2.0, which requires^3.0 || ^4.0.
Installation
composer require angeo/module-aeo-brand-visibility
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Quick start
Step 1 — Configure your brand
Go to Stores → Configuration → Angeo AEO → Brand Visibility → General:
- Brand Name → your store name as AI systems know it (e.g.
Angeo) - Brand Domain → your domain without protocol (e.g.
angeo.dev) - Store Category → what you sell (e.g.
Magento development tools)
Step 2 — Enable a free provider (Groq)
Go to Groq Settings:
- Get a free API key at console.groq.com — no credit card
- Enable Groq →
Yes - Groq API Key → paste your
gsk_...key - Save Config
Step 3 — Run your first audit
bin/magento angeo:aeo:brand-visibility
Or from Admin Panel: Marketing → Angeo AEO → Brand Visibility → Run Audit
Admin Panel
Marketing → Angeo AEO → Brand Visibility
Run Audit
The main dashboard with:
- Score ring — overall score 0–100 with letter grade (A–F)
- Signal breakdown — mention rate, recommendation rate, URL citation rate, 1st position rate, positive sentiment rate
- Results table — per-provider, per-prompt responses with detected signals highlighted
- Action plan — prioritised recommendations to improve your score
- Single Query Tester — test one provider + one prompt without saving to history
Audit History
Grid view of all past audit runs with:
- Date, brand, score (colour-coded), grade (badge), triggered by, query count, error count
- Signal pills showing signal rates at a glance
- Click any row action → View for full detail page with raw AI responses
Configuration
Stores → Configuration → Angeo AEO → Brand Visibility
CLI usage
# Full audit — all enabled providers, all enabled prompts
bin/magento angeo:aeo:brand-visibility
# Force fresh queries — bypass cache
bin/magento angeo:aeo:brand-visibility --refresh
# Test a single provider
bin/magento angeo:aeo:brand-visibility --provider=groq
# Test a single provider + specific prompt
bin/magento angeo:aeo:brand-visibility --provider=chatgpt --prompt=brand_direct
# Output as JSON (useful for CI pipelines)
bin/magento angeo:aeo:brand-visibility --format=json
# CI mode — exit code 1 if score below threshold
bin/magento angeo:aeo:brand-visibility --fail-on=70
| Option | Values | Description |
|---|---|---|
--refresh / -r |
flag | Bypass cache, force live queries |
--provider |
chatgpt claude perplexity gemini groq |
Test one provider only |
--prompt |
recommendation category brand_direct product_search comparison gift_guide |
Test one prompt type only |
--format |
table json markdown |
Output format. Default: table |
--fail-on |
0–100 |
Exit 1 if overall score is below this value |
Full configuration reference
Path: Stores → Configuration → Angeo AEO → Brand Visibility
General
| Field | Default | Description |
|---|---|---|
| Brand Name | (store name) | Your brand name as AI systems know it |
| Brand Domain | — | Your domain without protocol (e.g. angeo.dev). Used for URL citation detection. |
| Brand Keywords | — | Comma-separated aliases the AI may use to refer to your brand |
| Store Category | — | What you sell (e.g. Magento 2 development tools). Used in prompts. |
| Top Products / Services | — | Newline-separated product or service names for product search prompts |
| Cache Results (hours) | 12 | How long to cache audit results. 0 = always run live. |
| Enable Cron | No | Run automatically on a schedule |
AI Providers
Each provider has its own section. Enable the ones you have API keys for.
ChatGPT (OpenAI)
| Field | Default | Description |
|---|---|---|
| Enable ChatGPT | No | |
| API Key | — | Starts with sk-. Stored encrypted. |
| Model | gpt-4.1 | gpt-4.1-mini is fastest and cheapest. |
| Max Tokens | 800 | Maximum response length. |
| Request Timeout (s) | 30 |
Claude (Anthropic)
| Field | Default | Description |
|---|---|---|
| Enable Claude | No | |
| API Key | — | Starts with sk-ant-. Stored encrypted. |
| Model | claude-sonnet-4-6 | claude-haiku-4-5 is fastest and cheapest. |
| Max Tokens | 800 | |
| Request Timeout (s) | 60 |
Perplexity
| Field | Default | Description |
|---|---|---|
| Enable Perplexity | No | |
| API Key | — | Stored encrypted. |
| Model | sonar | sonar-pro for deeper web search. sonar-deep-research for most thorough results. |
| Max Tokens | 800 | |
| Request Timeout (s) | 60 | Perplexity performs live web searches — may be slower. |
Note: Perplexity uses live web search, making it the most realistic indicator of actual AI visibility. It reflects what customers would see today, not what was in training data months ago.
Gemini (Google)
| Field | Default | Description |
|---|---|---|
| Enable Gemini | No | |
| API Key | — | Stored encrypted. |
| Model | gemini-2.5-flash-preview-05-20 | gemini-2.0-flash has a free tier. |
| Max Tokens | 800 | |
| Request Timeout (s) | 30 |
Groq (Free)
| Field | Default | Description |
|---|---|---|
| Enable Groq | No | |
| API Key | — | Starts with gsk_. No credit card required. |
| Model | llama-3.3-70b-versatile | Best quality on free tier. |
| Max Tokens | 800 | |
| Request Timeout (s) | 30 |
Free tier: 30 RPM, 14,400 requests/day.
Query Prompts
Six prompt types are available. Enable or disable each individually.
| Prompt Key | Example query sent to AI |
|---|---|
recommendation |
"What are the best online stores to buy [category]?" |
category |
"Where can I buy [category] online?" |
brand_direct |
"Tell me about [brand] — what do they sell and what is their website?" |
product_search |
"I'm looking for [top products] online. Which stores do you recommend?" |
comparison |
"Compare [brand] with other [category] stores online." |
gift_guide |
"Which online stores have the best [category] for gifts?" |
Additional settings:
| Field | Default | Description |
|---|---|---|
| Queries per Provider | 3 | How many prompts to run per enabled provider per audit |
| Delay Between Queries (ms) | 500 | Rate limiting delay between individual API calls |
| System Prompt | (default) | Instructions sent to each AI model before the query |
| Custom Prompts | — | Additional prompts, one per line, format: key: prompt text |
Scoring
Signal weights determine the contribution of each detected signal to the overall score:
| Signal | Default Weight |
|---|---|
| 1st Position | 2.0 |
| Recommended | 1.5 |
| URL Cited | 1.5 |
| Mentioned | 1.0 |
| Positive Sentiment | 0.5 |
Grade thresholds:
| Score | Grade |
|---|---|
| 90–100 | A |
| 75–89 | B |
| 60–74 | C |
| 40–59 | D |
| 0–39 | F |
Cron
| Field | Default | Description |
|---|---|---|
| Enable Cron | No | Run audit automatically on a schedule |
| Schedule | 0 6 * * * |
Standard cron expression. Default: daily at 6:00 AM. |
Results from cron runs appear in Audit History with triggered_by: cron.
Setup guides
Groq API key (free)
- Go to console.groq.com — create an account, no credit card required
- API Keys → Create API key
- Copy the key (starts with
gsk_) - In Magento: Stores → Configuration → Angeo AEO → Brand Visibility → Groq Settings → API Key
OpenAI API key
- Go to platform.openai.com → sign in or create account
- API keys → Create new secret key
- Copy the key (starts with
sk-) — shown only once - In Magento: ... → ChatGPT Settings → API Key
Anthropic Claude API key
- Go to console.anthropic.com → create account
- API Keys → Create Key
- Copy the key (starts with
sk-ant-) - In Magento: ... → Claude Settings → API Key
Google Gemini API key
- Go to aistudio.google.com/app/apikey
- Create API key in new project
- Copy the key
- In Magento: ... → Gemini Settings → API Key
Perplexity API key
- Go to perplexity.ai/settings/api
- Generate → copy the key
- In Magento: ... → Perplexity Settings → API Key
Scoring explained
Each AI query produces a BrandQueryResult with five boolean signals. Signals are weighted and averaged:
query_score = sum(signal_weight for each detected signal) /
sum(all_signal_weights) * 100
The overall score is the average of all successful query scores. Failed queries (API errors) are excluded from the average.
Example with default weights:
- 1st Position detected → +2.0
- Recommended detected → +1.5
- URL Cited not detected → 0
- Mentioned detected → +1.0
- Positive Sentiment detected → +0.5
query_score = (2.0 + 1.5 + 1.0 + 0.5) / (2.0 + 1.5 + 1.5 + 1.0 + 0.5) * 100
= 5.0 / 6.5 * 100 = 76.9 → Grade B
How to improve your score
| Signal missing | Root cause | Fix |
|---|---|---|
| Not mentioned | AI has no knowledge of your brand | Publish content that AI systems crawl: Dev.to, Reddit, GitHub |
| URL not cited | Domain not in AI training data or live index | Install angeo/module-llms-txt to give AI systems a structured map of your site |
| Not recommended | No authority signals in AI-accessible content | Add Product and Organization JSON-LD via angeo/module-rich-data |
| Not 1st position | Competitors have stronger AI presence | Increase external mentions: guest posts, Packagist downloads, GitHub stars |
| Negative sentiment | Poor reviews or negative coverage | Address public feedback; ensure AI-crawlable content is positive |
Run bin/magento angeo:aeo:audit for a full 15-signal technical AEO audit to identify and fix the infrastructure issues that block AI indexing.
Integration with angeo/module-aeo-audit
When angeo/module-aeo-audit v3.0+ is installed (required dependency), this
module adds a brand_visibility checker to the AEO audit pipeline as the
16th signal alongside the 15 built-in ones.
# Full 16-signal audit including brand visibility
bin/magento angeo:aeo:audit
# Skip brand visibility (saves API calls) — runs only the 15 built-in technical checks
bin/magento angeo:aeo:audit --category=technical,feed
# Run only live signals (this checker — live_signal category is reserved for third-party live checks)
bin/magento angeo:aeo:audit --category=live_signal
Brand visibility is registered with:
- Category:
live_signal— calls external APIs - Severity:
critical— headline AEO metric - Weight: 1.0 — top-tier signal in the score
Pass/warn/fail status is driven by your configured score thresholds
(default pass = 80, warn = 60).
Custom-checker authors
This module is the canonical example of how to extend the audit pipeline.
v3 checker contract:
public function check(\Magento\Store\Api\Data\StoreInterface $store): CheckResult;
public function getCategory(): string; // CheckerInterface::CATEGORY_*
public function getSeverity(): string; // CheckerInterface::SEVERITY_*
Extending \Angeo\AeoAudit\Model\Checker\AbstractChecker is the easiest
path — you get HttpCache + StoreUrlSampler + JSON-LD parsing
helpers + result factory methods for free.
Related modules
| Module | Purpose |
|---|---|
angeo/module-aeo-audit |
15-signal CLI audit — robots/llms/schema/UCP/feeds/etc. |
angeo/module-llms-txt |
Auto-generates llms.txt and llms.jsonl |
angeo/module-rich-data |
Product, Organization, FAQPage JSON-LD schema |
angeo/module-openai-product-feed |
ChatGPT Shopping product feed |
angeo/module-ucp |
Universal Commerce Protocol /.well-known/ucp |
angeo/module-ai-description-updater |
Bulk AI product description generation |
Security & data handling
This module talks to external AI APIs and renders their responses in the admin
panel, so it follows defensive defaults:
- API keys for every provider (ChatGPT, Claude, Perplexity, Gemini, Groq)
are stored with Magento'sMagento\Config\Model\Config\Backend\Encrypted
backend model and rendered asobscurefields. They are never written to
logs. The Gemini key is sent in thex-goog-api-keyrequest header rather
than the URL query string, so it cannot leak into proxy or access logs. - Outbound HTTP is HTTPS-only and does not follow redirects
(CURLOPT_PROTOCOLS/CURLOPT_REDIR_PROTOCOLSpinned to HTTPS,
CURLOPT_FOLLOWLOCATIONdisabled), with an explicit connect timeout. - Admin AJAX endpoints are protected by ACL
(Angeo_AeoBrandVisibility::run) and Magento's form key; mutating actions
are POST-only. Unexpected exceptions are logged to the module log and only a
generic message is returned to the browser. - Output escaping: server-rendered templates use
escapeHtml/escapeUrl,
and the JS that injects AI-provider text into the admin UI routes every
untrusted value through a strict HTML/attribute escaper before insertion. - Serialization uses Magento's
SerializerInterfacethroughout (no native
json_encode/json_decodeand no PHPserialize()of untrusted data),
avoiding object-injection surfaces. - Log contents: when Enable Logging is on, truncated prompt and response
previews are written tovar/log/angeo_aeo_brand_visibility.log. Keep logging
off in production if your prompts may contain sensitive data.
License
MIT — free to use, modify, and distribute.
Author
Ievgenii Gryshkun · angeo.dev · [email protected]
Changelog
All notable changes to angeo/module-aeo-brand-visibility will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
[3.0.0] — 2026-07-03
The systems release: from a single-store measurement tool to a per-store,
alerting, API-exposed system with an evidence tie-in to the audit module.
Breaking: requires angeo/module-aeo-audit ^4.0 (was ^3.0||^4.0).
Added
- Per-store-view scoping. Brand name, domain, keywords, category,
competitors, analysis languages and query language are all read at store
scope.BrandVisibilityService::run()takes an optional$storeId; the
cache key, the persisted record (store_idcolumn) and the audit checker
all carry it. A multi-market install now gets an independent score, trend
and alerting baseline per locale. The scheduled cron iterates every store
view that enables the module at its own scope (falling back to a single
default-scope run — pre-3.0 behaviour — when none do). - Email alerting. When a scheduled run drops by more than the configured
threshold (default 10 points) versus the previous run for the same scope,
or a competitor newly overtakes you in share of voice,AlertDispatcher
emails the configured recipients. Alerts fire on cron/CLI runs only, never
on interactive admin previews. Configurable under Brand Visibility →
Alerting; ships an adminhtml email template. - REST API.
GET /V1/angeo/brand-visibility/latestand
…/latest/store/:storeIdreturn the newest persisted summary (score,
grade, brand, share-of-voice JSON, timestamp) for headless storefronts and
external dashboards. Backed byReportManagementInterface/
VisibilitySummaryInterface, guarded by theAngeo_AeoBrandVisibility::run
ACL resource. - Optional LLM-judge sentiment. Response Analysis → Sentiment Analysis
can switch from phrase packs to an LLM judge: the cheapest enabled provider
reads each answer in context and classifies sentiment as JSON. More
accurate across languages and paraphrase; falls back to phrase packs
automatically on any failure, so availability never depends on it. - Evidence tie-in with aeo-audit v4. When brand visibility is weak AND
the store's own bot-hit instrumentation shows the SEARCH-class crawlers
(OAI-SearchBot, PerplexityBot, …) never arrived, the checker stops guessing
and points the operator at thewaf_reality/ai_crawler_activity
signals — low visibility caused by a WAF/CDN blocking crawlers is a
different fix from thin content.
Changed
angeo/module-aeo-auditconstraint tightened to^4.0— the evidence
tie-in uses the v4 bot-hit resource and registry.BrandVisibilityService,ResponseAnalyzer,AuditResultRepositoryand
BrandVisibilityCheckergained optional?int $storeIdparameters
throughout. All are additive with null defaults — existing call sites keep
working.
Database
- New nullable
store_idcolumn (+ index) onangeo_brand_visibility_audit
(declarative schema — applied bysetup:upgrade). No data migration; older
rows carry a null store scope.
Upgrading from 2.x
- Ensure
angeo/module-aeo-auditis on^4.0, then
composer require angeo/module-aeo-brand-visibility:^3.0. bin/magento setup:upgrade && bin/magento setup:di:compile.- Optional: set per-store brand values, enable Alerting with recipients,
switch Sentiment Analysis to the LLM judge, and consume the REST
endpoint from your dashboard.
[2.0.0] — 2026-07-03
The measurement-validity release. Until now 4 of 5 providers measured
training recall — what a model memorised months ago — while the UI implied
live AI-search visibility. 2.0 closes that gap and adds the competitive
dimension. Breaking changes (see Upgrading below).
Added
- Grounded (live web search) mode per provider. ChatGPT via the Responses
API +web_searchtool, Gemini via Grounding with Google Search, Claude via
the server-sideweb_searchtool — the same retrieval real users get.
Toggle Live Web Search under each provider (default OFF; grounded calls
cost more and get a longer timeout). Perplexity is always grounded; Groq
never is. Each result records which mode produced it, and the report never
averages the two silently —groundingBreakdown()surfaces the mix. - Share of voice. A competitor watch-list (Response Analysis → Competitor
Watch-list,Name | domain.tldper line) turns "your score is 40" into
"you appear in 20% of answers, competitor X in 80%". The analyzer now
extracts every competitor mention and every domain cited in each answer;
BrandVisibilityReport::shareOfVoice()ranks brand vs competitors, persisted
in the newshare_of_voicecolumn and surfaced in the audit checker. - Structured citations. Providers return their source URLs as structured
data (ProviderResponse::$citations) instead of Perplexity smuggling them
into the text as a "Sources:" suffix. A citation of your own domain now
feedsurl_citeddirectly — being a cited source is the strongest
visibility outcome, and it is scored as such. - Repeats per prompt (1–5). LLM answers are stochastic even at low
temperature. Sampling each prompt N times and keeping the MEDIAN score /
majority-vote signals turns noisy single samples into stable trend points.
Default 1 (cost-neutral); 3 recommended for weekly tracking. A failed
attempt no longer poisons the rest; all-failed still yields a clean error
result. - Pluggable provider registry.
BrandVisibilityServicenow receives an
AiProviderInterface[]via di.xml. Third-party modules add a provider
(Mistral, DeepSeek, a local Ollama, …) with one di.xml<item>— no core
edits. Ships with the five built-ins wired inetc/di.xml.
Changed
AiProviderInterface(BC break).query()now returns a
ProviderResponse(text + citations + grounded) instead of a bare string,
and addssupportsGrounding()/isGrounded(). Any custom provider must be
updated.BrandVisibilityServiceconstructor (BC break). The five concrete
provider arguments are replaced by a singleprovidersarray (injected via
di.xml). Custom instantiation must pass the array.- Cache namespace bumped to
angeo_bv2_— the 2.0 payload shape must not
hydrate from 1.x cache entries. Old entries expire naturally; no action
needed.
Database
- New nullable
share_of_voicecolumn onangeo_brand_visibility_audit
(declarative schema — applied bysetup:upgrade). No data migration.
Upgrading from 1.3.x
composer require angeo/module-aeo-brand-visibility:^2.0bin/magento setup:upgrade && bin/magento setup:di:compile- If you wrote a custom AiProviderInterface implementation, update it to
returnProviderResponseand implement the two new methods. - If you instantiate
BrandVisibilityServiceyourself (not via DI),
pass providers as theprovidersarray argument. - Optional: add competitors under Response Analysis, enable Live Web
Search per provider, and set Repeats Per Prompt to 3 for stable trends.
[1.3.0] — 2026-07-02
Release hygiene + the multilingual analyzer. Drop-in upgrade from 1.2.x
(composer update, setup:upgrade, setup:di:compile) — no DB changes;
one config field renamed with a read fallback, saved values survive.
Added
- Multilingual response analysis. Recommendation and sentiment phrases
now come from per-language packs — English, Dutch, German, French and
Ukrainian (Service/Analysis/PhrasePack). AI assistants answer in the
shopper's language; before this release a Dutch "zeker aan te raden" or a
German "sehr empfehlenswert" scoredrecommended = false. Languages are
selectable under Response Analysis → Analysis Languages (empty = all
packs, the safe default). Adding a language is one array in PhrasePack. {{language}}prompt placeholder plus a Query Language config field
— probe AI models in the language of your market, not just English.- GitHub Actions CI (
.github/workflows/ci.yml): phpcs, PHPStan, PHPUnit
on PHP 8.2/8.3/8.4, and a Mage-OS mirror installability job. The
aeo-audit dependency resolves from GitHub until new tags reach Packagist. i18n/en_US.csv— base translation dictionary (46 admin strings).
Changed
- Unicode word-boundary brand matching. Brand name and keywords are now
matched as whole words ((?<![\p{L}\p{N}]) … (?![\p{L}\p{N}])), so the
brand "Geo" no longer matches inside "geography" and short keywords stop
firing on unrelated words. Domain matching intentionally remains
substring-based (domains are distinctive and live inside URLs). - Deterministic provider temperatures. Claude now sends an explicit
temperature: 0.2(previously unset → provider default ≈ 1.0); Gemini and
Groq aligned from 0.3 to 0.2. Visibility measurement needs the model's
most probable answer — creative variance was score jitter between runs. - "Queries Per Provider" renamed to "Max Prompts Per Provider" — the old
name described the cap incorrectly (it limits prompts; total queries =
prompts × providers). Values saved under the legacy path are still read. angeo/module-aeo-auditconstraint widened to^3.0||^4.0— compatible
with the aeo-audit 4.0.0 evidence-layer release.
Fixed
GroqProviderTest::testIsConfiguredWithApiKeynever mocked the enabled
flag and silently failed — it had never actually run (no CI existed).
Fixed; full suite green (63 tests).
[1.2.0] — 2026-06-12
Security hardening and code-quality release. No database or configuration
changes — upgrading from 1.1.x is drop-in (composer update, then
bin/magento setup:upgrade && bin/magento setup:di:compile).
Security
- Admin UI XSS hardening. The JavaScript escaper used when injecting
AI-provider responses into the Run/History/Single-Test panels now escapes
single quotes, backticks and slashes in addition to& < > ", making it safe
for both HTML-text and quoted-attribute contexts. All untrusted provider text
(raw responses, prompts, labels) is routed through it. - Gemini API key moved out of the URL. The key is now sent in the
x-goog-api-keyheader instead of the?key=query parameter, so it can no
longer appear in proxy logs, access logs or error messages. - Outbound HTTP locked down. The shared provider transport is now HTTPS-only
(CURLOPT_PROTOCOLS/CURLOPT_REDIR_PROTOCOLS), no longer follows redirects
(CURLOPT_FOLLOWLOCATIONdisabled — SSRF guard), and sets an explicit
CURLOPT_CONNECTTIMEOUT. - No exception detail leaks to the browser. Admin AJAX controllers
(Run,Plan,History/Data,History/ViewData) now log the full
exception to the dedicated module log and return a generic message. The
single-query diagnostic tool still surfaces the provider message (it is a
manual debugging aid and no longer key-bearing).
Changed
- All (de)serialization goes through Magento
SerializerInterface. Replaced
every nativejson_encode/json_decodecall (provider transport, audit
result model, history grid column, CLI--format=json) with the injected
serializer. The main service and repository now depend on the interface
rather than the concreteJsonclass. - Cache invalidation fixed. The audit cache key now includes the set of
enabled providers, their configured models and the system prompt, so toggling
a provider or switching a model no longer serves a stale report. Cache Results (hours) = 0now truly disables caching. Previously the
0value was swallowed and silently treated as 24h.- Provider list corrected in the CLI. Command description and the
--provideroption help now list all five providers
(chatgpt|claude|perplexity|gemini|groq).
Tests
BrandVisibilityServiceTestrewritten against the real service contract
(MagentoCacheInterface, real method names and constructor signature, real
serializer) covering guard clauses, cache hits, force-refresh and save-failure
resilience.GroqProviderTestupdated for the new serializer-aware constructor.
[1.1.1] — 2026-05-28
Changed — documentation only (no code changes)
angeo/module-aeo-audit v3.0.0 final release ships with 15 built-in
signals, not the 16 referenced in this module's v1.1.0 README. The
ai_bot_traffic checker was removed from aeo-audit during pre-release
security review (it encouraged broad read access on /var/log/nginx/,
didn't work on Cloud/containerised hosting, and was dominated by false
positives behind edge caches — see aeo-audit CHANGELOG "Considered and
rejected" for the full rationale).
This patch release synchronises documentation with the published aeo-audit
v3.0.0 counts:
- README: "17th signal alongside the 16 built-in ones" →
"16th signal alongside the 15 built-in ones" - README CLI examples: "Full 17-signal audit" → "Full 16-signal audit";
"16 built-in technical checks" → "15 built-in technical checks" - README CLI examples: "Run only live signals (this checker + AI bot
traffic)" → "Run only live signals (this checker —live_signal
category is reserved for third-party live checks)" - README Related modules: "16-signal CLI audit" → "15-signal CLI audit"
- README How-to-improve: "8-signal technical AEO audit" (stale since v2) →
"15-signal technical AEO audit"
No behaviour change. BrandVisibilityChecker continues to register
under CheckerInterface::CATEGORY_LIVE_SIGNAL (still a valid constant
in aeo-audit v3.0.0), and aeo-audit's documentation explicitly reserves
that category for this module. Upgrading from 1.1.0 → 1.1.1 is risk-free.
[1.1.0] — 2026-05-22
Compatibility — required for angeo/module-aeo-audit v3.0+
This release adapts BrandVisibilityChecker to the v3 CheckerInterface
introduced in angeo/module-aeo-audit 3.0.0. Without this update, attempting
to use brand-visibility v1.0.x with aeo-audit v3.x produces a fatal at boot:
Fatal error: Declaration of
Angeo\AeoBrandVisibility\Model\Checker\BrandVisibilityChecker::check(string $baseUrl)
must be compatible with
Angeo\AeoAudit\Api\CheckerInterface::check(Magento\Store\Api\Data\StoreInterface $store)
Changed
BrandVisibilityChecker::check()signature updated to accept
\Magento\Store\Api\Data\StoreInterface $store(wasstring $baseUrl).BrandVisibilityCheckernow extends\Angeo\AeoAudit\Model\Checker\AbstractChecker
instead of implementingCheckerInterfacedirectly — gets sharedHttpCache,
StoreUrlSampler, and result factory helpers automatically.- Replaced direct
new CheckResult(...)calls with the v3 named factories
($this->pass()/$this->warn()/$this->fail()) — these correctly
propagatecheckCode,weight,categoryandseverityinto the result. - The disabled-module case now returns WARN instead of the removed
STATUS_SKIP(the v3 status vocabulary is pass / warn / fail only). - Weight clamped from 1.5 → 1.0 to fit the v3 normalised-weight contract
(0.0–1.0). Brand visibility remains a top-tier signal because all
technical checks at 1.0 share the same weight. - The service-exception catch broadened from
\RuntimeExceptionto
\Throwable— covers\Errorand\LogicExceptionfrom upstream
provider client libraries.
Added
getCategory(): string→ returnsCATEGORY_LIVE_SIGNAL(external API).
Allowsbin/magento angeo:aeo:audit --category=technicalto skip the
brand check for fast cron runs.getSeverity(): string→ returnsSEVERITY_CRITICAL. Plays with
--fail-on-severity=criticalfor CI gates.detailsarray now surfaces full breakdown: score, grade, queries
run/ok, all four signal rates, cache flag, configured thresholds.- New unit test suite
Test/Unit/Model/Checker/BrandVisibilityCheckerTest
with 13 test cases covering signature compatibility, short-circuits,
threshold-driven outcomes, recommendation building.
Migration from 1.0.x
For typical users — composer update angeo/module-aeo-brand-visibility.
The DI wiring in etc/di.xml is unchanged (the AuditRunner argument
extension is identical between v2 and v3 of aeo-audit).
If you pinned angeo/module-aeo-audit to v2.x:
- Keep
angeo/module-aeo-brand-visibilitypinned to^1.0, OR - Update both to v3.0+ together.
[1.0.0] — 2026-04-15
Added
- Initial release.
- Live AI brand audit across ChatGPT, Claude, Perplexity, Gemini and Groq.
- Five-signal scoring (Mentioned / Recommended / URL Cited / First Result / Sentiment).
- Configurable prompts, models, max_tokens, temperature per provider.
- Admin UI: History grid, Detail view, Run-Audit form, Plan preview.
- CLI:
bin/magento angeo:aeo:brand-visibility. - Cron support with cache TTL.
- Auto-registers as the 9th checker in
angeo/module-aeo-auditvia DI.
| Version | Stability | QA Status | Compatibility | Released |
|---|---|---|---|---|
| 4.0.1 | stable | Fail | Magento 2.4.7-2.4.9 Details | 2026-09-17 19:30:00 |
| 4.0.0 | stable | Fail | Not compatible Details | 2026-09-06 16:44:57 |
| 3.0.0 | stable | Not tested | Not yet tested Details | 2026-09-06 16:43:51 |
| 2.0.0 | stable | Not tested | Not yet tested Details | 2026-09-06 16:42:55 |
| 1.2.0 | stable | Fail | Magento 2.4.7-2.4.8 Details | 2026-06-14 18:51:44 |
| 1.1.1 | stable | Fail | Magento 2.4.7-2.4.8 Details | 2026-05-28 19:14:06 |
| 1.1.0 | stable | Not tested | Not yet tested Details | 2026-05-28 19:09:11 |
| 1.0.0 | stable | Not tested | Not yet tested Details | 2026-05-16 19:15:52 |
Requires 11
| Package | Constraint |
|---|---|
| angeo/module-aeo-audit | ^3.0||^4.0 |
| magento/framework | ^103.0 |
| magento/framework-message-queue | ^100.4 |
| magento/module-backend | ^102.0 |
| magento/module-catalog | ^104.0 |
| magento/module-config | ^101.2 |
| magento/module-cron | ^100.4 |
| magento/module-email | ^101.1 |
| magento/module-store | ^101.1 |
| magento/module-ui | ^101.2 |
| php | ~8.1.0||~8.2.0||~8.3.0||~8.4.0||~8.5.0 |
Requires-dev 4
| Package | Constraint |
|---|---|
| bitexpert/phpstan-magento | ^0.43 |
| magento/magento-coding-standard | ^40.0 || ^41.0 |
| phpstan/phpstan | ^2.0 |
| phpunit/phpunit | ^10.5 |
Suggests 3
| Package | Reason |
|---|---|
| angeo/module-llms-txt | Publish llms.txt to improve brand recall in AI training pipelines. |
| angeo/module-openai-description-updater | Improve product content quality to increase AI citation rate. |
| angeo/module-rich-data | Improve Organization + Product schema to strengthen entity recognition. |
No QA results yet
QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.
More from angeo
View vendorMagento 2 module for AI Engine Optimization (AEO). Generates spec-compliant llms.txt and llms-full.txt per llmstxt.org standard, plus streaming JSONL for vector indexing. Multi-store, multi-website, CLI, cron, async admin UI, Page Builder-aware sanitization, customer-group pricing, atomic writes, ETag/Cache-Control, .md mirrors.
Magento 2 module for AI Engine Optimization (AEO). Injects AI crawler rules (OAI-SearchBot, GPTBot, ChatGPT-User, PerplexityBot, Perplexity-User, Google-Extended, ClaudeBot, anthropic-ai, Claude-User, Applebot, cohere-ai, Amazonbot, Meta-ExternalAgent) into robots.txt — without overwriting your existing configuration. Supports per-bot Allow/Disallow lists, Crawl-delay, Sitemap directives, multi-store, and a public Api\RobotsStatusInterface for cross-module integration with angeo/module-aeo-audit.
Magento 2 AEO (AI Engine Optimization) Audit. v3 covers 15 signals — robots.txt AI bots, llms.txt + llms.jsonl, Product / Organization / FAQ schema, merchant return + shipping policies, sitemap.xml, UCP profile, AI product feed, OG tags, canonical + hreflang, JSON-LD quality, well-known endpoint matrix, Core Web Vitals via CrUX. Score Trend dashboard, Admin UI, cron, dynamic fix commands, dependency-injected extension point for custom checkers.
Spec-compliant Universal Commerce Protocol (UCP) profile generator for Magento 2. Generates /.well-known/ucp at protocol version 2026-04-08 with ECDSA P-256 signing keys, declared capabilities, and proper cache headers. v0.1.x is profile-only — catalog, cart, checkout endpoints land in later releases.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.