rohea/openx-api-client
A PHP client for the OpenX ad server API. It wraps OpenX API endpoints in a simple, reusable interface so PHP or Laravel applications can integrate ad server operations without hand-rolling HTTP requests. Suitable for projects needing programmatic OpenX access.
Install and inspect first. Add the package with Composer.
composer require rohea/openx-api-client
Before writing any code, open composer.json in the package and check two things: (a) which XML-RPC transport it depends on (ext-xmlrpc, phpxmlrpc/phpxmlrpc, or a Zend component), and (b) whether the autoload is PSR-0 or PSR-4. This is a PHP5-era port; expect PSR-0 class paths and possibly a hard dependency on ext-xmlrpc, which was removed from PHP core in 8.0.
Check the source tree, not the README. Since this is a "work in progress", the README is likely thin. Read the client class and the Struct/type classes to see which OpenX v2 methods are actually implemented. Grep for function to get a real method list rather than trusting the docs.
Point at your OpenX/Revive endpoint. The classic v2 XML-RPC URL is:
https://ads.example.com/www/api/v2/xmlrpc/
or the ox/api/v2/xmlrpc/ plugin path on newer Revive installs. Confirm the endpoint responds by hitting logon first.
First use case: authenticate and list inventory. A good smoke test is to log on and pull the zone list for a publisher:
// Verify namespace/class name in the repo first
$client = new \Rohea\OpenXApiClient\OpenXApiClient(
'https://ads.example.com/www/api/v2/xmlrpc/'
);
$sessionId = $client->logon('admin', 'secret');
$zones = $client->getZoneList($sessionId, $publisherId);
print_r($zones);
Once logon and getZoneList work, you have proven the transport, auth, and struct serialization are all functional.
Wrap the client in a Laravel service. Bind it as a singleton on a dedicated manager, and keep the raw client out of controllers.
// AppServiceProvider
$this->app->singleton(OpenXManager::class, fn () => new OpenXManager(
config('services.openx.endpoint'),
config('services.openx.username'),
config('services.openx.password'),
));
Use scoped() if you want a fresh session per request; use singleton() only inside queue workers where you control the lifecycle.
Manage the session explicitly. The v2 API is session-oriented: logon returns a session ID that must be passed as the first argument to nearly every subsequent call. Put this in the wrapper and cache it per request/job:
class OpenXManager {
private ?string $sessionId = null;
public function session(): string {
return $this->sessionId ??= $this->client->logon($this->user, $this->pass);
}
public function __call($m, $args) {
try {
return $this->client->{$m}($this->session(), ...$args);
} catch (XmlRpcFault $e) {
if ($this->isSessionFault($e)) { $this->sessionId = null; }
throw $e;
}
}
}
Typical ad-ops workflow — create a campaign end-to-end:
addAdvertiser → returns advertiser ID.addCampaign (start/end dates, impressions, clicks, priority, weight) → campaign ID.addBanner (campaign ID, name, storage type, image/HTML, size) → banner ID.linkBanner (banner ID + zone ID) to put it live.Store the returned OpenX IDs on your local models (e.g. advertisers.openx_id) so subsequent syncs can update rather than duplicate.
Reporting ingestion. Nightly jobs calling getCampaignStatistics / getBannerStatistics / getZoneStatistics and writing rows into a local ad_stats table is the single most common production use. Always pass a narrow startDate/endDate range, and use the statsBreakdown struct to request only the dimensions you need.
Sync jobs over webhooks. Treat the API as a batch system: queue jobs, chunk over ID lists, and make each operation idempotent by checking for an existing remote ID before creating.
ext-xmlrpc is gone in PHP 8. If the package calls xmlrpc_encode_request / xmlrpc_decode, it will not run on modern PHP. You'll need to shim it or swap the transport for phpxmlrpc/phpxmlrpc.logon on the recognizable session-expired codes only."1" where 1 is needed, or 0 where false is needed, and the API rejects or silently misbehaves. Cast aggressively before building structs.DateTime + setTimezone rather than date().add* call.How can I help you explore Laravel packages today?