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:
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.
<?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);
}
}
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://).
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)
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.
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.
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.