# Extensibility
## Customize layout
You can customize the default layout of the autocomplete or instantSearch by extending the Algolia plugin. In this example, we extend the Algolia autocomplete, and the same approach can be applied to instantSearch.

Override `CampitAlgoliaSearchPlugin` in `main.js`

``` js
import AlgoliaSearchOverridePlugin from './js/plugin/algolia-search-override.plugin';

PluginManager.override('CampitAlgoliaSearch', AlgoliaSearchOverridePlugin, '[data-campit-algolia-search]');

```

1. Create a new JavaScript plugin ex. `algolia-search-override.plugin.js`
2. Extend `CampitAlgoliaSearchPlugin` class
3. Override for example the `_renderAutocompleteItemTemplate` function. You can add a layout to your liking

``` js
import CampitAlgoliaSearchPlugin
    from "../../../../../../../../vendor/store.shopware.com/campitalgolia/src/Resources/app/storefront/src/plugin/campit-algolia/campit-algolia-search.plugin";

export default class AlgoliaSearchOverridePlugin extends CampitAlgoliaSearchPlugin {
    _renderAutocompleteItemTemplate(hit, components, html) {
        // your custom design
    }
}
```

## Index additional data
### Extend product indexer
Add additional data to the product index or change existing product data

- Create a data mapper by implementing the `ProductMapperInterface` interface

``` php
class ProductCustomDataMapper implements ProductMapperInterface
{
    public function __invoke(array $product, SalesChannelEntity $salesChannel, Context $context, ?array $allowedFields = null): array
    {
        return [
            'customData' => $product->getCustomData(),
        ];
    }
}
```

- Subscribe to an event

Event   | Description
---     | ---
BeforeProductsFetchedEvent | Change the query to fetch product data
ConfigureAllowedFieldsEvent | Control which fields are indexed (allowlist)
IndexSetSettingsEvent | Add additional index settings
ProductMapperEvent | Map additional product data to the index

## Limit indexed fields

By default, all product fields are indexed. For large datasets or to reduce Algolia record size, you can limit which fields are sent to Algolia using the `ConfigureAllowedFieldsEvent`.

When an allowlist is configured, only the specified fields will be computed and indexed. This improves performance as expensive operations are skipped for excluded fields.

``` php
class AllowedFieldsListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [ConfigureAllowedFieldsEvent::class => '__invoke'];
    }

    public function __invoke(ConfigureAllowedFieldsEvent $event): void
    {
        if ('product' !== $event->getIndexerName()) {
            return;
        }

        $event->setAllowedFields([
            'name',
            'productNumber',
            'image',
            'prices',
        ]);
    }
}
```

### Add new indexer
Index additional entities like blogs, events, CMS pages, etc. This data can be shown in the frontend. 

Create for example a `BlogIndexer` and extend from the `AbstractIndexer`. 
``` php
class BlogIndexer extends AbstractIndexer 
{
    public function entityName(): string
    {
        return BlogDefinition::ENTITY_NAME;
    }

    public function name(SalesChannelEntity $salesChannel, string $languageId): string
    {
        return sprintf('%s-%s-%s', $this->entityName(), $salesChannel->getId(), $languageId);
    }

    public function data(array $ids, SalesChannelEntity $salesChannel, Context $context): array
    {
        // fetch data
    }
}
```

Retrieve the index name in Twig templates.
``` php
indexName: algoliaIndexName(constant('\\Shopware\\Core\\Content\\Product\\BlogDefinition::ENTITY_NAME'), context),
```

## Extend index settings
Subscribe to `IndexSetSettingsEvent` and add some additional index settings. Example:

``` php
class IndexSettingsSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [IndexSetSettingsEvent::class => '__invoke'];
    }

    public function __invoke(IndexSetSettingsEvent $event): void
    {
        if (!$event->getIndexer() instanceof ProductIndexer) {
            return;
        }

        $settings = $event->getSettings();

        $settings['searchableAttributes'] = [
            'name',
            'productNumber',
        ];

        $event->setSettings($settings);
    }
}
```
