The snippet below is exactly what the dashboard generates under Project > Settings > Identity when you choose PHP. Copy it from the dashboard to get your real project ID and audience URL pre-filled.
Install
composer require firebase/php-jwt
Mint a token
<?php
// composer require firebase/php-jwt
use Firebase\JWT\JWT;
$now = time();
$payload = [
"sub" => $user->id,
"email" => $user->email,
"traits" => ["plan" => $user->plan, "amount" => $user->planAmount, "interval" => $user->billingInterval], // amount in cents; interval "month" | "year"
"aud" => "https://reqio.app/p/YOUR_PROJECT_ID",
"iat" => $now,
"exp" => $now + 300,
];
$token = JWT::encode($payload, $_ENV["REQIO_SECRET"], "HS256");
Replace YOUR_PROJECT_ID with your project ID, or copy the full snippet from the dashboard where the audience URL is pre-filled.
Environment variable
Set REQIO_SECRET to the signing secret from Project > Settings > Identity > Reveal secret. Store it in your environment (.env file, server config, or secrets manager) and never echo it into responses.
Laravel example
<?php
namespace App\Http\Controllers;
use Firebase\JWT\JWT;
use Illuminate\Http\Request;
class PageController extends Controller
{
public function index(Request $request)
{
$user = $request->user();
$now = time();
$token = JWT::encode(
[
"sub" => (string) $user->id,
"email" => $user->email,
"traits" => ["plan" => $user->plan, "amount" => $user->plan_amount, "interval" => $user->billing_interval],
"aud" => config("services.reqio.audience"),
"iat" => $now,
"exp" => $now + 300,
],
config("services.reqio.secret"),
"HS256"
);
return view("page", compact("token"));
}
}
{{-- resources/views/page.blade.php --}}
<script
src="https://reqio.app/widget.js"
data-project-id="{{ config('services.reqio.project_id') }}"
data-identity-token="{{ $token }}"
async
></script>
Store the audience URL in services.reqio.audience in config/services.php so you do not hardcode it.
Plain PHP example
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
$now = time();
$token = JWT::encode(
[
"sub" => (string) $_SESSION["user_id"],
"email" => $_SESSION["user_email"] ?? null,
"aud" => getenv("REQIO_AUDIENCE"),
"iat" => $now,
"exp" => $now + 300,
],
getenv("REQIO_SECRET"),
"HS256"
);
?>
<script
src="https://reqio.app/widget.js"
data-project-id="<?= htmlspecialchars(getenv("REQIO_PROJECT_ID")) ?>"
data-identity-token="<?= htmlspecialchars($token) ?>"
async
></script>
Always escape output with htmlspecialchars when interpolating into HTML attributes.
Pass the token to the widget
For server-rendered templates, pass the token via data-identity-token:
<script
src="https://reqio.app/widget.js"
data-project-id="YOUR_PROJECT_ID"
data-identity-token="<?= htmlspecialchars($token) ?>"
async
></script>
For SPAs where the user authenticates after the initial page load, call window.Reqio.identify() from JavaScript after login:
window.Reqio.identify(token);
Traits reference
| Field | Type | Description |
|---|---|---|
| plan | string | Plan name on your billing system, e.g. "pro". |
| amount | int | Recurring charge as billed, in cents. For annual plans send the full annual total; Reqio divides by 12 to derive the monthly value. |
| interval | "month" or "year" | Billing cadence for amount. |
Security
Store REQIO_SECRET in your environment and never echo it into responses. The JWT is short-lived and audience-bound to one project, limiting the blast radius of a leaked token. The signing secret must never leave your server.