sendermaster / laravel
SenderMaster server APIs and durable Laravel delivery
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- laravel/framework: ^10.10
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Server API integration for PHP 8.1+ and Laravel 10. Verified with PHP 8.3 / Laravel 10. Keep the key empty and collection disabled until migrations, queue configuration and test-site acceptance are complete.
Install
composer require sendermaster/laravel:^0.1.3
Composer installs the SDK into vendor/sendermaster/laravel. The Laravel service provider is auto-discovered and loads the package migration. Commit the application's composer.json and composer.lock; other machines run composer install. No local ZIP, SDK source directory or application repositories override is required after Packagist registration.
Configure and run
SENDERMASTER_ENABLED=false SENDERMASTER_API_KEY= SENDERMASTER_API_HOST=https://api.sendermaster.com SENDERMASTER_QUEUE_CONNECTION=redis SENDERMASTER_QUEUE=default
Use a Private API Key for the same SenderMaster site as the frontend Site Key. It needs customers:write, identity:write and orders:write; catalog synchronization additionally needs products:write. Never use NEXT_PUBLIC_ for this key or send it to a browser.
Before enabling, review and run application migrations in the intended environment, enable Laravel's usual minute scheduler and an asynchronous queue worker (or include the configured queue in Horizon). The package schedules sendermaster:deliver once per minute. It rejects the sync connection. The request only writes to the application database; workers perform network calls.
php artisan migrate php artisan schedule:work php artisan queue:work redis --queue=default --timeout=60 php artisan sendermaster:deliver php artisan sendermaster:outbox
These are setup instructions, not commands automatically executed by the package. Keep workers disabled on production until the test site is accepted. Query sendermaster:outbox for redacted IDs/status/error codes; after repairing a failed payload or configuration, replay its ID with --replay=123. A failed delivery blocks later snapshots in the same resource stream until replayed; other resources continue. No payload editing is provided by this command.
Business success points
use SenderMaster\Laravel\SenderMaster; DB::transaction(function () use ($sdk, $customer, $order) { // Save the application's business state first. $customerDelivery = $sdk->upsertCustomer([ 'externalId' => (string)$customer->id, 'email' => $customer->email, 'sourceUpdatedAt' => $customer->updated_at->toIso8601String(), ]); $sdk->upsertOrder([ 'externalOrderId' => (string)$order->id, 'externalCustomerId' => (string)$customer->id, 'status' => 'PAID', 'totalAmount' => 100, 'currency' => 'GBP', 'orderedAt' => $order->created_at->toIso8601String(), 'items' => [['externalProductId'=>'123', 'quantity'=>1, 'unitPrice'=>100]], ], ['dependsOn'=>$customerDelivery]); });
Pass authoritative business modification timestamps when available; preserve them on replay/backfill. At a live, locked business success point, captureVersion => true opts into a monotonic millisecond snapshot timestamp when an application's second-resolution timestamps cannot distinguish transitions. PARD uses this option for real-time customer/order hooks. The original snapshot is deduplicated; queued payloads and versions remain unchanged during retry. Do not use captureVersion to make an old historical snapshot appear new.
Identity and subscription are separate
Only when the browser grants analytics consent, use SenderMaster\Laravel\Http\Context::capture($request) to read valid SDK anonymous/session IDs. Derive the customer ID from the authenticated account or the saved checkout customer, never an arbitrary external ID submitted by the browser. Use identify with a payload containing externalCustomerId, email and the actual method (SIGN_UP, LOGIN, NEWSLETTER, CHECKOUT). An operation ID captured on the request can be passed via Context::operationId; otherwise the package generates one at enqueue time. logout($anonymousId) unlinks identity; it never deletes the customer. Then the browser calls senderMaster.resetIdentity() to start a fresh identity without changing Cookie consent.
setSubscription works without an anonymous ID or analytics consent:
$sdk->setSubscription([ 'externalCustomerId' => (string)$customer->id, 'email' => $customer->email, // Captures the email the customer consented to. 'channel' => 'EMAIL', 'status' => 'SUBSCRIBED', // or UNSUBSCRIBED 'source' => 'store-newsletter-form', 'policyVersion' => 'email-v1', ], ['dependsOn'=>$customerDelivery]);
Customer sync, account registration, login, purchase and analytics consent never imply marketing subscription. Call this only after an explicit newsletter action. Source subscription cannot clear SenderMaster local unsubscribe, bounce, complaint or manual suppression. The API records operation/evidence atomically and rejects reused IDs with changed data. Older operations cannot replace a newer state. An email snapshot mismatch returns 409 rather than subscribing a changed address.
Reliability and limits
Durable rows are committed with the business transaction and survive queue/server restarts. Each resource is serialized with a recoverable two-minute lease; customer dependencies precede identity/orders. A terminal optional identity dependency removes browser attribution so an order can still synchronize to its saved customer. A required dependency failure stops the dependent delivery. Network failures, 429, 5xx and an unreceived Pixel visitor/session retry with bounded backoff (default eight attempts). Other 4xx fail and require repair. A lost response may retry after a successful server write; server-side versions/operation receipts prevent duplicate business facts.
The package deliberately owns no storefront popup, product field mapping, payment webhooks, authentication routes, or historical import policy. PARD retains those business decisions. Consent withdrawal prevents later identity/attribution when the server has received the withdrawal; already sent facts cannot be recalled. Outbox/operation retention cleanup is an operator responsibility; diagnostics never print keys or payloads.
Verification and support
The release is validated by the SenderMaster maintainer test harness with in-memory database fixtures and mocked API delivery, including retry identity, source versions, resource ordering, leases and dependency failures. Run the merchant application's own integration tests after adapting its business hooks. Installation does not migrate a database, send events, or configure production credentials automatically.
Report SDK issues at https://github.com/zishaunghuang/sendermaster-laravel/issues. Full setup and API contracts are documented at https://docs.sendermaster.com/zh/laravel-sdk/.
Automatic Web Push (0.1.3+)
Upgrade and deploy sendermaster/laravel:^0.1.3. The auto-discovered provider registers /sendermaster-push/sw.js and /sendermaster-push/status without writing any files into the merchant project. After upgrading, clear/rebuild the application's configuration and route caches. Keep the existing site Private API Key with identity:write, SENDERMASTER_ENABLED=true and an HTTPS SENDERMASTER_API_HOST. No additional key or queue is needed for push setup. SENDERMASTER_PUSH_ENABLED=false disables these routes at runtime.
In SenderMaster, initialize Web Push for the same connected domain. The SDK retrieves only that site's installation source using the server-side Private API Key. The public Worker response contains the current origin's ownership marker and script, never the private key, VAPID private key, customer data or upstream error details. It is cached server-side for up to five minutes, separately per API host, credential and exact website origin. Redirects, foreign origins, HTML and invalid source fail closed.
Only the default /sendermaster-push/sw.js path is supported by this adapter; existing custom Worker paths continue to use manual installation. Keep any existing PWA Worker unchanged. The website/server must forward this URL to Laravel and allow direct HTTPS access; a static-file-only nginx rule may otherwise return 404. Correct trusted-proxy configuration is needed when TLS terminates upstream.
Upgrade the existing frontend package to @sendermaster/browser or @sendermaster/react 0.2.2+ and rebuild/deploy once. It discovers the enabled channel automatically; the Laravel package does not inject scripts into HTML or alter storefront pages. Return to SenderMaster to check installation and explicitly enable subscription collection. A real visitor opt-in and a test notification are still required to verify end-to-end delivery.