spryker-eco/algolia

Algolia module

Installs: 232

Dependents: 0

Suggesters: 1

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/spryker-eco/algolia

1.0.0 2026-02-15 17:07 UTC

This package is auto-updated.

Last update: 2026-02-15 17:26:53 UTC


README

Latest Stable Version Minimum PHP Version

The Algolia module provides seamless integration between Spryker Commerce OS and Algolia search service, enabling real-time synchronization of products and CMS pages to Algolia indices for fast, relevant search experiences.

Features

  • 🔄 Real-time synchronization of products and CMS pages to Algolia
  • 🎯 Event-driven architecture using Spryker's Publisher module
  • 🌍 Multi-locale and multi-store support
  • 📦 Batch export capabilities for initial data sync
  • 🔍 Search API integration for frontend and backend
  • ⚙️ Configurable event subscriptions per entity type
  • 🏗️ Modular design with optional module support
  • 🔌 Custom entity index mapping for searching any custom entity in Algolia

Table of Contents

Installation

composer require spryker-eco/algolia

Configure Algolia credentials in your config files:

// config/Shared/config_default.php or config_local.php
use SprykerEco\Shared\Algolia\AlgoliaConstants;
$config[AlgoliaConstants::IS_ACTIVE] = true;
$config[AlgoliaConstants::APPLICATION_ID] = getenv('ALGOLIA_APPLICATION_ID');
$config[AlgoliaConstants::ADMIN_API_KEY] = getenv('ALGOLIA_ADMIN_API_KEY');
$config[AlgoliaConstants::SEARCH_ONLY_API_KEY] = getenv('ALGOLIA_SEARCH_ONLY_API_KEY');
$config[AlgoliaConstants::TENANT_IDENTIFIER] = 'john'; // Add if you use one Algolia account for multiple environments, default is "production".

Step 1: Enable Console Command

File: src/Pyz/Zed/Console/ConsoleDependencyProvider.php

<?php

namespace Pyz\Zed\Console;

use Spryker\Zed\Console\ConsoleDependencyProvider as SprykerConsoleDependencyProvider;
use SprykerEco\Zed\Algolia\Communication\Console\AlgoliaEntityExportConsole;

class ConsoleDependencyProvider extends SprykerConsoleDependencyProvider
{
    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return array<\Symfony\Component\Console\Command\Command>
     */
    protected function getConsoleCommands(Container $container): array
    {
        $commands = [
            // ... existing commands

            // Add Algolia export command
            new AlgoliaEntityExportConsole(),
        ];

        return $commands;
    }
}

Step 2: Configure Entity Exporter Plugins

File: src/Pyz/Zed/Algolia/AlgoliaDependencyProvider.php

<?php

namespace Pyz\Zed\Algolia;

use SprykerEco\Zed\Algolia\AlgoliaDependencyProvider as SprykerEcoAlgoliaDependencyProvider;
use SprykerEco\Zed\Algolia\Communication\Plugin\Algolia\CmsPageAlgoliaEntityExporterPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Algolia\ProductAlgoliaEntityExporterPlugin;

class AlgoliaDependencyProvider extends SprykerEcoAlgoliaDependencyProvider
{
    /**
     * @return array<\SprykerEco\Zed\Algolia\Dependency\Plugin\AlgoliaEntityExporterPluginInterface>
     */
    protected function getAlgoliaEntityExporterPlugins(): array
    {
        return [
            new ProductAlgoliaEntityExporterPlugin(),
            new CmsPageAlgoliaEntityExporterPlugin(),
            // Add more entity exporters here
        ];
    }
}

Step 3: Configure Search Adapter Plugin

File: src/Pyz/Client/Search/SearchDependencyProvider.php

<?php

namespace Pyz\Client\Search;

use Spryker\Client\Search\SearchDependencyProvider as SprykerSearchDependencyProvider;
use SprykerEco\Client\Algolia\Plugin\Search\AlgoliaSearchAdapterPlugin;

class SearchDependencyProvider extends SprykerSearchDependencyProvider
{
    /**
     * @return array<\Spryker\Client\SearchExtension\Dependency\Plugin\SearchAdapterPluginInterface>
     */
    protected function getClientAdapterPlugins(): array
    {
        return [
            new AlgoliaSearchAdapterPlugin(),
            // ... other search adapters
        ];
    }
}

Step 4: Configure Catalog Search Query Plugins

Note: Also requires \Pyz\Shared\Algolia\AlgoliaConfig::isSearchInFrontendEnabledForProducts() to be set to true.

Note 2: Integration heavily depends on SearchHttp module plugins, so they have to be also enabled in src/Pyz/Client/Catalog/CatalogDependencyProvider.php, see the integration guide.

File: src/Pyz/Client/Catalog/CatalogDependencyProvider.php

<?php

namespace Pyz\Client\Catalog;

use Spryker\Client\Catalog\CatalogDependencyProvider as SprykerCatalogDependencyProvider;
use SprykerEco\Client\Algolia\Plugin\Search\AlgoliaSearchQueryPlugin;
use SprykerEco\Client\Algolia\Plugin\Search\AlgoliaSuggestionSearchQueryPlugin;
use SprykerEco\Client\Algolia\Plugin\Search\AlgoliaProductConcreteSearchQueryPlugin;

class CatalogDependencyProvider extends SprykerCatalogDependencyProvider
{
    /**
     * @return array<\Spryker\Client\SearchExtension\Dependency\Plugin\QueryInterface>
     */
    protected function createCatalogSearchQueryPluginVariants(): array
    {
        return [
            new AlgoliaSearchQueryPlugin(),
        ];
    }

    /**
     * @return array<\Spryker\Client\SearchExtension\Dependency\Plugin\QueryInterface>
     */
    protected function createSuggestionQueryPluginVariants(): array
    {
        return [
            new AlgoliaSuggestionSearchQueryPlugin(),
        ];
    }

    /**
     * @return array<\Spryker\Client\SearchExtension\Dependency\Plugin\QueryInterface>
     */
    protected function createProductConcreteCatalogSearchQueryPluginVariants(): array
    {
        return [
            new AlgoliaProductConcreteSearchQueryPlugin(),
        ];
    }
}

Step 5: Configure CMS Page Search Query Plugin (Optional)

Note: Also requires \Pyz\Shared\Algolia\AlgoliaConfig::isSearchInFrontendEnabledForCmsPages() to be set to true.

Note 2: Integration heavily depends on SearchHttp module plugins, so they have to be also enabled in src/Pyz/Client/SearchHttp/SearchHttpDependencyProvider.php and src/Pyz/Client/CmsPageSearch/CmsPageSearchDependencyProvider.php, see the integration guide.

File: src/Pyz/Client/CmsPageSearch/CmsPageSearchDependencyProvider.php

<?php

namespace Pyz\Client\CmsPageSearch;

use Generated\Shared\Transfer\SearchContextTransfer;
use Spryker\Client\CmsPageSearch\CmsPageSearchConfig;
use Spryker\Client\CmsPageSearch\CmsPageSearchDependencyProvider as SprykerCmsPageSearchDependencyProvider;
use SprykerEco\Client\Algolia\Plugin\Search\AlgoliaSearchQueryPlugin;

class CmsPageSearchDependencyProvider extends SprykerCmsPageSearchDependencyProvider
{
    /**
     * @return array<\Spryker\Client\SearchExtension\Dependency\Plugin\QueryInterface>
     */
    protected function getCmsPageSearchQueryPlugins(): array
    {
        return [
            new AlgoliaSearchQueryPlugin(
                (new SearchContextTransfer())
                    ->setSourceIdentifier(CmsPageSearchConfig::SOURCE_IDENTIFIER_CMS_PAGE),
            ),
            // ... other search query plugins
        ];
    }
}

Step 6: Generate Transfers

vendor/bin/console transfer:generate

Step 7: Verify Installation

# List available commands (should show algolia:entity-export)
vendor/bin/console | grep algolia

vendor/bin/console algolia:entity-export

Step 8: Send data to Algolia

vendor/bin/console algolia:entity-export --all

# Or export specific entity types
vendor/bin/console algolia:entity-export product

vendor/bin/console algolia:entity-export cms-page

See Full Indexing section for more details and scheduling options.

See Real-time Synchronization section for real-time updates.

Step 9: Verify data in the Algolia Dashboard

  1. Login to Algolia
  2. Check created indexes and data inside (Search section).
  3. Try searches from the Algolia Dashboard.
  4. Tune index settings (facets, searchable attributes) as needed.

Step 10: Configure Real-time Synchronization

Complete Integration Example:

<?php

namespace Pyz\Zed\Publisher;

use Spryker\Zed\Publisher\PublisherDependencyProvider as SprykerPublisherDependencyProvider;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\Product\AlgoliaProductAbstractPublisherPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\Product\AlgoliaProductConcretePublisherPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\Product\AlgoliaProductConcreteDeletePublisherPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\CmsPage\AlgoliaCmsPagePublisherPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\CmsPage\AlgoliaCmsPageVersionPublisherPlugin;
use SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\CmsPage\AlgoliaCmsPageDeletePublisherPlugin;

class PublisherDependencyProvider extends SprykerPublisherDependencyProvider
{
    protected function getPublisherPlugins(): array
    {
        return [
            // Algolia product publishers
            new AlgoliaProductConcretePublisherPlugin(),
            new AlgoliaProductAbstractPublisherPlugin(),
            new AlgoliaProductConcreteDeletePublisherPlugin(),

            // Algolia CMS page publishers
            new AlgoliaCmsPagePublisherPlugin(),
            new AlgoliaCmsPageVersionPublisherPlugin(),
            new AlgoliaCmsPageDeletePublisherPlugin(),
        ];
    }
}

See Real-time Synchronization section for details on each plugin and their subscribed events.

Step 11: Enable Search in Frontend & API

WARNING: Please make sure you have data in the Algolia indices before enabling search in frontend, otherwise search will return no results.

Enable product and/or CMS page search in the frontend for Algolia integration at the project level.

File: src/Pyz/Client/Algolia/AlgoliaConfig.php

<?php

namespace Pyz\Client\Algolia;

use SprykerEco\Client\Algolia\AlgoliaConfig as SprykerEcoAlgoliaConfig;

class AlgoliaConfig extends SprykerEcoAlgoliaConfig
{
    /**
     * Enable product search in frontend.
     */
    public function isSearchInFrontendEnabledForProducts(): bool
    {
        return true;
    }

    /**
     * Enable CMS page search in frontend.
     */
    public function isSearchInFrontendEnabledForCmsPages(): bool
    {
        return true;
    }
}

Real-time Synchronization

Product Publisher Plugins

Located in: SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\Product\

1. AlgoliaProductConcretePublisherPlugin

Purpose: Publishes product concrete (variant) data to Algolia when products are created or updated.

Default Subscribed Events:

  • Product creation/update events
  • Product localized attributes changes
  • Product images changes
  • Product bundles changes (if ProductBundleStorage exists)
  • Product prices changes (if PriceProduct exists)
  • Product search data changes (if ProductSearch exists)

Behavior:

  • Publishes or updates product concrete data in Algolia indices upon relevant events.
  • Handles multi-store and multi-locale data.

2. AlgoliaProductAbstractPublisherPlugin

Purpose: Publishes all concrete products of a product abstract when abstract-level data changes.

Default Subscribed Events:

  • Product abstract updates
  • Category assignments
  • Product labels
  • Reviews
  • Images
  • Price changes (if PriceProduct exists and enabled in the configuration)

Behavior:

  • Triggers re-indexing of all related concrete products in Algolia when abstract-level data changes.

3. AlgoliaProductConcreteDeletePublisherPlugin

Purpose: Removes deleted products from Algolia indices.

Default Subscribed Events:

  • PRODUCT_CONCRETE_UNPUBLISH
  • ENTITY_SPY_PRODUCT_DELETE

Behavior:

  • Removes product concrete data from Algolia indices when products are deleted or unpublished.

CMS Page Publisher Plugins

Located in: SprykerEco\Zed\Algolia\Communication\Plugin\Publisher\CmsPage\

1. AlgoliaCmsPagePublisherPlugin

Purpose: Publishes CMS page data to Algolia when pages are created or updated.

Default Subscribed Events:

  • ENTITY_SPY_CMS_PAGE_UPDATE

Behavior:

  • Fetches full CMS page data including latest version
  • Checks if page is active AND searchable before publishing
  • Extracts locale-specific flattened CMS content
  • Sends complete page data to Algolia for indexing
  • Removes pages from all relevant indices if page is inactive or not searchable

2. AlgoliaCmsPageVersionPublisherPlugin

Purpose: Publishes CMS pages when new versions are created or published.

Default Subscribed Events:

  • CMS_VERSION_PUBLISH
  • ENTITY_SPY_CMS_VERSION_CREATE

Behavior:

  • Maps CMS version IDs to CMS page IDs
  • Fetches CMS page and version data
  • Extracts full page content with locale-specific data
  • Publishes to Algolia with version metadata

Full Indexing

Usage Examples

# Export all products to Algolia
console algolia:entity:export product

# Export all CMS pages
console algolia:entity:export cms-page --store=DE

# Export for specific store
console algolia:entity:export product --locale=en_US

# Export with custom chunk size
console algolia:entity:export product --chunk-size=200

Schedule Automatic Exports (Recommended)

For periodic full re-indexing, add a cron job to export entities to Algolia on a scheduled basis.

File: config/Zed/cronjobs/jenkins.php

/* Algolia - Weekly full export */
$jobs[] = [
    'name' => 'algolia-export-products',
    'command' => $logger . '$PHP_BIN vendor/bin/console algolia:entity:export product',
    'schedule' => '0 2 * * 0',
    'enable' => true,
];

$jobs[] = [
    'name' => 'algolia-export-cms-pages',
    'command' => $logger . '$PHP_BIN vendor/bin/console algolia:entity:export cms-page',
    'schedule' => '30 2 * * 0',
    'enable' => true,
];

Schedule explanation:

  • 0 2 * * 0 - Runs at 2:00 AM every Sunday (weekly)
  • 30 2 * * 0 - Runs at 2:30 AM every Sunday (weekly)

Note: These cron jobs complement the real-time publisher plugins. The publishers handle incremental updates, while the cron jobs ensure full data consistency by performing periodic complete exports.

Custom Entity Index Mapping

The Algolia module supports searching custom entities that are already indexed in Algolia but are not natively supported by the module (like products or CMS pages). This feature allows you to integrate any custom entity search without creating new plugins or modules.

When to Use

Use entity-to-index mapping when you:

  • Have custom entities (e.g., documents, manufacturers, locations) already indexed in Algolia
  • Want to search these entities from your Spryker storefront
  • Don't want to create custom publisher plugins for simple read-only search

Quick Setup

Step 1: Configure the mapping in your shared config:

<?php

namespace Pyz\Shared\Algolia;

use SprykerEco\Shared\Algolia\AlgoliaConfig as SprykerEcoAlgoliaConfig;

class AlgoliaConfig extends SprykerEcoAlgoliaConfig
{
    public function getEntityToIndexMappings(): array
    {
        return [
            [
                'sourceIdentifier' => 'document',
                'store' => 'DE',
                'locales' => ['de_DE'],
                'indexName' => 'documents_de',
            ],
            [
                'sourceIdentifier' => 'manufacturer',
                'store' => '*', // All stores
                'locales' => ['*'], // All locales
                'indexName' => 'manufacturers',
            ],
        ];
    }
}

Step 2: Create a search query plugin:

<?php

namespace Pyz\Client\YourModule\Plugin\Search;

use Generated\Shared\Transfer\SearchContextTransfer;
use Spryker\Client\Kernel\AbstractPlugin;
use Spryker\Client\SearchExtension\Dependency\Plugin\QueryInterface;

/**
 * @method \Pyz\Client\YourModule\YourModuleFactory getFactory()
 */
class DocumentSearchQueryPlugin extends AbstractPlugin implements QueryInterface
{
    protected const SOURCE_IDENTIFIER = 'document';

    protected ?SearchContextTransfer $searchContextTransfer = null;

    public function getSearchQuery()
    {
        // Your query logic
    }

    public function getSearchContext(): SearchContextTransfer
    {
        return $this->searchContextTransfer ?? (new SearchContextTransfer())
            ->setSourceIdentifier(static::SOURCE_IDENTIFIER);
    }

    public function setSearchContext(SearchContextTransfer $searchContextTransfer): void
    {
        $this->searchContextTransfer = $searchContextTransfer;
    }
}

Step 3: Use the plugin in your dependency provider and execute search.

For a complete implementation guide with examples, see Custom Entity Index Mapping Guide.

Configuration

Available Configuration Methods

Product Events:

  • getProductConcreteSubscribedEvents() - Product variant events
  • getProductAbstractSubscribedEvents() - Product abstract events
  • getProductConcreteUnpublishSubscribedEvents() - Delete events

CMS Page Events:

  • getCmsPageUpdateSubscribedEvents() - Page update events
  • getCmsPageVersionPublishSubscribedEvents() - Version publish events

Search:

  • isSearchInFrontendEnabledForProducts() - Enable product search in frontend
  • isSearchInFrontendEnabledForCmsPages() - Enable CMS page search in frontend

Insights & Analytics & Personalization:

  • getIsPersonalizationEnabled() - Enable/disable Algolia Personalization for search. This feature requires a premium Algolia plan.
  • getProjectMappingFacets() - Facet names mapping for Algolia Insights event tracking (via TraceableEventWidget).

Default Event Subscriptions

All publisher plugins get their subscribed events from AlgoliaConfig. The config automatically includes events from optional modules if they exist:

For Products:

  • All product abstract and product concrete events
  • ProductBundle - Bundle events (if module exists)
  • PriceProduct - Price events (if module exists)
  • ProductLabel - Label events (if module exists)
  • ProductReview - Review events (if module exists)

For CMS Pages:

  • CMS - All CMS page and version events

Customizing Event Subscriptions

Extend AlgoliaConfig in your project to customize events:

<?php

namespace Pyz\Zed\Algolia;

use SprykerEco\Zed\Algolia\AlgoliaConfig as SprykerEcoAlgoliaConfig;

class AlgoliaConfig extends SprykerEcoAlgoliaConfig
{
    public function getProductConcreteSubscribedEvents(): array
    {
        // Completely override events
        return [
            'Product.product_concrete.publish',
            'Entity.spy_product.update',
        ];
    }

    public function getCmsPageUpdateSubscribedEvents(): array
    {
        // Extend parent events
        $events = parent::getCmsPageUpdateSubscribedEvents();
        $events[] = 'YourCustom.custom_event';
        return $events;
    }

    public function getDefaultExportChunkSize(): int
    {
        return 500; // Custom chunk size for exports
    }
}

Architecture

Data Flow

Spryker Events (Back Office/API changes/Data Import)
           ↓
Publisher Module (Queue-based processing)
           ↓
Algolia Publisher Plugins
    ├── Product Publishers
    └── CMS Page Publishers
           ↓
AlgoliaFacade → Mappers → Indexers → API Client
           ↓
Algolia Search Service

Event Consolidation

Products:

  • Concrete events: Direct changes to variants
  • Abstract events: Changes affecting all variants
  • The abstract publisher fetches all active concrete products

CMS Pages:

  • Page update events: Direct entity changes
  • Version publish events: New version creation
  • Delete events: Page removal (unpublish)
  • Both update and version plugins ensure pages stay current

Troubleshooting

No entity types available

Problem: "No entity exporters are registered"

Solution:

  1. Ensure plugins are registered in AlgoliaDependencyProvider::getAlgoliaEntityExporterPlugins()
  2. Check the dependency provider is in Pyz namespace if extended
  3. Clear cache: console cache:empty-all

Transfer not found

Problem: Class 'Generated\Shared\Transfer\AlgoliaExportCriteriaTransfer' not found

Solution:

console transfer:generate

Events not triggering

Problem: Changes not appearing in Algolia

Solution:

  1. Check AlgoliaConfig::getIsActive() returns true
  2. Verify publisher plugins are registered in PublisherDependencyProvider
  3. Check queue workers are running:
    console queue:task:start publish
  4. Debug publishing with Xdebug docker/sdk console -x queue:task:start publish or using logs.

Search requests are failing

Problem: Search queries return errors or no results

Solution:

  1. Verify Algolia credentials in config are correct
  2. Ensure indices exist in Algolia dashboard
  3. Disable personalization getIsPersonalizationEnabled() if you use not premium plan.

Migration from ACP Algolia App

If migrating from MessageBroker-based Algolia ACP App:

Note: The logic of data synchronization remains the same, so if you don't want to re-synchronize all data to Algolia, just use TENANT_IDENTIFIER the same as ACP tenant ID:

$config[AlgoliaConstants::TENANT_IDENTIFIER] = 'tenant-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx';

Step 1: Remove Old Plugins

Remove from src/Pyz/Zed/Publisher/PublisherDependencyProvider.php

// - CmsPageVersionPublishedMessageBrokerPublisherPlugin
// - CmsPageUpdateMessageBrokerPublisherPlugin
// - ProductAbstractUpdatedMessageBrokerPublisherPlugin
// - ProductConcreteCreatedMessageBrokerPublisherPlugin
// - ProductConcreteDeletedMessageBrokerPublisherPlugin
// - ProductConcreteExportedMessageBrokerPublisherPlugin
// - ProductConcreteUpdatedMessageBrokerPublisherPlugin

Remove from src/Pyz/Zed/MessageBroker/MessageBrokerDependencyProvider.php

// - SearchEndpointMessageHandlerPlugin
// - ProductExportMessageHandlerPlugin
// - CmsPageMessageHandlerPlugin

Update in src/Pyz/Client/Search/SearchDependencyProvider.php

  • Replace SearchHttpSearchAdapterPlugin with AlgoliaSearchAdapterPlugin

  • Remove:

// - SearchHttpSearchContextExpanderPlugin

Update in src/Pyz/Client/Catalog/CatalogDependencyProvider.php

Replace them SearchHttp plugins with Algolia equivalents:

  • Replace SearchHttpQueryPlugin with AlgoliaSearchQueryPlugin
  • Replace SuggestionSearchHttpQueryPlugin with AlgoliaSuggestionSearchQueryPlugin
  • Replace ProductConcreteSearchHttpQueryPlugin with AlgoliaProductConcreteSearchQueryPlugin

Update in src/Pyz/Client/CmsPageSearch/CmsPageSearchDependencyProvider.php

  • Replace SearchHttpQueryPlugin with AlgoliaSearchQueryPlugin

Step 2: Add New Algolia Plugins and Configuration

Follow all integration steps from the Installation section.

Step 3: Verify

  • No data migration needed - data structure remains the same
  • Do full re-index using console command (see Full Indexing) section)
  • Configure schedule for periodic exports if needed (see Schedule Automatic Exports section)
  • Test with products update in Back Office
  • Test with a CMS page update in Back Office
  • Check Algolia dashboard for indexed content

Benefits of Migration

  • ✅ Direct integration (no MessageBroker overhead)
  • ✅ Simpler architecture
  • ✅ Better performance
  • ✅ Batch indexing support
  • ✅ Configuration and extensibility

Performance Considerations

Products

  • Published asynchronously via queue system
  • Multiple events for same product are deduplicated
  • Events from optional modules only registered if installed
  • Use AlgoliaConfig to limit events if needed

CMS Pages

  • Published asynchronously via queue system
  • Only active AND searchable pages indexed
  • Not searchable or inactive pages removed from indices

General

  • All plugins check AlgoliaConfig::getIsActive() before subscribing
  • If Algolia disabled, no events processed
  • Initial export uses configurable batch sizes

Support

For issues or questions:

Development

To check/fix code style and run static analysis, use:

composer cs-fix # can be used standalone
composer phpstan # only works together with Spryker project (uses autoloader from it)

for test execution check details in tests/README.md file.

License

This module is licensed under the same license as Spryker Commerce OS.