Send paid orders from any PHP backend
One client sends your server events when the request ends, and an idempotency key makes a repeated webhook count once.
Package mirafive/sdk-php
Set up in 5 steps
Install the package
It needs PHP 8.3 or later with
ext-jsonand has no required Composer dependencies. It sends withext-curlwhen it is loaded, otherwise with PHP streams, or through your own PSR-18 client.Code for step 1 of the PHP setup: Install the package. composer require mirafive/sdk-php
Add the secret key
Use the secret key of a server source from Data → Sources. It stays on the server, so never print it into HTML, JavaScript or a mobile app.
Code for step 2 of the PHP setup: Add the secret key. MIRAFIVE_SECRET_KEY=mf_…
Create one client
new Mirareads the key from$_ENV,$_SERVERorgetenv().track()buffers, and the buffer is sent at the end of the request, every 100 events and onflush(). A flush never takes longer than 3 seconds, even when MIRA FIVE is unreachable.Code for step 3 of the PHP setup: Create one client. <?php declare(strict_types=1); use MiraFive\Mira; require __DIR__.'/vendor/autoload.php'; // Reads MIRAFIVE_SECRET_KEY, and MIRAFIVE_HOST when it is set. $mira = new Mira;
Send the paid order
Call
track()with named arguments where the payment is confirmed. Ids are strings, so cast integer ids with(string). Therevenueproperty feeds your purchase goal.Code for step 4 of the PHP setup: Send the paid order. $mira->track('order_paid', userId: (string) $order->customerId, properties: [ 'revenue' => 328, 'currency' => 'EUR', ]);
Check the key
The install check proves the key and host work and is never stored or billed. A wrong key throws a
MiraErrorinstead. Then track a real event and find it under Data → Live.Code for step 5 of the PHP setup: Check the key. $receipt = $mira->send([['name' => '$install_check']]); var_dump($receipt->reason); // string(13) "install_check"
MIRA FIVE is analytics built around the person. mirafive/sdk-php is its server side for plain PHP and for
frameworks without a MIRA FIVE package: it buffers events, sends them when the request ends, and evaluates
feature flags in your process. Under PHP-FPM, pass a PSR-16 cache your app already has
(new Mira(cache: $psr16Cache)), so every PHP process shares the flag document and pauses delivery together
during an outage.
Where do pageviews come from?
From the browser. Add the two-line script tag to your templates with the website key of a website source. Both sources report into the same project, and the secret key never goes into a page.
How does a paid order reach its channel?
Through the person who paid. With consent, the browser keeps an anonymous id. Send it to your server, for example in
a hidden field of the checkout form, and identify links the visitor’s earlier visits to your user id:
$mira->identify((string) $user->id, ['plan' => 'pro'], anonymousId: $anonymousId);The paid order carries the same user id, so MIRA FIVE puts it on that person, next to the channel of their first
visit. Use your internal id, never an email address. Create a purchase goal for order_paid to see buyers and
revenue per channel and campaign.
How do I make a webhook count once?
send() delivers at once and returns the server’s Receipt. With an idempotency key, a repeat is stored and billed
once:
$receipt = $mira->send([
['name' => 'order_paid', 'userId' => (string) $order->customerId, 'properties' => ['revenue' => 328, 'currency' => 'EUR']],
], idempotencyKey: "order-{$order->id}");send() throws a MiraError when MIRA FIVE refuses the batch or cannot be reached after the retries. track()
and flush() never throw for transport reasons.
The source’s Install tab has Let your coding agent install it, a prompt for Claude Code, Cursor or Codex with every step and the check; for a server source it never contains the secret key. The PHP SDK docs cover queues, transports and flags, and the setup page shows who does what, in order.
Other setups
The same numbers, whichever way your site is built.
Questions and answers
What happens when MIRA FIVE is unreachable?
cache, that pause covers every PHP process. handOff moves delivery to your queue.What about Octane, RoadRunner and queue workers?
$mira->flush() after each request or job.How do I keep tests and local runs quiet?
new Mira(enabled: getenv('APP_ENV') === 'production') sends nothing and needs no key, but still refuses the input production would. To assert on what was sent, pass a transport that records requests.I use Laravel or Symfony. Is this the right package?
mirafive/sdk-laravel and mirafive/sdk-symfony wire this SDK into the container and send after the response. See the Laravel setup and the Symfony setup.