Ecommerce

How to Create a Custom Akeneo Connector: Jobs, Steps & UI Forms

When native Akeneo connectors are not enough, build your own: Symfony jobs, custom steps, job instances, CLI execution, and UI forms—based on the official Akeneo create-connector guide.

How to Create a Custom Akeneo Connector: Jobs, Steps & UI Forms
Ecommerce 16 min read

Sometimes native Akeneo connectors will not cover your needs—you need to write your own. According to the official How to create a new Connector guide, a connector is an ensemble of jobs that import or export data in a specific format, and each job is composed of several steps. This Spygar walkthrough mirrors that guide with the critical code paths teams ask us to implement on CE/EE projects.

A connector is a set of jobs—each job is a chain of steps you can extend without rewriting the native export.

What you are building (notify-after-CSV-export example)

The official example extends the native CSV product export: after the file is written, notify another application and include the export directory path. It is intentionally simple so you learn the connector seams—jobs, steps, parameters, CLI, and UI—before tackling new file formats or complex readers/writers.

  • Job = Symfony service tagged akeneo_batch.job (connector name + type import/export)
  • Step = AbstractStep with doExecute() for custom behavior
  • Job instance = saved parameter set you can run from UI or CLI
  • UI = form extensions + form provider so profiles are editable in Spread → Export profiles

1) Configure the job service

Jobs and steps are Symfony services. Declare a product export job almost identical to the native CSV export—only the job name and connector tag change. Ensure your bundle extension loads the YAML (see Symfony DI docs). Full official detail: create-connector.html.

services.yml — job declaration
services:
    acme_notifyconnector.csv_product_export_notify:
        class: 'Akeneo\Tool\Component\Batch\Job\Job'
        arguments:
            - 'csv_product_export_notify' # Job name
            - '@event_dispatcher'
            - '@akeneo_batch.job_repository'
            -
                - '@pim_connector.step.csv_product.export'
            - true # stoppable?
        tags:
            - { name: akeneo_batch.job, connector: 'Acme CSV Notify Connector', type: 'export' }

2) Add a custom step

Extend Akeneo\Tool\Component\Batch\Step\AbstractStep and implement doExecute(StepExecution $stepExecution). Read job parameters, perform your side effect (HTTP notify, SFTP push, message bus publish), and write summary info or errors onto the StepExecution so operators can see outcomes in the job UI.

NotifyStep.php (simplified from official docs)
<?php
namespace Acme\Bundle\NotifyConnectorBundle\Step;

use Akeneo\Tool\Component\Batch\Step\AbstractStep;
use Akeneo\Tool\Component\Batch\Model\StepExecution;

class NotifyStep extends AbstractStep
{
    protected function doExecute(StepExecution $stepExecution)
    {
        $jobParameters = $stepExecution->getJobParameters();
        $directory = dirname($jobParameters->get('storage')['file_path']);
        $fields = sprintf('directory=%s', urlencode($directory));
        $url = $jobParameters->get('urlToNotify');

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);

        if (false !== curl_exec($ch)) {
            $stepExecution->addSummaryInfo('notified', 'yes');
        } else {
            $stepExecution->addSummaryInfo('notified', 'no');
            $stepExecution->addError('Failed to call target URL: '.curl_error($ch));
        }

        curl_close($ch);
    }
}
Register the step and append it after export
services:
    acme_notifyconnector.step.notify:
        class: 'Acme\Bundle\NotifyConnectorBundle\Step\NotifyStep'
        arguments:
            - 'notify'
            - '@event_dispatcher'
            - '@akeneo_batch.job_repository'

    acme_notifyconnector.csv_product_export_notify:
        class: 'Akeneo\Tool\Component\Batch\Job\Job'
        arguments:
            - 'csv_product_export_notify'
            - '@event_dispatcher'
            - '@akeneo_batch.job_repository'
            -
                - '@pim_connector.step.csv_product.export'
                - '@acme_notifyconnector.step.notify' # custom step
            - true
        tags:
            - { name: akeneo_batch.job, connector: 'Acme CSV Notify Connector', type: 'export' }

Because steps are DI services, you can reuse NotifyStep on any export job by listing it in that job’s step array—no copy-paste of notification logic.

3) Job parameters: defaults + validation

A job is a template; a job instance supplies parameters (file_path, urlToNotify, filters, etc.). Implement DefaultValuesProviderInterface and ConstraintCollectionProviderInterface—often in one class—and decorate the native CSV export providers so you keep their constraints while adding urlToNotify (Url constraint, default http://).

Tag JobParameters providers
services:
    acme_notifyconnector.job.job_parameters.csv_product_export_notify:
        class: 'Acme\Bundle\NotifyConnectorBundle\JobParameters\ProductCsvExportNotify'
        arguments:
            - '@pim_connector.job.job_parameters.default_values_provider.product_csv_export'
            - '@pim_connector.job.job_parameters.constraint_collection_provider.product_csv_export'
            - ['%acme_notifyconnector.job_name.csv_product_export_notify%']
        tags:
            - { name: akeneo_batch.job.job_parameters.constraint_collection_provider }
            - { name: akeneo_batch.job.job_parameters.default_values_provider }

If a job needs no extra parameters, use EmptyDefaultValuesProvider and EmptyConstraintCollectionProvider from the Batch component.

4) Create and execute a job instance (CLI)

Create, list, and run
php bin/console cache:clear

# akeneo:batch:create-job <connector> <job> <type> <code> <config> [<label>]
php bin/console akeneo:batch:create-job \
  'Acme CSV Notify Connector' \
  csv_product_export_notify \
  export \
  my_app_product_export \
  '{"urlToNotify": "http://my-app.com/product-export-done"}'

php bin/console akeneo:batch:list-jobs

# Local/dev style run
php bin/console akeneo:batch:job my_app_product_export

# Production: publish to the queue (job workers must be running)
php bin/console akeneo:batch:publish-job-to-queue my_app_product_export --env=prod

Override parameters at runtime with -c / --config when publishing to the queue (for example changing storage.file_path). In production, start one or more job queue daemons—see Akeneo’s job queue daemon docs linked from the installation guide.

5) Configure the UI form for the job

CLI-only jobs frustrate catalog teams. To edit instances in the UI, copy the native csv_product_export edit/show form_extension YAML into your bundle, rename every csv-product-export key to a unique csv-product-export-notify key, then register a JobInstanceFormProvider that maps your job name to that form root.

Form provider service
services:
    acme_notifyconnector.provider.form.job_instance:
        class: 'Akeneo\Platform\Bundle\ImportExportBundle\Provider\Form\JobInstanceFormProvider'
        arguments:
            -
                csv_product_export_notify: pim-job-instance-csv-product-export-notify
        tags:
            - { name: pim_enrich.provider.form }

6) Add a custom field (urlToNotify)

Register a text field view under your job form properties. fieldCode must match the JobParameters key (configuration.urlToNotify). Provide edit (readOnly: false) and show (readOnly: true) variants, plus translation keys for label and tooltip.

form_extensions snippet (edit mode)
pim-job-instance-csv-product-export-notify-edit-properties-url-to-notify:
    module: pim/job/common/edit/field/text
    parent: pim-job-instance-csv-product-export-notify-edit-properties
    position: 190
    targetZone: properties
    config:
        fieldCode: configuration.urlToNotify
        readOnly: false
        label: acme.form.job_instance.tab.properties.url_to_notify.title
        tooltip: acme.form.job_instance.tab.properties.url_to_notify.help

After clearing cache, create/edit profiles via Spread → Export profiles → Create export profile. You can also add custom tabs (for example field mapping) with a frontend form extension that triggers tab:register—covered further in the official guide.

Related official docs

  • How to create a new Connector — https://docs.akeneo.com/master/import_and_export_data/guides/create-connector.html
  • How to import Products from a XML file — next chapter for new formats
  • How to clean a CSV file during a Product import — reader/processor customization
  • Import and Export data overview — jobs, steps, and formats

When Spygar builds custom connectors

We use this pattern for notify-after-export, SFTP drops, ERP acknowledgements, and format adapters—always as upgrade-safe bundles. Pair custom jobs with REST API sync when near-real-time matters (see our API integration guide and Magento/Shopify connectors). For delivery help, visit Akeneo integration services or Akeneo development.

Ready to start your next project?

Let's work together to bring your ideas to life.