# PHP SDK

Server-side PHP SDK mirroring the Mixpanel PHP library - if you have used `mixpanel-php` you already know this SDK. Requires PHP 8.1+ with `ext-curl` and `ext-json`, no other dependencies.

## Install

```bash
composer require cohorly/cohorly-php
```

## Initialize

```php
<?php
require 'vendor/autoload.php';

use Cohorly\Cohorly;

$cohorly = Cohorly::getInstance('YOUR_PROJECT_TOKEN', [
    'host' => 'https://cohorly-service.velloalabs.com', // your Cohorly server
]);

// Track an event
$cohorly->track('button clicked', [
    'distinct_id' => 'user-123',
    'label' => 'sign-up',
]);

// Or identify once and let every subsequent event carry the id
$cohorly->identify('user-123');
$cohorly->track('page viewed', ['page' => '/pricing']);

// Profile updates
$cohorly->people->set('user-123', ['$name' => 'Ada', 'plan' => 'pro']);
```

Events are queued in memory and sent in batches: when the queue
reaches `max_batch_size`, when you call
`flush()`, or automatically in the destructor at the end of
the request - like mixpanel-php.

## API

| Member                                                    | Notes                                                                                                        |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `Cohorly::getInstance($token, $options)`                  | Singleton per token. Options: `host`, `max_batch_size` (50, server cap 500), `consumer`, `debug`, `timeout`. |
| `track($event, $props)`                                   | Stamps `time` (unix ms), `$insert_id`, `$lib`, `$lib_version`; call-site props win.                          |
| `identify($id)` / `register($k, $v)` / `reset()`          | Request-lifetime identity and super properties, like mixpanel-php.                                           |
| `alias($alias, $distinctId)`                              | POST /alias (flushes queued events first to preserve ordering).                                              |
| `people->set / setOnce / increment / remove / deleteUser` | Profile updates mapped to /engage ops.                                                                       |
| `flush()`                                                 | Deliver all queued messages now.                                                                             |

## Delivery and retries

Implements the shared Cohorly retry contract: 429/5xx/network errors
keep the queue with exponential backoff honoring
`Retry-After`; 413 halves the batch size; 400 drops the
batch; 401 keeps the queue at max backoff; the queue caps at 1000
messages. PHP processes are request-scoped, so anything still queued
is retried on `flush()` or in the destructor. Custom
consumer strategies are pluggable exactly like mixpanel-php.
