jeffersongoncalves/laravel-optimizely
Integrate Optimizely with Laravel using this package for feature flags, experiments, and A/B testing. It provides configuration and convenient helpers to evaluate decisions and track events in your Laravel applications.
composer require <vendor>/<package>
php artisan vendor:publish --tag=optimizely-config
OPTIMIZELY_API_TOKEN=your-personal-access-token
OPTIMIZELY_PROJECT_ID=123456789
# OPTIMIZELY_BASE_URL=https://api.optimizely.com/v2
# OPTIMIZELY_PER_PAGE=50
use Vendor\Optimizely\Facades\Optimizely;
$running = Optimizely::experiments()
->forProject(config('optimizely.project_id'))
->status('running')
->list();
config/optimizely.php — default project id, base URL, and per-page sizeOptimizelyException exposes the decoded API error body, so start debugging there rather than in the HTTP layerThe first realistic use case is a read-only dashboard or scheduled sync: list projects, list experiments filtered by status, and pull results for completed experiments.
Resolve the default project explicitly. The configurable default project id is convenient, but most production code should pass the project id from your own model rather than relying on global config:
$experiments = Optimizely::experiments()
->forProject($site->optimizely_project_id)
->list();
Use list calls as the entry point, then get by id. The package exposes list/get pairs for projects, experiments, campaigns, audiences, events, and pages. A common pattern is to sync list endpoints into local tables on a schedule, then fetch individual resources only when you need full detail or results.
Filter experiments server-side. The experiment list supports a status filter; use it rather than pulling everything and filtering in PHP:
$paused = Optimizely::experiments()
->forProject($projectId)
->status('paused')
->list();
Treat create/update payloads as raw API arrays. The package is a thin client; build payloads from your own form requests or DTOs and pass them through. Keep a dedicated action class per resource so you can validate required fields before the HTTP call:
$experiment = Optimizely::experiments()->create($projectId, [
'name' => 'Checkout test',
'type' => 'a/b',
// ...
]);
Use results endpoints from queued jobs, not web requests. Campaign and experiment results are heavier calls and often feed reporting screens. Dispatch a job, cache the decoded response, and let the UI read from cache. Invalidate the cache when an experiment is updated or archived.
Wrap mutations in a transaction-like flow. Archive and update are separate API calls. If your domain requires both, record intent locally first, call the API, then reconcile with a get to confirm the final state.
Catch OptimizelyException at the boundary. The decoded error body is the useful part. A typical pattern:
try {
Optimizely::experiments()->update($projectId, $experimentId, $payload);
} catch (OptimizelyException $e) {
report($e);
// $e->getResponseBody() is an array with the API's message/errors
throw ValidationException::withMessages([
'optimizely' => $e->getResponseBody()['message'] ?? 'Optimizely request failed',
]);
}
Paginate deliberately. Set a sane per_page in config and handle the pagination metadata returned by list endpoints. For sync jobs, loop until the API indicates no further pages, and persist a cursor or last-synced timestamp so reruns are idempotent.
Keep a single client instance per request/job. If the package binds the client as a singleton, reusing it avoids repeated config resolution. In long-running queue workers, verify that the client does not cache stale project state across jobs.
per_page is capped by the API. Setting it very high in config will not necessarily return more records; always read the pagination metadata rather than assuming count($items) < $perPage means you are done.OptimizelyException bodies are decoded but not guaranteed to be arrays. The API can return a string body or an unexpected shape on gateway errors. Guard with is_array() before indexing into the body.dd(config('optimizely')) or exception context. Use a redacted config dump or a dedicated debug command.config:cache. If you change the default project id or base URL in .env, run php artisan config:cache in cached environments, otherwise the old value persists in queue workers and Octane processes.retryUntil.try/catch blocks across controllers and jobs.How can I help you explore Laravel packages today?