PHP SDK for the idealo Business Click Report API, built on Saloon PHP.
Implements the V2 Detailed Click Report flow only. The deprecated V1 Detailed Click Report (planned shutdown 2026-03-15) is intentionally not included.
- PHP
^8.2 saloonphp/saloon^4.0- A pair of idealo Business API credentials (
client_id+client_secret)
composer require macropage/idealo-business-apiThe SDK reads no env vars itself. Wire your own config:
use IdealoBusiness\IdealoBusinessConnector;
use IdealoBusiness\Data\ClickReportStatus;
$idealo = new IdealoBusinessConnector(
clientId: getenv('IDEALO_CLIENT_ID'),
clientSecret: getenv('IDEALO_CLIENT_SECRET'),
);
// First request triggers auto-auth via boot(). You can also call it explicitly:
$idealo->authenticateWithClientCredentials();
// idealo returns the shop_id directly in the token response for single-shop credentials:
$shopId = $idealo->getAuthenticatedShopId();- Endpoint:
POST /api/v1/oauth/token - Auth: HTTP Basic (
client_id:client_secret) - No request body
- Response fields used by the SDK:
access_token,expires_in,scope,shop_id
The connector caches the token internally. boot() re-authenticates automatically when the token has expired (with a 60-second safety buffer).
The full flow is start → poll → download.
$response = $idealo->clickReports()->start(
shopId: $shopId,
from: '2026-04-20', // YYYY-MM-DD, optional
to: '2026-04-22', // YYYY-MM-DD, optional
);
$data = $response->json();
// $data = ['status' => 'PROCESSING', 'startTime' => '...', 'id' => '<uuid>',
// 'shopId' => 12345, 'from' => '2026-04-20', 'to' => '2026-04-22']
$reportId = $data['id'];HTTP 201 Created on success. endTime is not present while status is PROCESSING.
$response = $idealo->clickReports()->get($shopId, $reportId);
$data = $response->json();
$status = ClickReportStatus::from($data['status']);
// ClickReportStatus::Processing | Failed | SuccessfulPoll responsibly. The SDK ships no built-in polling helper on purpose, so you stay in control of intervals and retries.
The download response is a ZIP archive containing one CSV file. The SDK does not decompress or parse it.
$response = $idealo->clickReports()->download($shopId, $reportId);
// Always treat this as binary. Do NOT call ->json().
file_put_contents("report_{$reportId}.zip", $response->body());Server filename pattern: click-cost-report_{shopId}_{YYYY-MM-DD-HH-MM-SS}.csv.zip.
Inspect with PHP's ZipArchive:
$zip = new ZipArchive();
$zip->open("report_{$reportId}.zip");
$csv = $zip->getFromIndex(0);In order:
Date, Product, idealo Product ID, Category, Customer-IP, Click Type, Site/Partner, Link, Sku, EANs, Cpc
Customer-IPis hashed.EANsmay contain one or more GTIN values.Cpcis the cost per click (decimal).Click Typedistinguishes regularofferclicks from low-price-inventory clicks. See the official docs for the full list.
- 5 requests per 24 hours to
start()per shop. - At least 15 minutes between two
start()calls. - The report covers data up to 15 months in the past, but never including today.
- Previous-day data is typically available from ~05:00 UTC.
- Exceeding the limits returns HTTP 429.
The connector uses AlwaysThrowOnErrors. Non-2xx responses throw Saloon\Exceptions\Request\RequestException. Common ones:
| Status | Meaning |
|---|---|
409 Conflict |
A report is already in progress for this shop. |
429 Too Many Requests |
Rate limit reached (5/24h or 15-min minimum). |
$idealo = new IdealoBusinessConnector($clientId, $clientSecret);
// Optional 3rd arg: $baseUrl (defaults to https://businessapi.idealo.com)
$idealo->authenticateWithClientCredentials(): self
$idealo->getAuthenticatedShopId(): ?int // from token response
$idealo->getTokenScope(): ?string
$idealo->getTokenType(): ?string
$idealo->clickReports()->start(int $shopId, ?string $from = null, ?string $to = null): Response
$idealo->clickReports()->get(int $shopId, string $reportId): Response
$idealo->clickReports()->download(int $shopId, string $reportId): Response- Detailed Click Report V1 (
/api/v1/shops/{shopId}/click-reports) — discontinued 2026-03-15, not implemented. - Daily Click Report — exists at
/api/v1/shops/{shopId}/daily-click-reports/downloadand is not yet covered by this SDK. - The SDK does not decompress ZIPs, parse CSV, validate dates, or poll automatically. Those are application concerns.