Skip to main content

How to add a custom data source

The eChat extension syncs store information, products, categories, CMS pages and Mirasvit Knowledge Base articles to the chatbot's knowledge base. If your store holds content the chatbot should also know about - a blog, brand pages, product manuals, a custom entity - you can add it with a small module of your own.

A data source is called a sync provider. Your module implements one class and registers it, and the extension does the rest: it creates the knowledge base category, cleans the content, pushes each document, and respects the API rate limit.

note

This page is for developers. No configuration is needed in the Magento admin panel - a provider becomes active as soon as the module that ships it is installed.


1. Create the provider class

A provider is any class implementing Mirasvit\EChat\Api\SyncProviderInterface. In practice you extend Mirasvit\EChat\Provider\AbstractSyncProvider, which implements the interface and supplies the defaults, and describe your source:

<?php
declare(strict_types=1);

namespace Acme\Recipe\Provider;

use Acme\Recipe\Model\ResourceModel\Recipe\CollectionFactory;
use Magento\Store\Api\Data\StoreInterface;
use Mirasvit\EChat\Model\SyncDocumentFactory;
use Mirasvit\EChat\Provider\AbstractSyncProvider;

class RecipeProvider extends AbstractSyncProvider
{
private SyncDocumentFactory $syncDocumentFactory;

private CollectionFactory $collectionFactory;

public function __construct(
SyncDocumentFactory $syncDocumentFactory,
CollectionFactory $collectionFactory
) {
$this->syncDocumentFactory = $syncDocumentFactory;
$this->collectionFactory = $collectionFactory;
}

public function getIdentifier(): string
{
return 'acme_recipe';
}

public function getTitle(): string
{
return 'recipes';
}

public function getCategoryName(): string
{
return 'Recipes';
}

public function fetch(StoreInterface $store): iterable
{
$recipes = $this->collectionFactory->create()
->addStoreFilter($store->getId())
->addFieldToFilter('is_active', 1);

foreach ($recipes as $recipe) {
yield $this->syncDocumentFactory->create([
'name' => (string)$recipe->getTitle(),
'identifier' => 'acme_recipe.' . $recipe->getId(),
'body' => (string)$recipe->getInstructions(),
'attributes' => [
'url' => $store->getBaseUrl() . 'recipes/' . $recipe->getUrlKey(),
'meta_description' => (string)$recipe->getMetaDescription(),
'servings' => (string)$recipe->getServings(),
],
]);
}
}
}

What each method does:

  • getIdentifier() - a machine name for your source. Prefix it with your vendor name to keep it unique. This is also the value you pass to the command's --type option.
  • getTitle() - the label shown in the command output. Optional; it defaults to the identifier.
  • getCategoryName() - the knowledge base category your documents belong to. The extension creates it on the first document, and reuses it afterwards.
  • fetch() - produces one document per record.

2. Register the provider

Add one line to your module's etc/di.xml:

<type name="Mirasvit\EChat\Model\ProviderPool">
<arguments>
<argument name="providers" xsi:type="array">
<item name="acme_recipe" xsi:type="object">Acme\Recipe\Provider\RecipeProvider</item>
</argument>
</arguments>
</type>

Add Mirasvit_EChat to the <sequence> in your module's etc/module.xml so your registration is always merged after the extension's own.

That is the whole integration. Run bin/magento setup:di:compile and your source is part of the sync.


3. Check the result

Use --dry-run to see what your provider produces without sending anything to the knowledge base:

bin/magento mirasvit:echat:sync --type=acme_recipe --dry-run --limit=5

Each document is listed with its identifier, name and content length. When it looks right, run the sync without --dry-run.


Writing a provider

Yield documents, do not collect them. fetch() is a generator. Returning an array loads your whole source into memory at once, which matters on a large catalog.

Send raw content. The extension cleans the HTML of the body and of every text attribute for you, including CMS directives and Page Builder styles. Do not clean it yourself, and do not call the knowledge base API - the extension owns the category, the upload and the rate limit.

Make identifiers stable and unique. The identifier is the key the knowledge base updates on, so acme_recipe.42 must always mean the same record. Prefix it with your entity type, or you will overwrite another provider's documents.

Attributes may nest. Values can be text, or arrays - including arrays of arrays, for something like a table of variants and prices. Empty values are dropped, except under keys starting with meta_ or content, where an empty value is kept as a meaningful "not set".

If your source may be absent, return early. A provider whose module is not installed simply never registers. But if your provider reads from something optional, return from fetch() without yielding, and no empty category will be created.

tip

A provider that throws an exception is logged and skipped - the remaining sources still sync. The same is true for a class registered in the pool that does not implement the provider interface.