Two-Way Product Catalog Synchronization with a PIM System
Imagine this: you export products from Akeneo to Excel, then manually upload them to your website. A week later, a manager changes the price in the PIM, but the old price remains on the site. Customers leave for competitors. According to statistics, outdated prices lead to a loss of up to 30% of potential revenue. Two-way synchronization solves this problem: changes in the PIM instantly appear on the site, while site data (ratings, stock) flows back to the PIM. This isn't theory—we've implemented such integrations for 20+ projects. The result: up-to-date prices, a single source of truth, and no manual effort. Compared to manual updates, two-way synchronization brings products to market three times faster.
A typical scenario: the product description is updated in the PIM and new photos are added, but the website still shows the old information. A potential buyer sees outdated data and leaves for a competitor. Or the opposite: a new review appears on the site, but marketing in the PIM doesn't see it. Two-way synchronization removes this asymmetry. The financial savings from automation can be significant.
In this article, we'll break down the technical architecture, common problems, and how to avoid them. We'll use Akeneo as an example, but the approach applies to any PIM: Pimcore, Salsify, Plytix. For an understanding of the basic Product Information Management concept, refer to Wikipedia.
Problems Solved by Two-Way Integration
Typical pain points:
- Data inconsistency—manual entry leads to errors in names, prices, attributes; up to 15% of items may contain inaccuracies.
- Update delays—a product appears on the site a day after being added to the PIM, which is critical for promotional offers.
- Loss of feedback—ratings and reviews from the site don't reach the PIM, so marketing lacks the full picture.
- Conflicts during parallel editing—two managers edit the same product, overwriting each other's data.
- Scaling complexity—adding a new sales channel (marketplace, mobile app) requires reconfiguring the integration, taking up to 10 working days.
These problems reduce conversion by 20–40% and increase operational costs. Two-way synchronization cuts time-to-market by three times and reduces costs by 30%. Implementing two-way synchronization can lower operational expenses by tens of thousands of rubles monthly.
How We Do It: Stack and Architecture
We use the Akeneo REST API v1.0+ with OAuth2. For real-time updates—webhooks (Enterprise only). The base code is in Laravel 10/11, but the approach works with any framework.
Example of Paginated Product Import
class AkeneoSyncService
{
private AkeneoClient $client;
public function syncProducts(): void
{
$cursor = null;
do {
$response = $this->client->getProducts([
'limit' => 100,
'search' => json_encode(['enabled' => [['operator' => '=', 'value' => true]]]),
'search_after'=> $cursor,
]);
foreach ($response['_embedded']['items'] as $item) {
$this->upsertProduct($item);
}
$nextLink = $response['_links']['next']['href'] ?? null;
$cursor = $nextLink ? $this->extractCursor($nextLink) : null;
} while ($cursor !== null);
}
private function upsertProduct(array $akeneoProduct): void
{
$values = $akeneoProduct['values'];
$name = $this->getLocaleValue($values, 'name', 'ru_RU');
$desc = $this->getLocaleValue($values, 'description', 'ru_RU');
$price = $this->getScopedValue($values, 'price', 'ecommerce');
Product::updateOrCreate(
['akeneo_code' => $akeneoProduct['identifier']],
compact('name', 'desc', 'price') + [
'family' => $akeneoProduct['family'],
'categories' => $akeneoProduct['categories'],
'raw_values' => $values, // JSONB—full PIM data
'synced_at' => now(),
]
);
}
private function getLocaleValue(array $values, string $attr, string $locale): ?string
{
return collect($values[$attr] ?? [])
->firstWhere('locale', $locale)['data'] ?? null;
}
}
Handling Webhook Events from Akeneo
Route::post('/webhooks/akeneo', function (Request $request) {
$signature = $request->header('X-Akeneo-Request-Signature');
if (!hash_equals(
hash_hmac('sha256', $request->getContent(), config('akeneo.webhook_secret')),
$signature
)) {
abort(401);
}
foreach ($request->json('events') as $event) {
match($event['action']) {
'product.created', 'product.updated' =>
SyncAkeneoProduct::dispatch($event['resource']['identifier']),
'product.removed' =>
Product::where('akeneo_code', $event['resource']['identifier'])
->update(['active' => false]),
};
}
return response('ok');
});
Attribute Mapping
Each product attribute is mapped from the PIM to the site model. For example, the field values.name.ru_RU.data transforms into name; values.price.ecommerce.data into price. For nested data, we use JSONB fields to preserve the original structures—this simplifies debugging.
How to Ensure Data Consistency During Failures?
We use database transactions and a retry mechanism for API requests. On error—automatic notification via Telegram. Conflicts are resolved using the "last write wins" principle with change history preservation.
Record versioning allows rolling back changes in case of incorrect synchronization. For critical data, manual verification is provided before publication.
Why Choose Akeneo Over a Custom PIM?
Akeneo is open-source, flexible, and has a large community. It already includes ready-made enrichment, assortment management, and localization features. Tailoring to business processes takes days, not months. We assist with customization and integration. Thanks to built-in connectors, Akeneo saves up to 60% of the development budget compared to a custom solution.
How to Choose the Sync Mode?
| Sync Mode | Latency | API Load | Implementation Complexity |
|---|---|---|---|
| Batch (CRON) | From 1 min | Moderate | Low |
| Webhook (realtime) | Instant | High (spikes) | Moderate |
Batch mode suits catalogs with low update frequency—for example, once an hour. Webhook mode is mandatory for high-load e-commerce where prices must update immediately. We help choose the optimal strategy based on load audit.
Process of Work
- Audit—analysis of the current data schema and identification of discrepancies (2–3 days).
- Design—attribute mapping, selection of synchronization strategy, agreement on error handling scenarios (2–4 days).
- Implementation—development of import/export, webhook handlers, unit tests (4–6 days).
- Testing—on a copy of the catalog with reference data, edge case verification (2–3 days).
- Deployment—rollout to the production server, monitoring setup (1–2 days).
- Support—2 weeks of warranty maintenance, fixing potential bugs.
Timeframes
| Stage | Duration (working days) |
|---|---|
| Import from PIM (one-way) | 6–10 |
| Two-way synchronization + webhooks | 10–16 |
| Custom mapping and complex rules | +2–5 |
What's Included in the Work
- Full integration documentation (data schemas, API call descriptions).
- Source code with comments.
- Deployment instructions (Docker, Ansible).
- Repository and CI/CD access.
- Employee training (up to 2 hours).
- 2-week stability guarantee after delivery.
Example Mapping Configuration (YAML)
Example mapping configuration (YAML)
mappings:
product:
identifier: code
attributes:
name:
source: values.name.ru_RU.data
target: name
type: string
description:
source: values.description.ru_RU.data
target: description
type: text
price:
source: values.price.ecommerce.data
target: price
type: float
categories:
source: categories
target: categories
type: array
We are ready to evaluate your project. Contact us—we'll calculate the timeline and cost. Two-way synchronization with a PIM pays off by reducing manual labor and decreasing catalog errors. Get a consultation on integration. Order an audit of your current synchronization—it will take no more than two days.







