1

I'm investigating using Algolia for a search page on a site where the entries have a single main image assets field where the file uploaded is quite large.

Transforms are performed in the Craft templates to output different image sizes.

But how do I send resized images to Algolia when there's just a single image field for the entry?

Are there any plugins that let you perform image transforms before syncing the data to Algolia?

At the moment I'm using https://github.com/brilliancenw/craft-algolia-sync for syncing Craft entries with Algolia. It mentions there is an event where you can intercept data and make changes but I'd need more help figuring out how that should work.

2 Answers 2

2

If you're not comfortable building your own custom module and you're willing to look at alternative Algolia plugins, Scout offers a reasonably simple method for defining the data you want to send to Algolia just inside its config file, and you can easily define image transforms within the transformer function:

// config/scout.php

// Imports
use craft\elements\Entry;
use craft\elements\db\EntryQuery;
use rias\scout\ScoutIndex;
use spacecatninja\imagerx\ImagerX;

return [
    'indices' => [
        ScoutIndex::create("myAlgoliaIndexName")
            ->criteria(function(EntryQuery $query) {
                return $query->section('myContent');
            })
            ->transformer(function(Entry $entry) {
                $logo = $entry->logo->one();
                
                // Generate logo image transform for Algolia using Imager X
                // (other image transform plugins/techniques are available!)
                $logoTransform = ImagerX::$plugin->imager->transformImage($logo,
                    [
                        'width' => 300,
                        'height' => 300
                    ],
                    [
                        'format' => 'webp',
                    ]
                );
                
                // Return the data to sync with Algolia
                return [
                    'id' => (int)$entry->id,
                    'url' => $entry->url,
                    'title' => $entry->title,
                    'logo' => $logoTransform->url,
                ];
            }),
    ],
];

If you want multiple image transforms, you can generate them all and include them in an array of image URLs. The initial Scout indexing operation will take a little time since it has to generate the image transforms but providing those images are cached somewhere once they're generated, subsequent operations ought to be much quicker.

I've shown the code using the Imager X image transformation plugin (which is a paid plugin) because that's what I use with Scout so it was easy to grab a code example, but you could use Craft's own image transforms instead.

4
  • I'd actually already started exploring using Scout after posting this and using native Craft image transforms. Haven't gotten it working with it adding the new image data yet though.
    – Tyssen
    Oct 24 at 23:40
  • Actually, it is now. :)
    – Tyssen
    Oct 25 at 0:42
  • Is there a way to see locally what values are being returned before actually syncing with Algolia? I've got a couple of pieces of data that I want to modify first and testing will be easier if I can do it locally before invoking the import/refresh.
    – Tyssen
    Oct 25 at 1:07
  • Yes, if you don't mind a bit of work setting up your IDE and dev environment to run Xdebug so you can put breakpoints in your Scout transformer methods and inspect the data. If you're using DDEV, it's already set up for you so you'd just need to set up your IDE to allow PHP debugging. Oct 25 at 10:59
2

You can use the EVENT_BEFORE_ALGOLIA_SYNC event to update the record that's being pushed to Algolia. In this event, you can modify the value that's being generated for the asset field, which seems to be the URL of the asset by default. It's not well documented, but the event has a recordElement property which will give you access to the element that's the source of the record. You can use that to access the asset, then update the record's value for that asset:

// Imports
use yii\base\Event;
use \brilliance\algoliasync\services\AlgoliaSyncService;

// init()
Event::on(
    AlgoliaSyncService::class,
    AlgoliaSyncService::EVENT_BEFORE_ALGOLIA_SYNC,
    function (\brilliance\algoliasync\events\beforeAlgoliaSyncEvent $event) {
        /** @var Element $element */
        $event->recordElement;

        $asset = $event->getFieldValue('myAssetField')->collect()->one();

        $event->recordUpdate['attributes']['myAssetField'] = $asset->getUrl([
            'width' => 600,
            'height' => 600,
        ]);
    }
);

You can put that code in a custom module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.