Productsup

Export connector

Send all processed product data to a third-party channel every run.

Once end-users have imported data into Productsup and set up all the needed data modifications, they send the processed data to the export channels of their choice. Export channels are third-party systems where customers sell their products — for example, Amazon or eBay.

To send product data to a channel, the platform provides end-users with two entities:

  • Export — contains all the settings of the selected export channel and its data requirements: what columns the channel needs and what format the data should have.
  • Export destination — a setting within the export that defines the access data and the method of sending data to the channel. An export destination can be a physical storage space (Amazon S3, FTP server, Google Merchant Center FTP, Productsup Server) or an upload mechanism (Content API for Shopping, Facebook Marketing API, YouTube API).

The role of an export connector is to gather all the data in a site relevant to the requirements of a chosen export and use the export destination defined in that export to send the data to the channel. The connector writes feedback reporting the result per product. It runs during the export phase of a site run.

If the third-party channel supports incremental updates, consider using an export-delta connector instead — it only processes products that changed since the last run.

Data flow

Productsup platform → Container API (input) → Your connector → Third-party channel

                                              Container API (feedback) → Productsup platform

Your connector reads the full product feed from the Container API input, sends each product to the third-party system, and writes feedback back to the platform.

How it works at runtime

  1. The platform starts your Docker container and passes export settings as environment variables
  2. Your code reads all products from the Container API input file
  3. For each product, you prepare the payload and send it to the third-party channel
  4. You write feedback for each product (success or failure)
  5. You send progress notifications to the Productsup notification panel
  6. Exit with code 0 (success) or non-zero (failure)
  7. The platform imports the feedback file as a data source on the next site run

Channels

Export connectors are assigned to one or more channels on the Productsup platform. A channel represents an export destination that end-users add to their sites — for example, "Google Shopping" or "Amazon Marketplace".

Channels are managed on the platform side. In the Dev Portal, you select which channels your export connector supports in the Export configuration step. Move channels from the Available list to the Selected list to assign them:

Export configuration in the Dev Portal — select channels and toggle feedback file

Key rules:

  • At least one channel is required before you can release the connector
  • Export connectors use regular (non-delta) channels
  • Export-delta connectors use delta channels — you cannot mix them
  • All assigned channels must have consistent CSA status (either all enabled or all disabled)

See Type-specific config for the Dev Portal configuration fields.

Reading input data

The Container API provides several methods for reading the full product feed.

Iterate products one by one

foreach ($this->containerApi->yieldFromInputFile() as $product) {
    $this->sendToChannel($product);
}

Iterate in batches

Useful when the third-party API supports batch operations.

foreach ($this->containerApi->yieldBatchFromInputFile(100) as $batch) {
    $this->sendBatchToChannel($batch);
}

Count total items

$total = $this->containerApi->countItemsFromInputFile();
$this->containerApi->info("Exporting {$total} products.");

Writing feedback

Feedback captures the result of each product export. Each feedback entry must include an id that matches a product in the input feed. The status and optional message fields report the outcome.

// Single product feedback
$this->containerApi->appendToFeedbackFile([
    'id' => $product['id'],
    'status' => 'success',
]);

// Batch feedback
$this->containerApi->appendManyToFeedbackFile($feedbackItems);

Feedback as an additional data source

The platform imports the feedback file as an additional data source on the next site run. This connects it to the primary data feed, letting end-users see export results alongside their product data.

Feedback file shown as an additional data source in the platform

The feedback file links to the main feed through connection columns — matching ID columns that tell the platform how to join the two data sources. You configure which columns to use in the Dev Portal when enabling feedback files.

Connection column configuration — select the ID column that matches products between feeds

Each export destination can have at most one feedback file.

Logging and notifications

Use log methods for operational messages visible in the Dev Portal run logs. Use notifications for end-user-facing messages that appear in the Productsup notification panel. End-users see notifications in a collapsible panel at the bottom of their site view:

Notification panel in the Productsup platform — end-users see connector messages here

// Logging — visible in Dev Portal run logs
$this->containerApi->info('Starting export.');
$this->containerApi->warning("Product {$id} has missing attributes, skipping.");
$this->containerApi->error("Channel API returned 500 for product {$id}.");
$this->containerApi->debug('Request payload: ' . json_encode($payload));

// Notifications — visible to end-users in the Productsup notification panel
$this->containerApi->sendNotification('success', 'Export completed: 1500 products exported.');
$this->containerApi->sendNotification('warning', 'Export completed with 3 errors.');
$this->containerApi->sendNotification('error', 'Export failed: channel API is unreachable.');

Available log levels: debug, info, notice, warning, error, critical, alert, emergency.

Available notification levels: info, notice, warning, error, success.

Example service

A minimal export service that reads products, sends them to a third-party channel, writes feedback, and reports progress:

<?php

namespace App\Export\Service;

use Productsup\CDE\ContainerApi\ContainerApiInterface;

readonly class ExportService
{
    // Replace with your third-party API endpoint
    private const string CHANNEL_API_ENDPOINT = 'https://api.example.com/products';

    public function __construct(
        private ContainerApiInterface $containerApi,
    ) {}

    public function run(): void
    {
        $totalProducts = $this->containerApi->countItemsFromInputFile();
        $this->containerApi->info("Starting export of {$totalProducts} products to channel.");

        $successCount = 0;
        $errorCount = 0;

        foreach ($this->containerApi->yieldFromInputFile() as $product) {
            try {
                $this->sendToChannel($product);
                $successCount++;

                $this->containerApi->appendToFeedbackFile([
                    'id' => $product['id'],
                    'status' => 'success',
                ]);
            } catch (\Throwable $e) {
                $errorCount++;

                $this->containerApi->warning("Failed to export product {$product['id']}: {$e->getMessage()}");

                $this->containerApi->appendToFeedbackFile([
                    'id' => $product['id'],
                    'status' => 'error',
                    'message' => $e->getMessage(),
                ]);
            }
        }

        $this->containerApi->info("Export finished. Success: {$successCount}, errors: {$errorCount}.");

        if ($errorCount > 0) {
            $this->containerApi->sendNotification('warning', "Export completed with {$errorCount} errors out of {$totalProducts} products.");

            return;
        }

        $this->containerApi->sendNotification('success', "Export completed: all {$totalProducts} products exported successfully.");
    }

    /**
     * Send a single product to the third-party channel.
     *
     * Replace this with your real API call — POST to a partner API, upload to a marketplace,
     * push to an advertising platform, etc.
     */
    private function sendToChannel(array $product): void
    {
        // Example: POST the product to the channel's API endpoint
        //
        // $response = $this->httpClient->request('POST', self::CHANNEL_API_ENDPOINT, [
        //     'json' => [
        //         'external_id' => $product['id'],
        //         'title'       => $product['name'],
        //         'price'       => $product['price'],
        //     ],
        // ]);
        //
        // if ($response->getStatusCode() !== 200) {
        //     throw new \RuntimeException("Channel API returned status {$response->getStatusCode()}");
        // }
    }
}

You can find this example in the quickstart repository under src/Export/.

Configuration

Export connectors have several type-specific configurations:

  • Channels — which export channels this connector supports (at least one required)
  • Feedback file — enable/disable feedback and configure connection columns
  • Category-specific attributes — enable support for category-specific attributes

See Type-specific config for details.

Individual configs on the platform

The individual configuration options you define for your connector in the Dev Portal (API keys, target countries, upload intervals, etc.) are presented to end-users as form fields on the export destination page in the Productsup platform. End-users fill in these fields to configure the connector for their specific site:

Individual config fields shown to end-users on the export destination page in the Productsup platform

Next steps

How is this guide?

On this page