Penn-Elcom: Coveo vs Algolia Assessment

Penn-Elcom: Coveo vs Algolia Assessment

Table of Contents


0. Confirmed Environment Facts (DB Scan)

Fact Value Source
Active store views 116 store table
Websites 6 store_website table
Customer groups 66 customer_group table (~3 likely inactive/archived)
Search engine elasticsuite catalog/search/engine config
Magento edition Adobe Commerce (B2B) 2.4.6-p15 composer.json

Store Structure

Website Region Store views Notes
1 Global / ROW ~67 English only — Americas, Africa, Asia, Middle East
2 Europe ~42 English + native language views (de_de, fr_fr, es_es, nl_nl, pt_pt, pl_pl)
3 USA / Mexico 3 English + us_es, mx_es, mx_en
4 Canada 1 ca_fr
5 New Zealand 1 nz_en
6 (TBC) 6th website in DB — likely staging/admin

Key finding: This is genuinely multi-language, not just multi-currency. German, French, Spanish, Dutch, Portuguese, Polish native-language store views exist. Any search index must handle language-aware tokenisation and relevance per locale.


1. Platform Overview

1.1 Coveo

Coveo is an enterprise AI-powered search platform that operates as a push-API-only service from a Magento integration standpoint — there are no native Magento indexers. Data flows one-way: Magento → Coveo Cloud via the Push/Stream API. The frontend is built separately using either:

Authentication: Frontend clients never expose an API key. A short-lived search token is generated server-side (PHP controller) by calling the Coveo Token API, carrying a user identity payload:

{
  "userIds": [{"name": "user@email.com", "provider": "Email Security Provider"}],
  "userGroups": ["b2b-group-name"]
}

This token gates which indexed content and pricing the session can see — the core mechanism for B2B.

Authentication & B2B Pricing — dictionaryFieldContext: This is the key mechanism for PE's 66-group B2B pricing. A dictionary field (e.g. @price) stores a key→value map on every indexed product, where each key is a customer group identifier. The search token carries a dictionaryFieldContext parameter that locks the session to one key:

{
  "userIds": [{"name": "user@email.com", "provider": "Email Security Provider"}],
  "userGroups": ["b2b-group-name"],
  "dictionaryFieldContext": { "price": "group_42" }
}

At query time, any reference to @price in a facet or sort resolves only the group_42 value for that session. No frontend changes needed per group — the token does all the work. Ashley confirmed in the call that the demo showed an array of group→value price pairs returned in the result payload. This is a first-class Coveo feature, not a workaround.

Delivery Assurance Programme (confirmed in Coveo call): Included at no additional cost with Commerce contracts. Comprises: - Kickoff call + 10 flexible workshops covering: technical readiness, source connectors, catalog architecture, UI dev (search box, query pipeline, ML, recommendations), go-live prep - Implementation review — Coveo validate backend configuration and UI functionality before go-live - 24/7 Technical Support + Customer Success team for training + self-learning resources - A named contact from Professional Services (Ashley + Dario) throughout

This directly addresses the "enterprise overkill" concern — Coveo are actively guiding the implementation, not leaving PE to figure it out alone.

UI Library recommendation (from call): Ashley specifically recommended Coveo Headless over Atomic for Magento/bespoke B2B implementations, citing greater flexibility and control, particularly for custom pricing blocks. This aligns with our Alpine.js + Headless recommendation.

AI/Agent features: Coveo has Generative Answering (RGA) — a RAG-based LLM layer exposed via Atomic's <atomic-generated-answer> component or the Headless GeneratedAnswer controller. Genuinely LLM-backed (not scripted), pulling context from indexed documents. Also supports AI merchandising, relevance tuning, and recommendations. Their "Quantic" library is the Salesforce LWC variant — not relevant here. AI agent priority not confirmed by PE yet — deferred to later in the process.

Product badging (confirmed in call): Coveo has a native out-of-the-box badging feature that allows non-technical users (PE's team) to manage promotional labels without dev involvement. Contact Myles Peyton at Coveo for a demo.


1.2 Algolia

Algolia is a hosted search engine with an official, actively maintained Magento 2 module that: - Installs native Magento indexers (product, category, CMS) - Overrides frontend search (InstantSearch.js, autocomplete library) - Provides admin configuration UI under Stores > Algolia - Handles multi-store via per-store-view index name suffixes - Supports merchandising rules in the Algolia dashboard

The module is opinionated and ships its own JS bundles, LESS/CSS, and templates — suitable for standard implementations with theme-level overrides. Alternatively, Algolia can be used headless via their API clients (ignoring the M2 frontend entirely), which gives the same level of UI flexibility as Coveo's Headless SDK approach. Confirmed by Algolia in their vendor Q&A (A10). Version upgrades only affect the indexing layer in the headless approach, not the frontend.

AI features: Algolia NeuralSearch is available (semantic vector search). Their "AI Assistant" is intent-classification based (scripted conversation trees triggering product recommendations by matched intent) — not a true LLM.

Commercial context: Ayko has an existing Algolia relationship (possibly referral/commission basis — Will to confirm). However, no new PE project has used Algolia for several years. Coveo is a new contact — Penn-Elcom found them independently and have had an introductory pitch call with Professional Services. No contract signed for either.


2. Commercial Risk & Total Cost of Ownership

Context: Penn-Elcom's concern is that Coveo is an enterprise platform pitched at £6B revenue businesses and may be overkill or overpriced for their scale. Their read is that Coveo means more dev effort but a better end result. This section addresses the commercial picture honestly.

2.1 Coveo Pricing — Order OF.V1.DD-24-6-26 (Received 24 Jun 2026)

Component Detail Cost (GBP)
Annual subscription 100k QPM, Personalization As-You-Go, Business-Aware Product Ranking, Enterprise £39,631/year
3-year subscription total Fixed term 30 Jun 2026 → 29 Jun 2029 £118,893
Onboarding / Delivery Assurance Included in contract ✅ No extra cost
Sandbox (non-production org) Included ✅ Included
EU hosting Included ✅ Included
Generative Answering (RGA) Not confirmed as included — needs clarification TBC

Renewal: Auto-renews at Coveo's applicable list price at the time (not a fixed escalator — could go up or down).

Contacts: Myles Peyton (AE, +44 7880054552), Robert Platt (billing), Andrew Martin (admin).

Delivery Assurance: Confirmed included. Provides structured workshops, schema design review, go-live validation, 24/7 enterprise support with named contacts.

2.2 Algolia Pricing — Quote Q-55286 (Received 25 Jun 2026)

Quoted plan: Elevate for Ecommerce (Algolia NeuralSearch) — effectively their top commercial ecommerce tier.

Component Detail Annual cost (GBP)
Subscription (Year 1) 4.92M search requests, 240k records, 1.4M recommend requests £25,182
Subscription (Year 2) Auto-renews at +7% £26,945
Subscription (Year 3) +7% again £28,831
3-year subscription total £80,958
Onboarding (one-time) Professional services — not optional £4,698
3-year total committed ~£85,656

Conversion: €1 = £0.8541 (2026-07-07 Frankfurter API)

What's included: - NeuralSearch (AI-powered relevance) ✅ - Algolia Recommend (1.4M requests/year) ✅ - Analytics Extended Retention ✅ - Core Foundation ✅ - Onboarding (€5,500 one-time) ✅

Overage rates (expensive — billed monthly in arrears): | Unit | Overage rate | |------|--------------| | Search requests | £1.67 per 1,000/month | | Records | £4.10 per 1,000/month | | Recommend requests | £0.51 per 1,000/month |

⚠️ Quote expiry: The quote stipulates Algolia can reject it if not signed by 30 June 2026. That date has passed. A revised quote will be needed — pricing may differ.

⚠️ 7% annual escalator: Fees increase automatically by 7% at each renewal. Unused search/record units do not roll over.

2.2a Record Count Risk — Critical Flag

The quote includes a 240,000 record maximum. The figure almost certainly maps to:

6 websites × 7,800 products × ~5 (1 main index + 4 sort replicas) = ~234,000 records ≈ 240,000 cap

This means Algolia have scoped PE as per-website indexing with sort replicas — a reasonable standard assumption. The risk is what they haven't accounted for:

Scenario Records Within 240k cap?
6 website indexes, no replicas ~46,800 ✅ Comfortably
6 website indexes + 4 sort replicas each ~234,000 ✅ Just inside (likely what Algolia quoted)
Above + 9 language-specific indexes (no replicas) ~304,200 ❌ Over cap
Above + replicas on language indexes too ~500,000+ ❌ Well over cap

The language index gap is the real risk. PE have 9 native-language store views (de, fr, es, pt, pl, nl, mx_es, us_es, ca_fr) confirmed active with full translations. Algolia's M2 module creates language-specific indexes by default for correct tokenisation. If Algolia's PS team haven't factored these in, the 240k cap is underscoped.

Overage rate: £4.10 per 1,000 records/month. At 300k records over cap, that's ~£1,230/month (£14,760/year) — meaningful but not catastrophic. At full language+replica expansion it could be higher.

Question 20 (below): confirm how Algolia have scoped the record count and whether language-specific indexes are included.

2.2b Algolia B2B Pricing Workaround

Key hard limit confirmed in PE call (transcript 00:21:57):

Will: "I think what they said is that their limitation for B2B pricing is 20 prices for a product which some products might be under this but obviously in the future that's going to change."

Algolia's proposed workaround (as quoted in the call): Rather than indexing prices, lazy-load them from Magento at search-result-render time via a custom API endpoint. Coveo's pricing data doesn't sit in Algolia — it's fetched dynamically on demand. - Custom endpoint estimate: ~30 hours. - UX implication: Price shows with a loading spinner or is blurred/deferred until the Magento API responds. Will acknowledged "it's hard to know until we've actually done the work" how fast this will be. - Future maintenance: Once built, growing price lists don't require re-indexing. But Magento performance becomes a dependency for PLP price display speed. - This is not an Algolia feature — it is bespoke Ayko dev work to work around Algolia's B2B pricing limitation. It is mandatory at all tiers — without it, Algolia cannot show correct B2B prices. - Important scope note from PESLA-1599: The estimate covers the lazy-loading integration layer only. It explicitly excludes: Algolia module installation/configuration, index setup and product sync, search results template redesign, ElasticSuite migration, and multi-store regression testing. A further 4h investigation is recommended before full commitment to validate SharedCatalog pricing model compatibility with the Algolia module hook points.

2.3 Total Cost of Ownership Comparison

Both quotes now confirmed. The actual subscription delta is £33,237.

Cost Component Algolia Coveo
Annual subscription (Year 1) £25,182 (Q-55286) £39,631 (OF.V1.DD-24-6-26)
Annual subscription (Year 2) £26,945 (+7% fixed escalator) £39,631 (fixed 3yr term)
Annual subscription (Year 3) £28,831 (+7% fixed escalator) £39,631 (fixed 3yr term)
3-year subscription £80,958 £118,893
Onboarding / PS (one-time) £4,698 ✅ Included in contract
3-year committed total £85,656 £118,893
Subscription delta (3yr) Coveo £33,237 more
Year 1 implementation (Tier 1) ~£8–10k ~£14–20k
PESLA-1599 (mandatory, all tiers) +£3,800 ❌ Not required
Ongoing maintenance overhead ~£2–4k/year ~£0.5–1k/year
3-year TCO (Tier 1 example) ~£102–108k ~£138–146k
Record overage risk ⚠️ Language indexes may breach 240k cap ❌ No record limit
Expansion headroom (Thailand, China) ⚠️ Adds ~2 language indexes + records (see §2.3a) ✅ Add 2 sources, no extra cost within QPM
3-year TCO delta Algolia ~£30–40k cheaper Higher subscription, lower operational risk

The full TCO gap is wider once implementation, PESLA-1599, and maintenance are included, but Algolia remains the lower-cost platform if record counts stay within the cap.

2.3a International Expansion Headroom — Thailand & China (Year 2)

New information (2026-07-08): PE are planning two new stores next year — Thailand and China.

Coveo impact: Add 2 new sources (or grouped under existing websites if architecture allows). 100k QPM cap unchanged — verify current search volume to confirm headroom. Zero additional subscription cost during the 3-year term.

Algolia impact — significant:

Item Notes
Thai language index (th_th) Requires dedicated index for correct Thai tokenisation. Algolia handles Thai but requires a separate index per locale.
Chinese language index (zh_cn) Simplified Chinese requires separate index. Significantly different tokenisation — cannot share a Western-language index.
Record impact +2 language indexes × 7,800 products = +15,600 base records. With replicas: +62,400–78,000. Pushes closer to or through the 240k cap depending on current language index count.
Module configuration 2 new store views to configure in Algolia admin. Additional regression test scope.

The 240k record cap was quoted before Thailand and China were on the roadmap. Even if the current scoping is within the cap today, these stores could push PE into overage territory at renewal. This must be raised with Algolia — added to Q20.

2.4 Where Algolia Hits Roadblocks — Specifics

Important framing: Most Algolia limitations are operational concerns, not implementation cost items. The table below explicitly separates the two. Only items in the first section influence the quoted estimate.

Affects Ayko dev cost

B2B pricing at 66 groups [Mandatory — PESLA-1599, 30h 45m quoted]
Algolia has no dictionaryFieldContext equivalent. The chosen workaround is lazy-loading prices from a custom Magento REST endpoint rather than indexing them. This is confirmed as the approach via PESLA-1599 (Dean Morgan, 2026-07-03). Without this work, Algolia cannot show correct B2B prices. Cost is fixed regardless of tier.

Contrast with Coveo: A single @price dictionary field, one token parameter, all 66 groups served from a single index. No additional dev work at any tier.

Module upgrade regression testing [Module approach only — not applicable to headless/API approach]
If using the M2 module frontend, Algolia module updates may affect bespoke theme overrides. With the headless/API approach, module updates only touch the indexing layer — frontend components are Ayko-owned and unaffected by module releases. This is therefore only a relevant cost consideration if the Basic (module) track is chosen.

PE operational concerns (do not affect Ayko dev cost)

Limitation Notes Assessment
116 index management Merchandising rules, synonyms, relevance tuning are per-index. Bulk tooling pending Algolia response. Doesn't change implementation cost — PE's problem to manage
SKU infix/partial search Current ElasticSuite ngram search is poor. Both platforms need this configured. Algolia requires API-level config; may not be in module UI. Not a regression — current search is poor anyway
No native badge rendering Amasty continues in search context. New badge types need dev each time vs Coveo self-serve. PE operational benefit only; Coveo still needs PDP badge dev
AI agent (scripted vs LLM) Algolia's AI Assistant is intent classification. Coveo RGA is genuine LLM. Tier 3/future concern only. Doesn't change implementation cost
Secured API Key field visibility Keys restrict which records appear, not field values. Minor risk with lazy-load approach as prices aren't indexed. Massive edge case; doesn't change implementation cost
No Delivery Assurance equivalent Coveo's workshops are valuable because Coveo needs more figuring out from scratch. Algolia's module removes that ambiguity. False equivalency — Algolia doesn't need the same level of support

2.4a Frontend Approach — Module vs Headless API

Updated 2026-07-10: Algolia confirmed via vendor Q&A (A10) that a fully headless/API approach is a first-class option — using the extension purely for indexing and building the frontend with Algolia's JS libraries or API clients directly. This removes module template ownership as a constraint.

Two distinct Algolia implementation paths exist:

Module approach (Algolia Basic):
Use the M2 module's InstantSearch.js frontend with theme-level overrides. Module owns product card templates — bespoke elements (enquiry CTAs, custom price display) are retrofitted via theme overrides. Faster initial build, less upfront dev, but customisation depth is constrained by what the module exposes. Suitable if PE's search ambitions are limited.

Headless/API approach (Algolia High):
Use the extension for indexing only. Build all frontend components from scratch with Algolia's JS API clients + Alpine.js — same architecture as the Coveo approach. Full UI control, no module upgrade regression risk, same build effort as Coveo Tier 1–2. B2B lazy-pricing (PESLA-1599) remains mandatory regardless of approach.

2.4b Full Catalogue / Buy Online Toggle — Ayko\NonTransactionalProducts

Codebase confirmed (2026-07-08): The toolbar toggle is an existing bespoke Ayko module, not a Magento-native or ElasticSuite feature. It must be migrated to whichever search platform is chosen.

How it currently works:

The non_transactional boolean product attribute marks enquiry-only products (value 1). The toolbar toggle (Full Catalogue / Buy Online) controls whether these products are visible.

Layer Implementation
UI toggle.phtml — rendered in toolbar, fires AJAX POST to SwitchAction controller
State ContextSwitcher observer stores toggle state in DataPersistor + Magento HttpContext (FPC variation key)
Search filter Model/Elasticsuite/.../NonTransactional implements ElasticSuite's FilterInterface — applies bool query excluding non_transactional=1 products when "Buy Online" is active
Layered nav fix RemoveFilterFromCollection plugin strips non_transactional from ES collection filters to prevent it breaking layered navigation
PDP ResultPage plugin adds layout handle catalog_product_view_type_available_in_store on enquiry-only PDPs (shows enquiry form instead of add-to-cart)

What needs to change when ElasticSuite is replaced:

Algolia migration:

Index non_transactional attribute. Convert the toggle from a POST/server-session mechanism to a JS-driven filter. Apply as an Algolia filter string (NOT non_transactional:true). The current HttpContext/FPC state model doesn't translate cleanly to Algolia's client-side rendering — you end up with a hybrid server+client toggle state, harder to reason about and test. The module's own filter architecture needs extending to accept this parameter, which means working against the module's assumptions.

Coveo migration:

Index non_transactional as a field. Build the toggle as an Alpine.js StaticFilter or Tab controller — Coveo Headless's TabManager is designed exactly for toggling between views of the same result set via a query condition:

// Alpine component — state managed by Headless URL manager
{
  toggleBuyOnline() {
    engine.dispatch(toggleSelectStaticFilterValue({
      id: 'catalogue-mode',
      value: { expression: 'NOT @non_transactional==1' }
    }))
  }
}

State is managed by the Headless URL manager — deep-linkable, bookmarkable, back-button safe. ES-specific classes are retired cleanly. No hybrid server/client state to maintain. The enquiry form CTA on PDPs continues via the existing ResultPage layout handle mechanism, which is Magento-native and platform-agnostic.

2.5 Is Coveo "Too Big" for Penn-Elcom?

Short answer: probably not, but it depends on the QPM figure and contract minimum.

The "£6B revenue" framing is Coveo's marketing. Their Commerce product is actively sold to mid-market retailers. The meaningful question is not revenue size — it's search query volume. PE is a B2B specialist manufacturer with a defined customer base (5 companies, 66 groups). Their search query volume is almost certainly modest compared to a consumer B2C retailer at comparable GMV. If Coveo's QPM pricing is based on volume, PE could be in a very affordable tier.

The risk is contract minimums — if Coveo requires a £40k+/year minimum regardless of volume, that changes the conversation. This is the single most important commercial question to get answered before recommending Coveo.

What PE should push Coveo for: A query volume estimate based on their actual traffic data, and a per-tier price breakdown. If Coveo can't or won't provide transparent indicative pricing, that itself is a commercial red flag.

2.6 Recommendation on Commercial Risk

Scenario Recommendation
Coveo contract minimum is within PE's budget Coveo — technical fit is clearly superior for their B2B complexity
Coveo contract minimum is prohibitive Algolia Premium with architectural B2B mitigation — accept the limitations, design around them, but be explicit with PE about what they're trading off
Neither contract is palatable ElasticSuite upgrade path — invest in upgrading the existing stack (newer ES/Opensearch, improved front end) rather than a third-party SaaS dependency

PESLA-1599 (30h 45m) is mandatory for Algolia at all tiers and must be added to every Algolia estimate. It is not in Coveo's scope at all. At Tier 2, this alone narrows the gap between Algolia and Coveo to near-zero before any other work is considered. At Tier 3, with module fighting and the B2B overhead, Algolia likely costs more in dev than Coveo.


3. Codebase Assessment — Penn-Elcom Specific Modules

3.1 Current Search Stack

The site runs Smile ElasticSuite open-source (smile/elasticsuite: ^2.11, smile/module-elasticsuite-shared-catalog: ~2.11.0) — confirmed as the community (free) edition, no enterprise license. Also installed: vortex/indexer-statistics-smile-elasticsuite (third-party indexer stats module), ayko/elasticsearch-index-cleanup (custom cleanup cron), ayko/merchandisingsmile (custom merchandising rules). All ElasticSuite-specific dependencies can be retired post-migration once the fallback decision is finalised.

3.2 Search-Specific Custom Modules

Module Purpose Migration Implication
Ayko_SearchAutocomplete Injects SKU into ElasticSuite autocomplete (AttributeConfig DI arg) so SKU appears in the typeahead dropdown Replace entirely — Coveo/Algolia autocomplete is built from scratch. SKU must be a searchable field in the new index.
Ayko_ElasticsuiteSearchBySku Adds ngram_sku edge-ngram analyzer to ElasticSuite, enabling partial SKU search (e.g. searching "4U" matches "rack-4U-12") Critical requirement to replicate — Coveo: configure field tokenisation in Push API mapping. Algolia: searchableAttributes with ngram-style settings.
Ayko_SmileElasticsuiteIndexDeduplication Prevents duplicate ES index creation per store dimension Retire post-migration — Coveo/Algolia manage their own index structure
Ayko_ElasticsuiteStatusAttributeFix Fixes product status filtering in ES collections Retire post-migration — irrelevant to external search platforms
Ayko_CatalogRuleOptimisation See §3.3 See §3.3

3.3 CatalogRuleOptimisation — Clarified

This module contains two plugins:

  1. AddCatalogRulePriceToProductCollection — hooks Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Fulltext\Collection::afterGetProductCollection() to call CollectionProcessorFactory::addPriceData(). This injects catalog price rule discounts into the ElasticSuite product grid so discounted prices display on PLPs. It is ElasticSuite-specific and will become inert when ElasticSuite is removed.

  2. FinalPricePlugin — hooks ProcessFrontFinalPriceObserver::beforeExecute() to populate RulePricesStorage with the catalog rule price from the product object if present, keyed by date|website|customerGroup|product. This affects final price resolution on PDPs.

Important distinction: Penn confirmed no active catalog price rules — they tried to get them working but couldn't, and now rely solely on cart price rules at checkout. This means: - Ayko_CatalogRuleOptimisation is effectively dead code — can be flagged for removal during migration - The catalog rule price issue does not affect search result prices (no active rules to push) - Cart price rules (checkout discounts) are handled entirely within Magento's quote/order system and are irrelevant to the search integration

3.4 Non-Transactional Products

Ayko_NonTransactionalProducts module confirmed — this handles enquiry-only products (no add-to-cart). In search results: - Push a boolean field to index: is_non_transactional: true/false - Product card component conditionally renders "Enquire Now" vs "Add to Cart" - Existing modal form logic can be retained — just needs the trigger wired up to the new card component

3.5 B2B & Multi-Store Modules

Module Purpose Implication
Ayko_SharedCatalog Extends Magento_SharedCatalog with custom TierPrice and GroupPrice indexer plugins; AddFallbackGroupID plugin Prices pushed to Coveo must carry group-keyed price fields per customer group
Ayko_SharedCatalogueAssignment Console tool for bulk shared catalog product assignment Informs sync scope — products can differ per catalog
Ayko_CompanyLocale Locale settings per company Relevant for language-scoped search tokens
Ayko_CompanyExternalCustomerId Maps company accounts to SageX3 ERP IDs May affect B2B identity in search token (ERP group ≠ Magento group)
Ayko_CompanyExtensionAttribute Custom attributes on company entities May need fields in the index
Ayko_DisableAutoGroup Disables automatic customer group assignment Indicates group assignment is manually managed — important for token identity
magento/extension-b2b: ^1.4 Core B2B (shared catalogs, company accounts, quotes) Full B2B stack active

3.6 Other Modules with Search/Listing Implications

Module Notes
Ayko_Trustpilot Custom wrapper around trustpilot/module-reviews ^2.6 — star ratings on product pages
amasty/module-product-labels-subscription-pack Condition-based product label badges
ayko/merchandisingsmile Custom ElasticSuite merchandising rules
ayko/module-indexer-statistics-merchandising ES indexer stats
ayko/elasticsearch-index-cleanup ES index cleanup cron
Ayko_GeoIpRedirect GeoIP-based store view redirect
Ayko_InternationalUrlRewrites International URL structure
Ayko_PriceListDownload Downloadable price lists
Ayko_EuNavigation / Ayko_Menu Custom nav/menu
Ayko_Msrp MSRP display logic
Ayko_CountrySelector Frontend country/store switcher

4. Platform Comparison for Penn-Elcom

4.1 B2B & Multi-Store

Capability Coveo Algolia
Per-customer-group pricing in index ✅ Custom fields — you define schema ⚠️ Supported but per-attribute config required
Search token per customer/group ✅ First-class — userIds + userGroups in token ❌ No token model — API key only; B2B needs separate indexes or runtime filter injection
Multi-store / multi-language ✅ Three source options: 116 per-store-view, 6 per-website (Tracking ID scoping), or 1 multi-market (PS commitment). All work without frontend changes. ✅ Per-store-view index (auto via M2 module)
Native language search (tokenisation) ✅ Language set per source — Coveo handles it ✅ Index-level language settings
Shared catalog scope You define what goes in the push M2 module handles automatically
B2B catalog visibility per company userGroups in search token — clean, single index Separate index per group or complex runtime filters

At 66 customer groups × 116 store views: Coveo's single-index-with-token-gating approach is far cleaner than Algolia's index-per-group model (which would imply up to 66 × 6 = 396 potential indexes). Even with Algolia's filtering approach, injecting 66 different price group filters correctly per session is fragile.

4.2 Customisation Scope

Aspect Coveo Algolia
Frontend architecture 100% custom UI Module owns ~80%, you customise the rest
Product card Fully custom Alpine/Headless Override InstantSearch templates
Mini-search (typeahead) Build from scratch Override Algolia autocomplete widgets
PLP facets Headless controllers or Atomic components Override Algolia facet widgets
B2B price display Fully custom — render whatever token returns JS hooks into Algolia module
Enquiry-only products Custom conditional render logic Algolia event hook + custom template
Product badges/labels Coveo Atomic field-conditional rendering — native Amasty module or custom template
AI chat agent Coveo RGA — true LLM/RAG Algolia AI Assistant — scripted intent classification
Future extensibility API is the only limit Limited by Algolia M2 module architecture

4.3 Coveo Turbo Module Assessment

GitHub: Coveo-Turbo/magento-integration

Feature set (from README and repo): - Multi-store: ✅ per-store-view configuration - B2B shared catalog: ✅ full + delta sync with separate batch sizes per catalog - Push/Stream/File Container APIs: ✅ all three integrated - Delta sync: ✅ via Magento observers (product save/delete) - Product variants (configurable, bundle, grouped): ✅ - Category hierarchy: ✅

Code quality issues: - 2 commits total, single branch, minimal tag history — immature release cadence - No return types on methods, no property promotion (confirmed in your review) - No visible unit or integration tests - PHP 97.7%, HTML 2.3% - Would not pass Ayko's internal code standards

Coveo's own recommendation (from call): Ashley specifically called out the Coveo Turbo integration as an accelerator for Magento implementations and endorsed using it as the backend data pump. This adds credibility to using it as a base — Coveo's PS team are familiar with it.

Source architecture — three confirmed options (from Coveo written Q&A):

Option Sources Connector changes Status
A — 116 per-store-view sources 116 None ✅ Works today
B — 6 per-website sources 6 None ✅ Works today
C — Multi-market single source 1 Connector enhancement needed ⚠️ PS commitment, not yet built

Option B detail (from Coveo Q&A): Per-website sources are scoped to the correct store view using a Tracking ID + Storefront Association — a mapping that links the Tracking ID with a language/country/currency combination to a Catalogue configuration. Each property gets a separate query pipeline for search, listings, and recommendations. Filter rules for the correct products are applied automatically from the Catalogue config. No connector changes required.

Option C detail: Multi-market catalogue sources introduce "catalogue views" — one product record with localised data per view, or an attribute defining which catalogue(s) a product belongs to. The Turbo connector would need minimal customisation. Coveo PS commit to making these enhancements if PE proceed.

⚠️ Option C connector enhancements are not yet built — this is a PS commitment. Options A and B work today. Option B (6 sources) is likely the pragmatic starting architecture — significantly lower admin overhead than 116 sources, no additional connector work.

📌 Pricing implication: Source count does not affect the subscription cost. The 100k QPM allowance is shared across all sources regardless of architecture chosen.

Decision options:

Option Effort Notes
~~Refactor Turbo module to Ayko standards~~ ~~3–4 days~~ Off table — Will confirmed project will not be signed off with refactor scope included
Use as-is with targeted patches 1–1.5 days Accepted approach — patch specific issues (missing return types where they cause errors, critical DI issues) without full standards lift
Build clean from scratch 5–7 days Full control, but harder to justify commercially given Coveo PS endorse the module

Recommendation: Use Turbo as-is with minimal targeted patches. Accept the code quality limitations as managed tech debt. Scope any patches to what is strictly necessary for the integration to function correctly at PE's scale. Raise any gaps found during the Delivery Assurance workshop review.


5. Penn-Elcom Specific Complexities

4.1 Trustpilot Review Hydration

Ayko_Trustpilot wraps the Trustpilot module. Rating badges on product cards in search results:

Recommend Option B with a lightweight caching layer (Redis-backed Magento endpoint) to avoid Trustpilot API rate limits on high-traffic searches.

4.2 Product Badges — Coveo vs Amasty

amasty/module-product-labels-subscription-pack handles condition-based product labels (NEW, SALE, CLEARANCE etc) site-wide. In the search context, Coveo Atomic provides atomic-field-condition — a result template component that conditionally renders content based on an indexed field value. This means:

This does not retire the Amasty module site-wide (it still handles PDP, category pages, etc.) but removes the need for label hydration in the search/PLP context.

4.3 Non-Transactional / Enquiry Products

Ayko_NonTransactionalProducts already tracks which products are enquiry-only. Push is_non_transactional: true/false to the index. Product card renders conditionally. Modal form remains as existing Magento component, triggered from the new card.

4.4 Catalog Price Rules — Clarified

Penn confirmed they use cart price rules (checkout/quote), not catalog price rules, for promotions. The CatalogRuleOptimisation module is an attempt to fix a separate pre-existing issue where catalog-level price rules (rules applied to PLP/PDP prices before checkout) weren't working.

This is a separate discovery spike — no search platform will resolve it. The search platform will display whatever price is pushed to the index. If catalog rules are later fixed in Magento, the push sync would need to resolve final prices inclusive of those rules.

4.5 Multi-Language Search (New Finding)

The DB scan confirmed native-language store views: de_de, fr_fr, es_es, nl_nl, pt_pt, pl_pl, mx_es, us_es, ca_fr. This means:

4.6 GeoIP Redirect & Store View Routing

Ayko_GeoIpRedirect routes visitors to country store views. The Coveo search token must be generated after store view resolution — it should carry the active store view scope so results are filtered to the correct regional catalog, currency, and language. This is straightforward but must be explicitly built into the token generation controller.


6. Fallback Architecture (Resilience)

Resilience concern: Both Coveo and Algolia are external APIs. If either has an outage, the search-dependent parts of the site (mini-search, PLPs, search results) go down. Manual switching is not acceptable.

5.1 The Problem

ElasticSuite is currently self-hosted (on the same infrastructure). Coveo and Algolia are SaaS platforms with their own SLAs. Both claim high availability (Coveo: 99.9% SLA, Algolia: 99.99% SLA), but outages do occur.

5.2 Fallback Strategy Options

Strategy Complexity User Experience
Silent fallback to Magento/ES native search High Transparent — user sees results, quality degrades
Fallback to cached last-known results Medium Acceptable for common queries, fails for long-tail
Graceful error state ("Search temporarily unavailable, browse categories") Low Honest but poor UX
Health-check-gated toggle in session Medium Switch to ES if Coveo unreachable on token fetch

On page load, the search token endpoint (PHP controller) checks Coveo availability. If the token request fails or times out: 1. Controller sets a session/cookie flag: search_provider=fallback 2. Frontend reads the flag and renders the native Magento/ElasticSuite search block instead of the Coveo UI 3. When Coveo recovers, subsequent page loads restore the Coveo token and clear the flag

Key requirement: ElasticSuite must be retained (not removed) even after Coveo goes live. It becomes the fallback search engine. The custom ES modules (ElasticsuiteSearchBySku etc.) should also be retained for the fallback to work correctly.

⚠️ Architectural implication: This adds meaningful scope to all tiers. The site effectively needs to maintain two parallel search stacks. Keeping ES alive is straightforward (no new code), but the health-check gateway and conditional UI rendering is additional work. Estimate this at +2–3 days across any tier.

5.4 Coveo SLA vs Algolia SLA

Coveo Algolia
Stated SLA 99.9% 99.99%
Circuit breaker / fallback tooling Manual (we build it) Manual (we build it)
Status page status.coveo.com status.algolia.com

Algolia's SLA is stronger on paper. In practice, both require the same fallback architecture at PE's scale.


7. Framework Recommendation

Confirmed: Alpine.js + Coveo Headless SDK

Alpine is already used in Ayko's Hyvä builds and Shopify themes — the team knows it, the patterns are established. It maps naturally to Headless controllers via x-data reactive state. No build pipeline changes needed in the Magento theme (Alpine loads from CDN or bundled via theme). For the Coveo integration:

// Example Alpine + Headless pattern
Alpine.data('coveoSearch', () => ({
  engine: null,
  searchBox: null,
  query: '',
  suggestions: [],
  init() {
    this.engine = buildSearchEngine({ configuration: { ... } });
    this.searchBox = buildSearchBox(this.engine);
    this.searchBox.subscribe(() => {
      this.suggestions = this.searchBox.state.suggestions;
    });
  },
  updateQuery(value) {
    this.searchBox.updateText(value);
    this.searchBox.showSuggestions();
  }
}));

For the AI chat agent (Tier 3), the Headless GeneratedAnswer controller wires into the same Alpine component pattern — no additional framework needed.

Option Verdict
Alpine.js + Coveo Headless Chosen — team familiarity, lightweight, Hyvä-aligned
React + Coveo Headless Overkill for this scope; consider if PE ever goes headless frontend
Coveo Atomic Web Components Usable but Shadow DOM limits deep custom styling
Vue 3 + Coveo Headless Viable but no existing team patterns

8. Three-Tier Rough Estimates (Revised)

⚠️ Ballpark figures only — not confirmed quotes. Designs must be provided and signed off before Tier 2 or Tier 3 can begin. All tiers assume: Coveo platform access in place, backend module in place, no major blockers from Magento infrastructure. Add +2–3 days to any tier for the fallback/resilience architecture (§5.3).


Tier 1 — Basic (Like-for-Like, Ajax)

Goal: Replace ElasticSuite frontend with Coveo search. Same layout/UX as today but AJAX-driven, no redesign. Autocomplete replaces existing. PLP replaces layered nav with Coveo-powered filters. B2B pricing via search token. Fallback to ES if Coveo unreachable.

Work Item Estimate
Backend module — Coveo-Turbo as-is + targeted patches 1–1.5 days
Search token endpoint (session-aware, store-scoped, B2B group identity) 1–2 days
Fallback health-check gateway + conditional UI flag 1–2 days
Mini-search autocomplete (typeahead, products + categories, SKU support) 2–3 days
Search results page (grid, basic facets, sort) 3–4 days
PLP override (category pages via Coveo, basic checkbox filters) 3–4 days
B2B price rendering (token-gated, group-specific price field) 1–2 days
Multi-store / multi-language source config (116 store views → Coveo sources) 2–3 days
Non-transactional product CTA (conditional render) 0.5 days
QA + cross-browser + multi-store smoke test 2–3 days
Total ~19–27 days
Indicative range ~£14k–£20k

Tier 2 — Medium (Enhanced Discovery)

Goal: Tier 1 + enriched filter experience equivalent to a well-configured ElasticSuite setup. Price slider, brand/attribute multi-select, category tree, result count, term highlighting, Trustpilot ratings, enquiry modal, product badges.

Additional Work Adds to Tier 1
Price range slider (Alpine + Coveo PriceRangeFacet controller) +1–2 days
Brand / attribute multi-select facet panel +1–2 days
Category tree hierarchical facet +1–2 days
Result count, items-per-page, pagination +0.5 days
Term/keyword highlighting in results +0.5 days
Enquiry-only modal integration with new product card +1 day
Trustpilot async hydration (skeleton state, cached Magento endpoint) +1–2 days
Coveo field-conditional badge rendering (replaces Amasty in search context) +0.5–1 day
Search results page enrichment (image, description snippet, richer layout) +1 day
Extended multi-language QA (key language store views) +1–2 days
Adds +9–14 days
Combined Total ~28–41 days
Indicative range ~£21k–£31k

⚠️ Requires designs signed off before starting. UI complexity significantly affects this estimate.


Tier 3 — High (Bespoke Premium Experience)

Goal: Tier 2 + full-screen Doofinder-style mini-search overlay, Coveo Generative Answering chat agent, fully custom product card components, visual merchandising, analytics events, dynamic recommendations, mobile-optimised. Premium UX end-to-end.

Additional Work Adds to Tier 2
Full-screen mini-search overlay (animated panel, keyboard nav, recent searches, trending terms) +3–5 days
Coveo GenAI chat agent (Headless GeneratedAnswer controller, custom Alpine chat UI) +3–5 days
Fully custom product card component (Alpine, handles all product types, B2B price, badge, enquiry) +2–3 days
Visual merchandising integration (Coveo merchandising rules, promoted products) +1–2 days
Analytics event wiring (click, add-to-cart, search pipeline, Coveo usage analytics) +1–2 days
Dynamic recommendations (RecommendationList on PLP / search results) +2–3 days
Catalog rule price discovery spike (understand and scope resolution) ~~+2–4 days~~ removed — no active catalog rules confirmed
Performance / LCP optimisation (lazy hydration, skeleton states, bundle sizing) +1–2 days
Mobile UX polish (touch-optimised filter drawer, responsive grid) +1–2 days
Adds +16–28 days
Combined Total ~44–69 days
Indicative range ~£33k–£52k

⚠️ Requires designs signed off before starting. AI agent scope (scripted vs full GenAI) must be confirmed — this estimate assumes Coveo RGA (full LLM) rather than a rules-based chatbot. If PE decide a scripted agent is sufficient, save ~2–3 days.


Algolia Comparison (for reference)

Estimating principle (Will Brammer, 2026-07-08): Algolia estimates should reflect what PE actually needs — not feature parity with Coveo. If Algolia doesn't natively have something Coveo has, that doesn't automatically add scope to the Algolia estimate.

Updated 2026-07-10: Algolia now structured as two tracks following vendor confirmation of the headless/API approach (A10).

Algolia Basic — module-based, line-item breakdown:

Work item Estimate
PESLA-1599 — B2B lazy-load pricing, BE + FE (mandatory) ~4 days
Theme-level product card overrides (enquiry CTA, Trustpilot slot, B2B price placeholder) 1–1.5 days
Non-transactional product CTA 0.5 days
Fallback architecture (ES health-check gateway) 2–3 days
Multi-store config verification (116 store views, API keys) 0.5–1 day
QA + cross-store smoke test (pricing accuracy, 3+ customer groups) 2–3 days
Total ~10–13 days

Algolia High — headless/API, Alpine.js, full custom build:

Work item Estimate
PESLA-1599 — B2B lazy-load pricing, BE only ~2 days
Search token / API key management (per-session, store-scoped) 1–2 days
Fallback architecture (ES health-check gateway) 2–3 days
Mini-search autocomplete (Algolia Autocomplete.js, custom Alpine component) 2–3 days
Search results page (grid, facets, sort — Algolia InstantSearch headless) 3–4 days
PLP override (category pages, Algolia-driven filters) 3–4 days
B2B price lazy-load FE (skeleton state, async price injection) 2 days
Multi-store config verification (116 store views, API keys) 0.5–1 day
Non-transactional product CTA 0.5 days
QA + cross-store smoke test 2–3 days
Total ~18–25 days
Algolia Basic Algolia High Coveo Tier 1 Coveo Tier 2
Dev days ~10–13 ~18–25 ~19–27 ~28–41
B2B pricing UX 🔴 Spinner (lazy-load) 🔴 Spinner (lazy-load) ✅ Instant (token-native) ✅ Instant (token-native)
UI flexibility 🟡 Module templates ✅ Unlimited ✅ Unlimited ✅ Unlimited
Module upgrade risk 🟡 Theme overrides at risk ✅ None (indexing only) 🟡 Turbo module (low cadence) 🟡 Turbo module (low cadence)
PHP compatibility ✅ Up to PHP 8.4 ✅ Up to PHP 8.4 ⚠️ Turbo module PHP 8.1 only ⚠️ Turbo module PHP 8.1 only
2.4.6 compat ⚠️ Not guaranteed since v3.16 (module) ✅ Not applicable (headless) ✅ Not module-dependent ✅ Not module-dependent
116-store-view handling ✅ Auto per index ✅ Auto per index 🟡 Per source (manual config) 🟡 Per source (manual config)
AI agent ❌ None ❌ None ❌ None ❌ None
Implementation support Onboarding workshops Onboarding workshops ✅ Delivery Assurance (10 workshops) ✅ Delivery Assurance
Existing Ayko relationship ✅ Referral basis confirmed ✅ Referral basis confirmed ❌ New vendor ❌ New vendor

Cross-tier outcome comparison

Key insight: The question is not just cost — it's what you get for the money:

Dev cost B2B pricing UX UI flexibility PHP support Maintenance
Algolia Basic ~10–13 days 🔴 Spinner (lazy-load) 🟡 Module templates ✅ PHP 8.4 🟡 Theme override risk
Algolia High ~18–25 days 🔴 Spinner (lazy-load) ✅ Unlimited ✅ PHP 8.4 🟢 Low (indexing only)
Coveo Tier 1 ~19–27 days ✅ Instant (token-native) ✅ Unlimited ⚠️ PHP 8.1 (Turbo module) 🟢 Low
Coveo Tier 2 ~28–41 days ✅ Instant (token-native) ✅ Unlimited ⚠️ PHP 8.1 (Turbo module) 🟢 Low
Coveo Tier 3 ~44–67 days ✅ Instant (token-native) ✅ Unlimited ⚠️ PHP 8.1 (Turbo module) 🟢 Low

Algolia High and Coveo Tier 1 are now closely comparable in both dev cost and UI capability. The residual difference is B2B pricing UX (spinner vs instant) and PHP support (Algolia ahead). Coveo's advantage is the native dictionaryFieldContext pricing and Delivery Assurance programme. Algolia's advantage is PHP 8.4 support and a more mature module ecosystem.

The only tier where Algolia's cost advantage is clear is Tier 1. If PE's ambition ends at Tier 1 — like-for-like replacement, minimal customisation, no development roadmap — Algolia is the rational choice. If PE have any ambition beyond that, Coveo is the better investment.



9. Decision Framework — For Business Owners

This section states clearly what each choice means for Penn-Elcom's business — commercially and practically. Neither option is being recommended above the other. The right answer depends on what you are trying to achieve.


Choose Algolia if you accept all of the following


Choose Coveo if you accept all of the following


Comparative matrix — business decision view

Algolia Coveo
3-year subscription £80,958 £118,893
Onboarding (one-time) £4,698 ✅ Included
3-year committed total £85,656 £118,893
Subscription delta +£33,237
Year 1 build (Tier 1) ~£8–10k ~£14–20k
B2B pricing workaround +£3,800 mandatory ✅ None
Est. ongoing maintenance/year ~£2–4k ~£0.5–1k
3-year TCO estimate (Tier 1) ~£102–108k ~£138–146k
TCO delta +£30–38k
B2B price display (66 groups) 🔴 Deferred load / spinner ✅ Instant, native
B2B price maintenance 🔴 Ayko-owned endpoint ✅ Self-maintaining
Record cap ⚠️ 240k (language indexes may breach) ✅ No limit
Thailand & China expansion ⚠️ Requires re-quote, possible overage ✅ No extra cost in 3yr term
Template / UI ownership 🟡 Basic: module. High: Ayko owns all ✅ Ayko owns all components
Bespoke feature integration 🟡 Basic: retrofitted. High: first-class ✅ First-class, built in
Module upgrade regression risk 🟡 Basic: theme overrides at risk. High: none 🟡 Turbo module (low cadence, PHP 8.1)
PHP compatibility ✅ PHP 8.4 ⚠️ Turbo module PHP 8.1 only
PE team self-service 🔴 Dev required for most changes ✅ Admin-driven
Catalogue toggle (NonTransactional) 🔴 Hybrid server/client rewrite ✅ Clean Headless StaticFilter
Recommendations ✅ Included (1.4M units/year) ✅ Included
Personalisation 🟡 Per-user (separate Recommend API) ✅ Integrated into search ranking
AI / GenAI capability 🟡 Scripted intent only ✅ True LLM (Tier 3)
Implementation support Ticket-based ✅ Delivery Assurance (24/7, named)
API stability / deprecation Standard semver Enterprise contract notice period
Algolia module upgrade risk 🔴 Custom hooks broken historically ✅ N/A

The honest summary

Algolia costs less. The 3-year TCO advantage is approximately £30–38k — real money.

What that buys is a Tier 1 like-for-like replacement that works well for a standard ecommerce use case. Penn-Elcom is not a standard ecommerce use case. It has 66 customer groups, 116 store views, bespoke transactional logic, international expansion planned, and a search UI that has been substantially customised over years.

Every point at which PE's requirements exceed Algolia's standard assumptions — B2B pricing, language scaling, custom UI elements, module upgrade cycles — generates additional cost that does not appear in the initial estimate. Those costs are real, they are recurring, and they compound. The risk is not that Algolia fails on day one. The risk is that PE regret the decision 12–18 months in, when the module has been upgraded twice, the catalogue toggle has been rewritten, Thailand is waiting on a re-quote, and the initial cost saving has been spent on maintenance.

Coveo costs more upfront. What PE are paying for is a platform that is architected for their actual complexity — not a module that was designed for a simpler problem.

The decision comes down to one question: Is PE's ambition for search limited to what can be delivered at Tier 1, or do they want a search platform that grows with their business?


9a. What You Have Today — And What Happens To It

Before looking at what you might gain from a new platform, it is worth being clear about what you have right now and what each choice means for those capabilities.

Note on pricing row: ElasticSuite indexes customer-group prices server-side, meaning prices currently load with the page. This should be verified against PE's live site before using it as a decision factor — if there is already any deferred price loading in the current implementation, the Algolia comparison on this row changes.

Current features and their fate

What PE has today With Algolia With Coveo
B2B pricing per customer group on search results 🔴 Structural change. Prices cannot be indexed per-customer-group in Algolia's model. They must load after the page renders via a custom Magento API endpoint (PESLA-1599 — confirmed 30h 45m of bespoke work). The endpoint is permanently Ayko-owned and maintained. Native. All 66 customer groups served via token model — no bespoke endpoint, no loading state, scales automatically to new groups.
Full Catalogue / Buy Online toolbar toggle 🔴 Requires rewrite. Current implementation ties into ElasticSuite's FilterInterface and Magento's FPC cache variation — both ES-specific. For Algolia the toggle must be rebuilt as a hybrid server/client mechanism. The Algolia module was not designed for this pattern. Clean migration. Maps to a Coveo Headless StaticFilter Alpine.js component — a purpose-built pattern for exactly this use case. More robust than the current implementation.
Enquiry-only product CTAs in search results 🟡 Basic: retrofitted into module template. High: first-class Alpine component, same as Coveo. First-class. Built into the Coveo Alpine product card component from day one. No override, no regression risk.
116 store view search configuration 🟡 Preserved, operationally heavier. Algolia creates one index per store view. Synonyms, rules, and relevance must be managed per index. No bulk tooling confirmed. 🟡 Preserved. Option B (6 per-website sources) reduces admin overhead vs 116 sources. Coveo pipeline rules are shared across sources — changes apply broadly. New store views map to existing source configuration.
Multi-language search quality (9 active language store views) 🟡 Preserved but requires separate indexes. Language-specific indexes are not confirmed within the 240k record quote — may push PE toward or over the cap. Configuration per language index needed. 🟡 Preserved. Each language configured at source level. No record cap. But Coveo source configuration for 9+ languages still requires initial setup time.
Product badge rendering on search results 🟡 Preserved but dev-dependent. New badge types require a developer to modify the Algolia module template. Each module update is a regression risk. Preserved and becomes self-service. Field-conditional badge logic managed in Coveo admin after initial build.
Thailand and China stores (Year 2) 🔴 Requires re-quote. Thai and Chinese language indexes need dedicated indexes, not in scope of current 240k record quote. PE would return to Algolia for an amended contract. Within existing contract. Fits in 3-year term at no extra subscription cost. Source configuration only.
Extending search with new features over time 🟡 Basic: constrained by module. High: open — Ayko owns all components, same as Coveo. Open. Coveo Headless + Alpine — Ayko owns all components. New features are additive.

What each platform honestly asks of you

Algolia asks: - Accept deferred B2B pricing (structural — not a configuration choice) - Permanently maintain a custom Ayko pricing endpoint - Accept that your bespoke UI features (toggle, enquiry CTAs, badges) require dev work to maintain around the module's template ownership - Budget for a record count re-quote when Thailand and China go live - Accept higher ongoing dev cost as customisation depth increases

Coveo asks: - Pay £33,237 more over 3 years (£220/month) - Accept a higher Year 1 build cost (£6–10k more at Tier 1) - Accept that the Coveo Turbo M2 module is newer and less battle-tested than Algolia's (though Ayko has reviewed and patched it) - Accept that Coveo's renewal price is list price at the time — not a fixed escalator. It could go up or down. - Accept a more complex initial implementation that requires more Ayko input to set up correctly

The trade-off, plainly stated

Neither list is fabricated. Both platforms have real costs and real trade-offs for PE's specific situation.

Algolia is cheaper in year 1 and over the subscription term. For a business whose search ambitions are genuinely Tier 1 — better relevance, standard facets, no major customisation roadmap — that is a completely rational choice and they would be overpaying for Coveo.

The question is whether PE's actual profile fits that description. With 66 customer groups, 116 store views, bespoke transactional logic, planned international expansion, and a history of investing in custom search features, the evidence suggests it does not. The Algolia cost savings are real — but so are the additional costs that follow from PE's specific complexity.

PE should make this decision with both lists in front of them.


10. Open Questions — Resolved

# Question Answer
1 Store view count 121 rows in DB (116 active store views, 6 websites) — confirmed by DB scan
2 Customer group count 66 groups in DB (Will cited 69 — ~3 likely inactive)
3 Catalog rule prices No active catalog rules — confirmed by PE. CatalogRuleOptimisation is dead code. Cart price rules at checkout unaffected.
4 Coveo contract status Not signed — introductory pitch stage. Delivery Assurance included in contract.
5 Frontend framework Alpine.js — confirmed. Coveo PS also recommended Headless SDK over Atomic for this use case.
6 ES removal post-migration Must be retained as fallback — not removed, kept as graceful degradation target
7 AI agent priority PE to confirm — general cost/scalability/data complexity are current priorities
8 Designs before dev Yes — required for Tier 2+
9 B2B price field strategy Dictionary fields confirmeddictionaryFieldContext in search token. Ashley demoed group→value price array. Single index, no duplication.
10 Source structure Three options confirmed by Coveo written Q&A — (A) 116 per-store-view sources, (B) 6 per-website sources via Tracking ID + Storefront Association (both work today, no connector changes), (C) multi-market single source (PS commitment, not yet built). Option B likely the pragmatic starting point.
11 Translation quality PESLA-572 — substantial translation project completed for de, fr, es, pt, pl, nl store views. URL structure migrated. hreflang implemented. Translations appear complete for 6 language views.
12 ElasticSuite license Open-source (community) edition — no enterprise license cost. Confirmed by composer deps.
13 Coveo tier + QPM Enterprise “Personalisation as you go” at 100,000 QPM — confirmed by Robert from the Coveo quote email.
14 Provider questions submitted Both Coveo and Algolia contacted 2026-07-08 — responses received 2026-07-10. See C1–C12 and A1–A14 below.
C1 Coveo: what counts as a query at 100k QPM? PLP page load = 1 query. Each facet selection, pagination, sort = additional query.
C2 Coveo: QPM cap — hard throttle or overage? Not a hard monthly cap. Evaluated across subscription term. No auto-restriction — commercial review if exceeded.
C3 Coveo: Is Generative Answering (RGA) included? Separate. Measured in GQPM — not standard QPM.
C4 Coveo: Source architecture options? Three options confirmed: (A) 116 per-store-view sources, (B) 6 per-website sources via Tracking ID + Storefront Association — both work today, no connector changes. (C) multi-market single source — PS commits to connector enhancements if chosen, not yet built. Source count does not affect subscription cost.
C5 Coveo: Partial price update or full re-push? Partial updates supported. Individual dictionary values updated without re-indexing full record. Turbo connector supports this.
C6 Coveo: Dictionary field key limits at 66 groups? 66 is well within limits. Reference customer has 10,000 keys per dictionary (numeric values).
C7 Coveo: Batching/chunking for 7,800 × 116 store views? Batch by payload size, not product count.
C8 Coveo: B2B connector auto-populate dictionary field? Not out of the box. Store-scoped pricing: yes. Customer-group pricing: requires small connector enhancement — Coveo says "relatively minor."
C9 Coveo: Delivery Assurance workshops — flexible? Yes. Can dedicate sessions to Push API schema, 66 price groups, SKU tokenisation before any code written.
C10 Coveo: Implementation review scope? End-to-end — frontend search, analytics, query pipeline config, and go-live readiness.
C11 Coveo: Search API SLA? Search API: 99.99% (5 nines in NA). Push API: no separate SLA stated.
C12 Coveo: Multi-language tokenisation config? Per-document "language" field. Current connector separates by locale/store view. Multi-market approach removes this constraint but connector not yet built.
A1 Algolia: Premium tier minimum commitment? 12-month minimum. Pricing scoped per project.
A2 Algolia: Record count at PE's scale? Algolia scopes PE at 2.7M records (store views + sort replicas). 240k quote cap is significantly underscoped.
A3 Algolia: Delivery Assurance equivalent? Onboarding service with PS workshops. Less structured than Coveo's 10-workshop DA.
A4 Algolia: 20-price limit — hard or soft? Recommended ceiling, not a hard limit. Practical max: 100 price lists per product.
A5 Algolia: Lazy-load pricing — officially supported? Documented, well-established approach. Implementation is bespoke dev work owned by Ayko.
A6 Algolia: Lazy-load latency / caching? Entirely depends on Magento pricing API — outside Algolia's scope.
A7 Algolia: Secured API Keys — OOTB in M2 module? Keys are virtual, no rate limit. Not supported OOTB in M2 module. Use unretrievableAttributes for field visibility.
A8 Algolia: Compatible with Magento 2.4.6-p15 + B2B? 2.4.6 not guaranteed since v3.16. No known Shared Catalog issues.
A9 Algolia: Breaking changes for bespoke themes? Cannot officially support customised solutions. Every release documents breaking changes.
A10 Algolia: Frontend override depth — theme vs fork? Three valid paths: (1) indexing only + custom FE, (2) InstantSearch + theme override, (3) v3.18+ Adapter module (SSR).
A11 Algolia: ElasticSuite migration path? No specific guide. Indexing/frontend/faceting migrate cleanly; low-level analyzer tuning does not.
A12 Algolia: Merchandising rules across 116 indexes — shareable? Propagatable via direct targeting or wildcard.
A13 Algolia: Infix SKU matching configurable? Achievable via API-level config. Not in M2 module UI.
A14 Algolia: Built-in fallback to native Magento search? No built-in fallback. Requires custom implementation.

11. Remaining Questions

Provider Q&A responses received 2026-07-10. Qs C1–C12 and A1–A14 now resolved in §10. Below: what is still outstanding.

Still awaiting — Coveo

  1. [Turbo module upgrade path] Given 2 commits, what is the upgrade/compatibility path for new Magento minor/patch versions? Tested against 2.4.7+?
  2. [API deprecation policy] Formal deprecation notice period for Headless SDK and Search/Push API. Governed by enterprise contract?
  3. [P1 SLA] Search fully offline — guaranteed response and resolution time under Enterprise?
  4. [Support triage] Magento data edge case causes index corruption/sync failure — how does Coveo triage responsibility vs our implementation?

Still awaiting — Algolia

  1. [P1 SLA] Search fully offline — guaranteed response and resolution time at PE's contract tier?
  2. [P2 SLA] Degraded results / prices not showing — classified differently from full outage?
  3. [Support triage] Bug triggered by Magento data edge case — Algolia support scope or treated as custom code?
  4. [PESLA-1599 support scope] If lazy-load pricing endpoint causes prices to fail — within Algolia support scope or entirely Ayko's responsibility?
  5. [Named contact] Named account contact or ticket queue only? Who to call at 2am?
  6. [Record count — CRITICAL] Algolia confirmed PE scopes at 2.7M records. Quote Q-55286 cap is 240k. Need revised quote confirming cost at actual scale and overage rates at 2.7M records.
  7. [Quote expiry] Quote Q-55286 stipulated sign-off by 30 June 2026 — date passed. Revised quote required.

12. Production Support & Incident Ownership

The operationally critical question that architecture analysis alone can't answer is support — if there's a bug caused by a specific bit of data that takes search offline, how soon would they fix it?

When search goes offline — who owns it?

Failure scenario Algolia ownership Coveo ownership
Platform API outage ✅ Algolia — covered by SLA ✅ Coveo — covered by enterprise SLA
Module/SDK bug ✅ Algolia (module is theirs) ✅ Coveo (SDK is theirs)
Magento data edge case corrupts index sync 🟡 Grey zone — Algolia may defer to Ayko 🟡 Grey zone — Coveo PS familiarity helps
PESLA-1599 endpoint slow/erroring (prices offline) ❌ Ayko's responsibility — Algolia cannot help ❌ N/A — doesn't exist in Coveo architecture
Custom template/hook causing bad results ❌ Ayko's responsibility ❌ Ayko's responsibility
Token endpoint failure (Coveo only) N/A ❌ Ayko's responsibility (simple, single point)

The PESLA-1599 gap is the material difference. If prices stop rendering — which is a realistic failure mode for the lazy-load endpoint — that is 100% Ayko's problem to diagnose and fix. Algolia will not engage. Coveo doesn't have this failure mode because pricing is handled in the token, not in a bespoke endpoint.

Coveo position (known)

Coveo Enterprise includes 24/7 support with named contacts and a Delivery Assurance team familiar with the implementation. Because Coveo PS reviewed the architecture during workshops, they understand the codebase when something goes wrong — faster triage, less finger-pointing.


13. Post-Project Maintenance Considerations

Ongoing maintenance cost is not reflected in the tier estimates and must be considered separately.

Algolia

Maintenance item Frequency Notes
Module version upgrades Per Algolia release cycle Each upgrade risks breaking bespoke hooks (PESLA-1599 pricing, custom product card, non-transactional CTA). Requires regression test across key store views.
PESLA-1599 endpoint maintenance As Magento pricing logic changes If PE add customer groups, change tier pricing structure, or modify shared catalog rules, the custom pricing endpoint may need updating.
Index configuration (116 stores) Ongoing New attributes, new facets, merchandising rules must be configured per-index in Algolia dashboard. No bulk tooling confirmed.
Synonym / relevance management Ongoing Per-index — changes across all 116 store views require either manual repetition or API scripting.
Badge management Per new badge type New condition-based badge requires dev involvement to add template logic.

Coveo

Maintenance item Frequency Notes
Coveo Turbo module upgrades Low cadence (2 commits currently) Unknown upgrade risk — module is immature. Fewer upgrades expected but less battle-tested. Parity question sent to Coveo PS.
Headless SDK / Search API deprecation Per Coveo release cycle Headless SDK is npm/semver — pinned version stays stable until you choose to upgrade. REST API (/rest/search/v2) has been stable for years. Enterprise contracts include formal deprecation notice periods. Not a quarterly forced cycle like Shopify. Major SDK version bumps (v1→v2→v3) may require frontend updates but are infrequent. Deprecation policy question sent to Coveo.
Push API schema changes Only if PE's product data model changes Adding a new price group = add a dictionary field key. No re-architecture required.
Source configuration Only if new websites/store views added New store view = new source config. More manual than Algolia's auto-creation.
Merchandising / relevance tuning Ongoing Shared pipeline rules — changes apply across all sources. PE team can manage some of this via Coveo admin without dev.
Badge management PE self-serve Field-conditional rendering — PE team can add/modify badge conditions in Coveo admin without dev involvement.
Subscription review Annual QPM tier vs actual usage — ensure PE aren't overprovisioned or hitting cap.

Maintenance summary

Algolia Coveo
Module upgrade risk Higher (frequent releases, custom hooks at risk) Lower but unknown (immature module). SDK pinned — stable until deliberately upgraded.
API deprecation risk Standard semver (same model as Coveo) Enterprise notice period in contract. Not Shopify-style quarterly forced cycle.
B2B pricing maintenance Bespoke endpoint (Ayko dependency) Token context (self-maintaining)
Index/source management Per-index, 116 stores, no bulk tool confirmed Shared pipeline, lower overhead
Badge/merchandising self-service ❌ Dev required per change ✅ PE self-serve
PE team autonomy Low Higher

Over a 3-year contract, Coveo's lower ongoing maintenance overhead is a meaningful TCO advantage that does not appear in the Tier implementation estimates.


14. Product Recommendations & Tracking Requirements

Coveo plan — what's included

The quoted plan (Coveo for Commerce) bundles three things:

Recommendation types — both platforms

Recommendation type Coveo Algolia (Recommend — included in Q-55286)
Frequently Bought Together ✅ ML-based ✅ ML-based
Viewed Also Viewed ✅ ML-based ✅ ML-based
Trending / Popular
Personalised (per user) ✅ Integrated into search ranking itself ✅ Separate Recommend API call
Visual similarity ✅ (requires image data)
Query-based
Rules-based override ✅ Business-Aware Ranking in admin ✅ Merchandising rules per index

Both are ML-based, not purely rule-driven. Neither replaces Magento's native Product Recommendations (Adobe Sensei) — that's a separate module.

Tracking instrumentation required

Both platforms use the same model: instrument the frontend to fire events that train the ML. Quality of recommendations = quality + volume of event data.

Event When it fires Required for PE note
Search click User clicks a product from search results All recommendation types, relevance Largely automatic via both platforms' modules/SDK
PDP view Any product page load Viewed Also Viewed, Related Products Needs wiring on every PDP load
Add to cart Product added to cart (ideally with query ID) Frequently Bought Together Magento observer or GTM
Purchase / order complete Order confirmed, all items + values Frequently Bought Together, Trending, Personalisation Magento observer on order success
Enquiry submission Enquiry form completed Treated as conversion PE-specific — custom event mapping required. Neither platform has a native enquiry type.
Recommendation click User clicks a recommended item Training the recommendation model Automatic once recommendation widgets are built
Facet / filter use Filter applied Relevance tuning Largely automatic

Algolia (Luma module)

The M2 module ships with Insights API integration. Search result click tracking is largely automatic once enabled in module config. PDP view, cart, and purchase events need Magento observer wiring — hooks exist in the module but need configuring. User token = Magento customer ID for logged-in users, cookie for guests. Important caveat at Tier 2/3: as module templates are increasingly overridden, the module's automatic Insights event chain can break silently. Heavily customised implementations may need manual event rewiring — putting them in the same position as a bespoke build anyway, but with less control.

Coveo (Headless SDK + Alpine.js)

The SDK controllers (ResultList, SearchBox, FacetList) fire search and click analytics automatically when properly configured. PDP views, cart, and purchase events need wiring via Coveo's analytics actions (logProductClick, logCartAction, logPurchase). In practice, not an issue: since all Coveo components are built as bespoke Alpine.js components from scratch, a single reusable tracking abstraction (e.g. a useTracking() helper) can be baked into the component templating layer and imported across every search, PLP, and recommendation component. Event dispatch is consistent, centralised, and doesn't depend on module hooks. This is a meaningful implementation advantage over Algolia at Tier 2+.

Cold start — both platforms

Neither platform can produce meaningful recommendations on day one.

PE have 116 store views across the EU. For anonymous users, cookie-based behaviour tokens require consent under GDPR before any tracking fires. Logged-in B2B users are likely covered by existing platform terms, but anonymous tracking needs checking against PE's cookie policy before instrumentation goes live.