# AEO Brand Visibility for Magento 2  -  module reference

> Measure if ChatGPT, Claude, Perplexity, Gemini and Groq name your Magento store. Setup, providers, prompts, scoring, alerts, CLI and cost per run.

Source: https://angeo.dev/docs/modules/aeo-brand-visibility/
Updated: 2026-10-17

Module reference

# AEO Brand Visibility for Magento 2  -  module reference

Covers `angeo/module-aeo-brand-visibility` 4.0.1 - Checked 16 October 2026 - MIT licensed

**AEO Brand Visibility** asks AI assistants the questions your shoppers ask  -  "where can I buy X?", "what are the best stores for Y?"  -  and reads the answers. It then scores how visible your brand is.

It supports ChatGPT, Claude, Perplexity, Gemini and Groq. Every question is asked several times, because AI answers change from one call to the next. So the score comes with a margin of error, not a single lucky number.

The module plugs into [AEO Audit](https://angeo.dev/docs/modules/aeo-audit/) as a live signal. It also runs on its own from the admin panel, from cron or from the command line.

Package`angeo/module-aeo-brand-visibility`Latest version4.0.1Magento2.4.xPHP8.1 - 8.5LicenseMIT, freeLinks[GitHub](https://github.com/angeo-dev/module-aeo-brand-visibility) - [Packagist](https://packagist.org/packages/angeo/module-aeo-brand-visibility) - [Changelog](https://github.com/angeo-dev/module-aeo-brand-visibility/blob/main/CHANGELOG.md) - [Module page](https://angeo.dev/modules/aeo-brand-visibility/)

**On this page**

1. What it measures
2. Reading the score honestly
3. Requirements
4. Installation
5. Setting it up
6. Command line
7. Admin panel and permissions
8. Cost
9. Configuration reference
10. Cron and stored data
11. Adding a provider
12. FAQ
13. Related

## What it measures

Each answer is scored on five signals:

| Signal | Question | Default weight |

| Mentioned | Does the answer name the brand? | 1.0 |
| Recommended | Is the brand suggested, not only listed? | 1.5 |
| URL cited | Is your domain quoted? | 1.5 |
| First position | Is the brand named before competitors? | 2.0 |
| Positive tone | Is the wording around the brand positive? | 0.5 |

**Negative tone** has no weight. It takes points away instead, because "avoid this shop" is worse than no mention.

On top of that, the report shows:

- **Share of voice**  -  your weight against every tracked competitor in the same answers.
- **Win rate**  -  how often you are named before every competitor.
- **Accuracy issues**  -  answers that link your brand to a website you do not own.

## Reading the score honestly

Two settings decide if the number is useful.

**Grounding.** A model that answers from memory repeats training data that is months old. Nothing you change this quarter moves it. A *grounded* model searches the live web first, so it reacts to your work within days. Perplexity is always grounded. ChatGPT, Claude and Gemini can be grounded per provider. Groq cannot.

**Sampling.** Each provider and prompt pair is asked N times (3 by default). The result is a mean with a 95 % confidence margin, shown as `±`. A change smaller than the margin is noise. Alerts ignore it.

## Requirements

| Magento | 2.4.x (Open Source, Mage-OS or Adobe Commerce)  -  `magento/framework ^103.0` |
| PHP | 8.1 - 8.5  -  `~8.1.0||~8.2.0||~8.3.0||~8.4.0||~8.5.0` |
| Other angeo modules | [angeo/module-aeo-audit](https://angeo.dev/docs/modules/aeo-audit/) `^3.0||^4.0` |

You also need at least one AI provider API key, and a running message queue consumer (or the *Inline* run mode).

## Installation

```
composer require angeo/module-aeo-brand-visibility
bin/magento module:enable Angeo_AeoBrandVisibility
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
```

Start the consumer that runs queued audits:

```
bin/magento queue:consumers:start angeoBrandVisAuditRun
```

On most stores `consumers_runner` in `app/etc/env.php` starts it from cron. If your hosting does not run consumers, set **Run Mode** to *Inline*. A full run then happens inside the admin request and can hit a PHP or gateway timeout.

## Setting it up

1. Open **Stores -> Configuration -> Angeo AEO -> Brand Visibility (AI Models)**.
2. In **General**, enable the module and fill in **Store Category**  -  what you sell, in two or three words. This one field moves the score more than any other. Without it, prompts fall back to generic phrases that big marketplaces always win.
3. Enable one or more providers and paste their API keys. Keys are stored encrypted.
4. For a score that reacts to your work, turn on **Answer from live web search** for at least one provider, or enable Perplexity.
5. Add competitors under **Competitors -> Tracked Competitors**, one per line.
6. Start a run from **Marketing -> AEO Brand Visibility -> Dashboard**.

Almost every setting works per website and per store view, so a multi-brand store can measure each brand on its own.

### Providers

| Provider | Grounded answers | Note |

| ChatGPT | Optional | Needs a search-capable model, such as `gpt-4o-search-preview` |
| Claude | Optional | Uses the server-side web search tool, billed per search |
| Perplexity | Always | The fastest-reacting signal of the five |
| Gemini | Optional | Uses Google Search as a tool |
| Groq | No | Free tier, a memory-only baseline |

Model names change often. Pick the closest option and check the field again after a provider release.

### Prompts

There are six built-in prompts, each with an on/off switch and optional override text: best stores in category, where to buy, tell me about this brand, product search, compare with competitors, and gift guide. Add your own under **Custom Prompts**, one per line, as `key: prompt text`.

You can use these placeholders: `{{brand}}`, `{{domain}}`, `{{category}}`, `{{products}}`.

### Languages

Phrase matching supports English, Ukrainian, Dutch, German, French and Spanish. English is always matched as well, because AI answers often mix languages.

For the accuracy check, add your country domains under **Extra Top-Level Domains** (for example `nl`, `de`, `co.uk`). Otherwise a wrong country domain linked to your brand is not flagged.

### Alerts

An alert fires when the score drops by more than the set number of points against the recent average **and** the drop is bigger than the margin of error. It also fires when a competitor outranks you, or when negative tone or a wrong URL shows up. Alerts go by email, by webhook, or both. The webhook must use HTTPS. Private and reserved addresses are refused unless you allow them.

## Command line

```
# Full audit for the default scope
bin/magento angeo:aeo:brand-visibility

# One store view, skip the cache, print the action plan
bin/magento angeo:aeo:brand-visibility --store=2 --refresh --plan

# Machine-readable output
bin/magento angeo:aeo:brand-visibility --format=json

# One provider and one prompt, with the raw answer
bin/magento angeo:aeo:brand-visibility --provider=perplexity --prompt=brand_direct

# Fail a CI pipeline below a score
bin/magento angeo:aeo:brand-visibility --fail-on=50
```

| Option | Meaning |

| `--store` | Store view id (default `0`) |
| `--refresh`, `-r` | Skip the result cache |
| `--provider` | Ask one provider instead of the full audit |
| `--prompt` | Prompt key to use with `--provider` |
| `--format` | `table`, `json` or `markdown` |
| `--plan` | Print the action plan |
| `--fail-on` | Exit code 1 below this score |

## Admin panel and permissions

**Marketing -> AEO Brand Visibility** has a **Dashboard** (start a run, read each answer, build an action plan) and **Audit History** (a grid with filters, a detail page and CSV export per run).

Access is split into four permissions. You can give an agency read access without the right to spend money on API calls.

| ACL resource | Title in admin |

| `Angeo_AeoBrandVisibility::root` | AEO Brand Visibility |
| `Angeo_AeoBrandVisibility::view` | View Reports |
| `Angeo_AeoBrandVisibility::run` | Run Audit |
| `Angeo_AeoBrandVisibility::export` | Export Results |
| `Angeo_AeoBrandVisibility::config` | Configuration |

## Cost

One run costs `providers × prompts × samples` API calls. Three providers, three prompts and three samples make 27 calls. Weekly runs on small models cost cents. Grounded searches on large models cost more. Start with three samples and one grounded provider.

## Configuration reference

All settings are under **Stores -> Configuration -> Angeo AEO -> Brand Visibility (AI Models)**. The table shows each field, its config path (for `bin/magento config:set`) and its default value.

General (9)

| Setting | Config path | Default |

| Enable Brand Visibility | `angeo_brand_vis/general/enabled` | No |
| Run Mode | `angeo_brand_vis/general/run_mode` | `queue` |
| Brand Name | `angeo_brand_vis/general/brand_name` |  -  |
| Brand Domain | `angeo_brand_vis/general/brand_domain` |  -  |
| Brand Aliases | `angeo_brand_vis/general/brand_keywords` |  -  |
| Store Category | `angeo_brand_vis/general/store_category` |  -  |
| Top Products | `angeo_brand_vis/general/top_products` |  -  |
| Cache Lifetime (hours) | `angeo_brand_vis/general/cache_ttl_hours` | `24` |
| Log Prompts and Answers | `angeo_brand_vis/general/log_enabled` | No |

ChatGPT (OpenAI) (7)

| Setting | Config path | Default |

| Enable | `angeo_brand_vis/chatgpt/enabled` | No |
| API Key | `angeo_brand_vis/chatgpt/api_key` |  -  (stored encrypted) |
| Model | `angeo_brand_vis/chatgpt/model` | `gpt-4.1-mini` |
| Answer from live web search | `angeo_brand_vis/chatgpt/grounding` | No |
| Max Answer Tokens | `angeo_brand_vis/chatgpt/max_tokens` | `800` |
| Temperature | `angeo_brand_vis/chatgpt/temperature` | `0.3` |
| Timeout (seconds) | `angeo_brand_vis/chatgpt/timeout` | `60` |

Claude (Anthropic) (7)

| Setting | Config path | Default |

| Enable | `angeo_brand_vis/claude/enabled` | No |
| API Key | `angeo_brand_vis/claude/api_key` |  -  (stored encrypted) |
| Model | `angeo_brand_vis/claude/model` | `claude-sonnet-4-6` |
| Answer from live web search | `angeo_brand_vis/claude/grounding` | No |
| Max Answer Tokens | `angeo_brand_vis/claude/max_tokens` | `800` |
| Temperature | `angeo_brand_vis/claude/temperature` | `0.3` |
| Timeout (seconds) | `angeo_brand_vis/claude/timeout` | `90` |

Perplexity (6)

| Setting | Config path | Default |

| Enable | `angeo_brand_vis/perplexity/enabled` | No |
| API Key | `angeo_brand_vis/perplexity/api_key` |  -  (stored encrypted) |
| Model | `angeo_brand_vis/perplexity/model` | `sonar` |
| Max Answer Tokens | `angeo_brand_vis/perplexity/max_tokens` | `800` |
| Temperature | `angeo_brand_vis/perplexity/temperature` | `0.2` |
| Timeout (seconds) | `angeo_brand_vis/perplexity/timeout` | `60` |

Gemini (Google) (7)

| Setting | Config path | Default |

| Enable | `angeo_brand_vis/gemini/enabled` | No |
| API Key | `angeo_brand_vis/gemini/api_key` |  -  (stored encrypted) |
| Model | `angeo_brand_vis/gemini/model` | `gemini-2.0-flash` |
| Answer from live web search | `angeo_brand_vis/gemini/grounding` | No |
| Max Answer Tokens | `angeo_brand_vis/gemini/max_tokens` | `800` |
| Temperature | `angeo_brand_vis/gemini/temperature` | `0.3` |
| Timeout (seconds) | `angeo_brand_vis/gemini/timeout` | `60` |

Groq (6)

| Setting | Config path | Default |

| Enable | `angeo_brand_vis/groq/enabled` | No |
| API Key | `angeo_brand_vis/groq/api_key` |  -  (stored encrypted) |
| Model | `angeo_brand_vis/groq/model` | `llama-3.3-70b-versatile` |
| Max Answer Tokens | `angeo_brand_vis/groq/max_tokens` | `800` |
| Temperature | `angeo_brand_vis/groq/temperature` | `0.3` |
| Timeout (seconds) | `angeo_brand_vis/groq/timeout` | `30` |

Queries (18)

| Setting | Config path | Default |

| Samples per Query | `angeo_brand_vis/queries/samples` | `3` |
| Maximum Prompts per Provider | `angeo_brand_vis/queries/max_prompts` | `3` |
| Delay Between Calls (ms) | `angeo_brand_vis/queries/delay_between_ms` | `600` |
| Retries per Call | `angeo_brand_vis/queries/max_retries` | `2` |
| System Prompt | `angeo_brand_vis/queries/system_prompt` |  -  |
| Prompt: Best stores in category | `angeo_brand_vis/queries/enable_recommendation` | Yes |
| Override text | `angeo_brand_vis/queries/prompt_recommendation` |  -  |
| Prompt: Where to buy | `angeo_brand_vis/queries/enable_category` | Yes |
| Override text | `angeo_brand_vis/queries/prompt_category` |  -  |
| Prompt: Tell me about this brand | `angeo_brand_vis/queries/enable_brand_direct` | Yes |
| Override text | `angeo_brand_vis/queries/prompt_brand_direct` |  -  |
| Prompt: Product search | `angeo_brand_vis/queries/enable_product_search` | No |
| Override text | `angeo_brand_vis/queries/prompt_product_search` |  -  |
| Prompt: Compare with competitors | `angeo_brand_vis/queries/enable_comparison` | No |
| Override text | `angeo_brand_vis/queries/prompt_comparison` |  -  |
| Prompt: Gift guide | `angeo_brand_vis/queries/enable_gift_guide` | No |
| Override text | `angeo_brand_vis/queries/prompt_gift_guide` |  -  |
| Custom Prompts | `angeo_brand_vis/queries/custom_prompts` |  -  |

Competitors (1)

| Setting | Config path | Default |

| Tracked Competitors | `angeo_brand_vis/competitors/list` |  -  |

Analysis (2)

| Setting | Config path | Default |

| Analysis Language | `angeo_brand_vis/analysis/language` | `auto` |
| Extra Top-Level Domains | `angeo_brand_vis/analysis/extra_tlds` |  -  |

Scoring (8)

| Setting | Config path | Default |

| Weight: Mentioned | `angeo_brand_vis/scoring/weight_mentioned` | `1.0` |
| Weight: Recommended | `angeo_brand_vis/scoring/weight_recommended` | `1.5` |
| Weight: URL Cited | `angeo_brand_vis/scoring/weight_url_cited` | `1.5` |
| Weight: First Position | `angeo_brand_vis/scoring/weight_first_result` | `2.0` |
| Weight: Positive Tone | `angeo_brand_vis/scoring/weight_positive_sentiment` | `0.5` |
| Negative Tone Penalty | `angeo_brand_vis/scoring/negative_penalty` | `0.5` |
| Pass Threshold | `angeo_brand_vis/scoring/pass_threshold` | `60` |
| Warning Threshold | `angeo_brand_vis/scoring/warn_threshold` | `30` |

Alerts (5)

| Setting | Config path | Default |

| Enable Regression Alerts | `angeo_brand_vis/alerts/enabled` | No |
| Alert Recipient | `angeo_brand_vis/alerts/recipient` |  -  |
| Drop Threshold (points) | `angeo_brand_vis/alerts/drop_threshold` | `10` |
| Webhook URL | `angeo_brand_vis/alerts/webhook_url` |  -  |
| Allow Private Webhook Targets | `angeo_brand_vis/alerts/webhook_allow_private` | No |

Scheduled Runs (2)

| Setting | Config path | Default |

| Enable Schedule | `angeo_brand_vis/cron/enabled` | No |
| Cron Expression | `angeo_brand_vis/cron/schedule` | `0 5 * * 1` |

Data Retention (2)

| Setting | Config path | Default |

| Runs Kept per Store View | `angeo_brand_vis/retention/max_records_per_store` | `90` |
| Maximum Age (days) | `angeo_brand_vis/retention/max_age_days` | `365` |

## Cron and stored data

Scheduled runs use their own cron group, `angeo_brand_visibility`, so slow provider calls never delay Magento's default group. A second job removes old runs every night.

| Job | Cron group | Schedule |

| `angeo_brand_visibility_audit` | `angeo_brand_visibility` | `0 5 * * 1` by default, set in `angeo_brand_vis/cron/schedule` |
| `angeo_brand_visibility_cleanup` | `angeo_brand_visibility` | `30 3 * * *` |

| Table | What it holds | Columns |

| `angeo_brand_visibility_audit` | Angeo Brand Visibility Audit Results | `id, run_uuid, status, error_message, brand_name, brand_domain, store_id, overall_score, score_margin, grade, samples, share_of_voice, win_rate, accuracy_issues, provider_scores, signal_rates, results_json, triggered_by, queries_count, errors_count, from_cache, created_at` |

## Adding a provider

Implement `AiProviderInterface` and add one line to the `ProviderPool` argument in `etc/di.xml`. No existing class needs a change.

## FAQ

### Why does my score not change after I improve the store?

The providers probably answer from memory. Turn on live web search for ChatGPT, Claude or Gemini, or enable Perplexity. Grounded answers react within days.

### Why is every question asked three times?

AI answers are not stable. The same question gives different answers. Asking several times gives a mean and a margin of error, so you can tell a real change from noise.

### How much does a run cost?

The number of calls is providers × prompts × samples. With the defaults that is a few dozen calls. Small models cost cents per run. Grounded searches on large models cost more.

### Does it need AEO Audit?

Yes. It requires `angeo/module-aeo-audit` 3.x or 4.x and reports into it as a live signal. You can still run it on its own.

### Can an agency see reports without running paid audits?

Yes. Give the agency role only the View Reports permission. Running audits needs the separate Run Audit permission.

## Related

- [AEO Audit](https://angeo.dev/docs/modules/aeo-audit/)  -  score 20 AI-visibility signals from the command line
- [llms.txt](https://angeo.dev/docs/modules/llms-txt/)  -  generate llms.txt, llms.jsonl, Markdown mirrors and agents.md
- [Rich Data](https://angeo.dev/docs/modules/rich-data/)  -  one linked JSON-LD graph per page, with offers and policies
- [Robots.txt AEO](https://angeo.dev/docs/modules/robots-txt-aeo/)  -  manage AI crawler rules in robots.txt and verify real bots
- [All module reference pages](https://angeo.dev/docs/modules/) - [Compatibility matrix](https://angeo.dev/docs/compatibility/)

This page was written from the `README.md`, `composer.json` and `etc/*.xml` files of [tag 4.0.1](https://github.com/angeo-dev/module-aeo-brand-visibility/tree/4.0.1), 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.
