Skip to content

CodeExamples

Ahmed Abbas edited this page Apr 7, 2026 · 1 revision

PHP SDK — Code Examples

Complete PHP code examples for all SDK methods.

Creating a User Context

A Context ties all SDK actions to a specific visitor. A unique visitorId is required for deterministic bucketing.

use ConvertSdk\Interfaces\ContextInterface;

$context = $sdk->createContext(
    'visitor-unique-id',
    [
        'country' => 'US',
        'language' => 'en',
    ]
);

As long as the visitorId and experience configuration remain the same, bucketing stays consistent. To ensure consistency even when configuration changes, provide a persistent DataStore (see Configuration).

BucketingAttributes

Every context method that runs experiences or features accepts an optional BucketingAttributes object:

use OpenAPI\Client\BucketingAttributes;

$attributes = new BucketingAttributes([
    'locationProperties' => ['url' => '/pricing'],
    'visitorProperties' => ['plan' => 'pro'],
    'updateVisitorProperties' => true,
    'enableTracking' => true,
    'environment' => 'staging',
    'typeCasting' => true,
    'experienceKeys' => ['specific-experience-key'],
]);
Property Type Description
locationProperties ?array Key-value pairs used for evaluating experience locations
visitorProperties ?array Key-value pairs used for evaluating experience audiences (overwrites same keys from context creation)
updateVisitorProperties ?bool Whether to permanently update in-memory visitor properties
enableTracking ?bool Whether to track bucketing events immediately (default: true)
environment ?string Override environment for this call
typeCasting ?bool Auto-convert feature variable values to the variable's defined type (default: true)
experienceKeys ?array Limit feature evaluation to specific experiences only

Running Experiences

Run All Active Experiences

Loops through each active experience, evaluates targeting rules, and returns the selected variation for each.

use ConvertSdk\DTO\BucketedVariation;
use OpenAPI\Client\BucketingAttributes;

/** @var BucketedVariation[] $variations */
$variations = $context->runExperiences();

// With attributes:
$variations = $context->runExperiences(new BucketingAttributes([
    'locationProperties' => ['url' => '/pricing'],
    'visitorProperties' => ['plan' => 'pro'],
    'enableTracking' => true,
]));

Parameters:

Parameter Type Required Description
$attributes BucketingAttributes|null No See BucketingAttributes above

Returns: BucketedVariation[]

Run a Single Experience

Evaluates a single experience by its key.

use ConvertSdk\DTO\BucketedVariation;
use OpenAPI\Client\BucketingAttributes;

/** @var BucketedVariation|null $variation */
$variation = $context->runExperience('experience-key');

// With attributes:
$variation = $context->runExperience('experience-key', new BucketingAttributes([
    'locationProperties' => ['url' => '/'],
    'visitorProperties' => ['country' => 'US'],
]));

Parameters:

Parameter Type Required Description
$experienceKey string Yes The experience's unique key
$attributes BucketingAttributes|null No See BucketingAttributes above

Returns: BucketedVariation|nullnull when the visitor is not bucketed (rule mismatch, inactive experience, etc.)

Full Experience Example

use ConvertSdk\ConvertSDK;
use ConvertSdk\DTO\BucketedVariation;

$sdk = ConvertSDK::create([
    'sdkKey' => 'your-sdk-key',
]);

if ($sdk->isReady()) {
    $context = $sdk->createContext('visitor-unique-id');

    /** @var BucketedVariation|null $variation */
    $variation = $context->runExperience('experience-key');

    if ($variation !== null) {
        echo $variation->experienceKey; // 'experience-key'
        echo $variation->variationKey;  // e.g. 'variation-1'
    }
}

Location-Scoped Bucketing

Pass BucketingAttributes to scope bucketing to a specific location:

use OpenAPI\Client\BucketingAttributes;

$variation = $context->runExperience('checkout-flow', new BucketingAttributes([
    'locationProperties' => ['page' => '/checkout'],
]));

Running Features

Features are resolved through variations of relevant experiences.

Run All Features

Returns all features with their status and variable values for the visitor.

use ConvertSdk\DTO\BucketedFeature;
use OpenAPI\Client\BucketingAttributes;

/** @var BucketedFeature[] $features */
$features = $context->runFeatures();

// With attributes:
$features = $context->runFeatures(new BucketingAttributes([
    'locationProperties' => ['url' => '/dashboard'],
    'visitorProperties' => ['tier' => 'premium'],
    'typeCasting' => true,
]));

Parameters:

Parameter Type Required Description
$attributes BucketingAttributes|null No See BucketingAttributes above

Returns: BucketedFeature[]

Run a Single Feature

Returns a single feature's status and variable values for the visitor.

use ConvertSdk\DTO\BucketedFeature;
use ConvertSdk\Enums\FeatureStatus;
use OpenAPI\Client\BucketingAttributes;

/** @var BucketedFeature|null $feature */
$feature = $context->runFeature('feature-key');

// With attributes and experience filter:
$feature = $context->runFeature('feature-key', new BucketingAttributes([
    'locationProperties' => ['url' => '/settings'],
    'visitorProperties' => ['role' => 'admin'],
    'typeCasting' => true,
    'experienceKeys' => ['specific-experience-key'],
]));

Parameters:

Parameter Type Required Description
$key string Yes The feature's unique key
$attributes BucketingAttributes|null No See BucketingAttributes above

Returns: BucketedFeature|null

Full Feature Example

use ConvertSdk\ConvertSDK;
use ConvertSdk\DTO\BucketedFeature;
use ConvertSdk\Enums\FeatureStatus;

$sdk = ConvertSDK::create([
    'sdkKey' => 'your-sdk-key',
]);

if ($sdk->isReady()) {
    $context = $sdk->createContext('visitor-unique-id');

    /** @var BucketedFeature|null $feature */
    $feature = $context->runFeature('feature-key');

    if ($feature !== null && $feature->status === FeatureStatus::Enabled) {
        echo 'Feature is enabled';
        print_r($feature->variables);
    }
}

Resolve All Features with Iteration

$features = $context->runFeatures();

foreach ($features as $feature) {
    echo "{$feature->featureKey}: {$feature->status->value}\n";
    foreach ($feature->variables as $key => $value) {
        echo "  {$key} = {$value}\n";
    }
}

Tracking Conversions

Sends a conversion event for a goal. The decision is made against the goal's configured triggering rules.

use ConvertSdk\DTO\ConversionAttributes;
use ConvertSdk\DTO\GoalData;
use ConvertSdk\Enums\GoalDataKey;

$context->trackConversion('goal-key', new ConversionAttributes(
    ruleData: [
        'action' => 'buy',
    ],
    conversionData: [
        new GoalData(GoalDataKey::Amount, 10.3),
        new GoalData(GoalDataKey::ProductsCount, 2),
        new GoalData(GoalDataKey::TransactionId, 'transaction-unique-id'),
    ],
    conversionSetting: [
        'forceMultipleTransactions' => false,
    ],
));

Parameters:

Parameter Type Required Description
$goalKey string Yes The goal's unique key
$attributes ConversionAttributes|null No Conversion attributes (see Return Types)

Returns: RuleError|bool|nullnull on success, false if goal not found or rule failed, RuleError enum on rule mismatch.

Simple Conversion (No Revenue)

$result = $context->trackConversion('signup-completed');

Goal Rule Matching

If a goal has targeting rules, pass ruleData to evaluate them:

use ConvertSdk\DTO\ConversionAttributes;

$context->trackConversion('checkout-goal', new ConversionAttributes(
    ruleData: ['page_type' => 'checkout', 'cart_value' => 100],
));

Revenue Reporting

use ConvertSdk\DTO\ConversionAttributes;
use ConvertSdk\DTO\GoalData;
use ConvertSdk\Enums\GoalDataKey;

$context->trackConversion('purchase-completed', new ConversionAttributes(
    conversionData: [
        new GoalData(GoalDataKey::Amount, 99.99),
        new GoalData(GoalDataKey::ProductsCount, 3),
        new GoalData(GoalDataKey::TransactionId, 'txn-abc-123'),
    ],
));

When conversionData is present, the SDK sends two events: a conversion event and a transaction event (with the goal data).

Force Multiple Transactions

By default, each goal fires once per visitor. For recurring transactions (e.g., subscription renewals), override deduplication:

use ConvertSdk\DTO\ConversionAttributes;
use ConvertSdk\DTO\GoalData;
use ConvertSdk\Enums\GoalDataKey;
use ConvertSdk\Enums\ConversionSettingKey;

$context->trackConversion('subscription-renewal', new ConversionAttributes(
    conversionData: [
        new GoalData(GoalDataKey::Amount, 29.99),
        new GoalData(GoalDataKey::TransactionId, 'renewal-456'),
    ],
    conversionSetting: [
        ConversionSettingKey::ForceMultipleTransactions->value => true,
    ],
));

Behavior Matrix

Scenario Conversion Event Transaction Event
First trigger, no goal data Sent Not sent
First trigger, with goal data Sent Sent
Repeat trigger, no force Not sent Not sent
Repeat trigger, force=true, no goal data Not sent Not sent
Repeat trigger, force=true, with goal data Not sent Sent

Segments

Run Custom Segments

Evaluates segment rules and updates custom segments in the user context.

$context->runCustomSegments(['segment-key-1', 'segment-key-2'], [
    'ruleData' => ['enabled' => true],
]);

Parameters:

Parameter Type Required Description
$segmentKeys string[] Yes List of segment keys to evaluate
$attributes ?array No Associative array with ruleData key-value pairs for segment matching

Returns: ?array — The matched custom segments, or null if none matched.

Set Default Segments

Permanently updates the visitor's default segments for reporting. Only the following properties are included in Convert Reports:

  • browser
  • devices
  • source
  • campaign
  • visitorType
  • country
$context->setDefaultSegments([
    'country' => 'US',
    'browser' => 'chrome',
    'devices' => 'desktop',
]);

Parameters:

Parameter Type Required Description
$segments array Yes Key-value pairs merged with the initial visitor properties

Returns: void


Visitor Properties

Set a Single Attribute

$context->setAttribute('weather', 'rainy');

Parameters:

Parameter Type Required Description
$key string Yes The attribute key
$value mixed Yes The attribute value

Returns: void

Set Multiple Attributes

Merges with existing attributes.

$context->setAttributes([
    'weather' => 'rainy',
    'plan' => 'enterprise',
]);

Parameters:

Parameter Type Required Description
$attributes array Yes Key-value pairs merged with existing visitor properties

Returns: void

Update Visitor Properties

Permanently updates all visitor properties used in audience evaluation via the data store.

$context->updateVisitorProperties('visitor-unique-id', [
    'weather' => 'rainy',
    'plan' => 'enterprise',
]);

Parameters:

Parameter Type Required Description
$visitorId string Yes The visitor ID
$visitorProperties array Yes Key-value pairs merged with the stored visitor properties

Returns: void

Inline Update via BucketingAttributes

Visitor properties can also be updated inline when calling any experience/feature method:

use OpenAPI\Client\BucketingAttributes;

$variation = $context->runExperience('experience-key', new BucketingAttributes([
    'visitorProperties' => ['weather' => 'rainy'],
    'updateVisitorProperties' => true,
]));

Config Entity Lookup

Get Config Entity by Key

Find a single entity in the project configuration by its key.

use ConvertSdk\Enums\EntityType;

$experience = $context->getConfigEntity('experience-key', EntityType::Experience->value);

Parameters:

Parameter Type Required Description
$key string Yes Entity key
$entityType string Yes An EntityType enum value — one of: audience, location, segment, feature, goal, experience, variation

Returns: array — The matching entity data.

Get Config Entity by ID

Find a single entity in the project configuration by its numeric id.

use ConvertSdk\Enums\EntityType;

$variation = $context->runExperience('experience-key');
if ($variation !== null) {
    $changes = $variation->changes;
    foreach ($changes as $change) {
        if (isset($change['data']['feature_id'])) {
            $feature = $context->getConfigEntityById(
                (string) $change['data']['feature_id'],
                EntityType::Feature->value
            );
        }
    }
}

Parameters:

Parameter Type Required Description
$id string Yes Entity ID (as string)
$entityType string Yes Same values as getConfigEntity above

Returns: array — The matching entity data.


Releasing Queues

The SDK batches tracking events and sends them in network requests (configured via events.batch_size). You can manually flush all pending queues at any time.

Key difference from the JavaScript SDK: releaseQueues() is synchronous and returns void, not a Promise. The PHP SDK also registers a register_shutdown_function handler that automatically flushes queues when the PHP process ends.

Manual Release

// From context
$context->releaseQueues();

// With a reason (for debugging)
$context->releaseQueues('page-exit');

// From SDK instance
$sdk->flush();

Context releaseQueues() Parameters:

Parameter Type Required Description
$reason ?string No Custom message for debugging

Returns: void

Automatic Shutdown Handler

The SDK registers a shutdown function during ConvertSDK::create():

register_shutdown_function(static function () use ($apiManager): void {
    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request(); // Send response to client before flushing
    }
    $apiManager->releaseQueue('shutdown');
});

This ensures that:

  1. In PHP-FPM environments, the response is sent to the client first (fastcgi_finish_request()), then queued events are flushed without blocking the response.
  2. In CLI or other SAPI environments, queues are flushed when the script exits.

You do not need to call releaseQueues() manually in typical PHP-FPM request lifecycles. Manual release is useful for long-running processes or when you need immediate delivery.


Events

The SDK emits events that you can subscribe to for logging, analytics integrations, or debugging.

Subscribing to Events

Use the on() method on the SDK instance. The callback receives two arguments: $args (event data) and $err (exception or null).

use ConvertSdk\ConvertSDK;
use ConvertSdk\Enums\EntityType;
use ConvertSdk\Enums\SystemEvents;

$sdk = ConvertSDK::create([
    'sdkKey' => 'your-sdk-key',
]);

// Ready event
$sdk->on(SystemEvents::Ready, function (mixed $args, mixed $err): void {
    if ($err !== null) {
        error_log('SDK initialization failed: ' . $err->getMessage());
        return;
    }
    echo "SDK is ready\n";
});

// Bucketing event (e.g., for analytics integration)
$sdk->on(SystemEvents::Bucketing, function (mixed $args, mixed $err): void {
    if ($err !== null) {
        error_log('Bucketing error: ' . $err->getMessage());
        return;
    }

    $visitorId = $args['visitorId'] ?? null;
    $experienceKey = $args['experienceKey'] ?? null;
    $variationKey = $args['variationKey'] ?? null;
    $featureKey = $args['featureKey'] ?? null;

    // Log or send to analytics
    error_log("Bucketed: visitor={$visitorId} experience={$experienceKey} variation={$variationKey}");
});

// Conversion event
$sdk->on(SystemEvents::Conversion, function (mixed $args, mixed $err): void {
    if ($err !== null) {
        error_log('Conversion error: ' . $err->getMessage());
        return;
    }

    $visitorId = $args['visitorId'] ?? null;
    $goalKey = $args['goalKey'] ?? null;
    error_log("Conversion: visitor={$visitorId} goal={$goalKey}");
});

// Config updated event
$sdk->on(SystemEvents::ConfigUpdated, function (mixed $args, mixed $err): void {
    if ($err !== null) {
        error_log('Config update error: ' . $err->getMessage());
        return;
    }
    echo "Configuration has been refreshed\n";
});

Note: Events registered with on() that are flagged as deferred (e.g., Ready) will fire immediately if the event already occurred before the listener was registered.

Available Events

Enum Case String Value Triggered By Callback Data
SystemEvents::Ready ready SDK initialization complete [] (empty array), with error as second arg on failure
SystemEvents::Bucketing bucketing Running experience(s) ['visitorId' => string, 'experienceKey' => string, 'variationKey' => string]
Running feature(s) ['visitorId' => string, 'experienceKey' => string, 'featureKey' => string, 'status' => string]
SystemEvents::Conversion conversion Tracking a conversion ['visitorId' => string, 'goalKey' => string]
SystemEvents::LocationActivated location.activated Location rules matched Location data
SystemEvents::LocationDeactivated location.deactivated Location rules no longer matched Location data
SystemEvents::ConfigUpdated config.updated Configuration refreshed []
SystemEvents::Segments segments Segments evaluated Segment data
SystemEvents::Audiences audiences Audiences evaluated Audience data
SystemEvents::ApiQueueReleased api.queue.released Event queue flushed to Tracking API Queue data

Clone this wiki locally