PHP SDK Pro

Send events from any PHP server using a project API key. Works with Laravel, Symfony, WordPress, Slim, and anything else that runs PHP 8.1+ and can make outbound HTTPS calls.

clamp-sh/analytics-phpMIT

Paste to your agent

Wire Clamp into a PHP backend
Adds clamp/analytics, initializes it on app boot, and tracks the project's primary conversion event from the relevant handler.

Install

terminal
composer require clamp/analytics

PHP 8.1+ supported. Requires ext-curl and ext-json (both standard).

Use an API key that starts with sk_proj_ from Settings → API Keys. Keys are scoped to one project.

Quick start

bootstrap.php
use Clamp\Analytics\Analytics;
use Clamp\Analytics\Money;

Analytics::init(
    projectId: 'proj_xxx',
    apiKey: getenv('CLAMP_API_KEY'),
);

// Simple event
Analytics::track('signup', ['plan' => 'pro', 'method' => 'email']);

// Link a server event to a browser visitor
Analytics::track(
    'subscription_started',
    [
        'plan' => 'pro',
        'total' => new Money(29.00, 'USD'),
    ],
    anonymousId: 'aid_xxx',
);

API

Analytics::init(projectId, apiKey, endpoint = null)

Initializes the SDK. Call once at application bootstrap. Stores config in static state on the Analytics class.

Analytics::track(name, properties = [], anonymousId = null, timestamp = null)

Sends a server event. Returns true on success.

Throws ClampHttpException on a non-2xx response, ClampNotInitializedException if init()wasn't called.

new Money(amount, currency)

A typed monetary value. amount is in major units (29.00, not 2900). currency is an ISO 4217 code.

Framework integrations

Laravel

Initialize in a service provider so the SDK is ready before the first request.

app/Providers/AppServiceProvider.php
namespace App\Providers;

use Clamp\Analytics\Analytics;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Analytics::init(
            projectId: config('services.clamp.project_id'),
            apiKey: config('services.clamp.api_key'),
        );
    }
}
app/Http/Controllers/SignupController.php
use Clamp\Analytics\Analytics;

public function complete(Request $request)
{
    $user = $this->createUser($request);

    Analytics::track('signup', [
        'plan' => $user->plan,
        'method' => 'email',
    ], anonymousId: $request->cookie('clamp_aid'));

    return redirect('/welcome');
}

Symfony

Initialize on the kernel boot event.

src/EventSubscriber/ClampInitSubscriber.php
namespace App\EventSubscriber;

use Clamp\Analytics\Analytics;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\KernelEvent;

class ClampInitSubscriber implements EventSubscriberInterface
{
    private bool $initialized = false;

    public function __construct(
        private string $projectId,
        private string $apiKey,
    ) {}

    public function onKernelRequest(): void
    {
        if (!$this->initialized) {
            Analytics::init($this->projectId, $this->apiKey);
            $this->initialized = true;
        }
    }

    public static function getSubscribedEvents(): array
    {
        return [KernelEvent::class => 'onKernelRequest'];
    }
}

WordPress

Initialize on the plugins_loaded action.

my-plugin.php
require __DIR__ . '/vendor/autoload.php';

use Clamp\Analytics\Analytics;

add_action('plugins_loaded', function () {
    Analytics::init(
        projectId: getenv('CLAMP_PROJECT_ID'),
        apiKey: getenv('CLAMP_API_KEY'),
    );
});

add_action('user_register', function (int $user_id) {
    $user = get_userdata($user_id);
    Analytics::track('signup', [
        'method' => 'email',
        'role' => $user->roles[0] ?? 'subscriber',
    ]);
});

Errors and retries

The SDK is synchronous and throws on failure. There are no automatic retries. Wrap calls in try/catch if you want fire-and-forget:

safe_track.php
use Clamp\Analytics\Analytics;
use Clamp\Analytics\ClampException;

try {
    Analytics::track('subscription_started', [...]);
} catch (ClampException $e) {
    error_log('failed to send to Clamp: ' . $e->getMessage());
}

For high-throughput webhook handlers, defer the track() call to a background queue (Laravel queues, Symfony Messenger).

Linking browser and server events

Pass the anonymous ID from the browser to your API, then include it in server-side calls. See the linking pattern on the server-side docs page; the same pattern applies in PHP.