PHP SDK
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.
Paste to your agent
Install
composer require clamp/analyticsPHP 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
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.
name: event name string.properties: optional associative array. Values may bestring,int,float,bool, orMoney. No nested arrays or plain objects.anonymousId: optional. Links the server event to a browser visitor.timestamp: optionalDateTimeInterfaceor ISO 8601 string. Non-UTC datetimes are normalized to UTC.
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.
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'),
);
}
}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.
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.
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',
]);
});Capturing exceptions
Wrap unexpected exceptions and send them as $error events on the same pipeline as the rest of your tracking, queryable via the MCP errors.* tools.
use Clamp\Analytics\Analytics;
try {
$this->processWebhook($payload);
} catch (\Throwable $e) {
Analytics::captureError($e, ['webhook' => 'stripe', 'event' => $payload->type]);
throw $e;
}See Error capture for the wire shape, length caps, and the MCP read tools.
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:
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.
Links
- Packagist: clamp/analytics
- Source: github.com/clamp-sh/analytics-php