casperlaitw/laravel-admob-ssv
Laravel AdMob SSV adds server-side verification for Google AdMob rewarded ad callbacks. It validates SSV signatures and callback parameters so you can securely confirm ad views and award user rewards. Includes simple configuration, key management, and robust validation for production reward flows.
laravel-admob-ssv is a narrow, single-purpose package: it validates Google AdMob server-side verification (SSV) callbacks — verifying the ECDSA signature on the query string against Google's published verification keys — and surfaces a verified event into the host Laravel app. It is not a payments, ads-serving, or analytics package; its blast radius is one HTTP endpoint and one event/job handoff.
Architecture fit. Strong, provided the product already monetizes via AdMob and needs to trust reward/impression callbacks (rewarded ads, in-app currency grants, entitlement unlocks). The package slots in as HTTP middleware plus a route, and delegates business logic to a listener. That matches Laravel's idiomatic shape (middleware → event → queued listener) and keeps verification concerns out of domain code. It is a poor fit if the team instead needs to call AdMob APIs, reconcile ad revenue, or verify callbacks from mediation networks other than AdMob — this package does none of that.
Integration feasibility. Low effort on the happy path: composer require, publish config, register the callback route, point AdMob's SSV callback URL at it, implement a listener. Work concentrates in three places: (1) key caching — verification requires fetching Google's key set, so the cache TTL and the failure behavior when the key endpoint is unreachable must be an explicit decision, not a default; (2) idempotency — Google may retry callbacks, and transaction_id de-duplication is host-app responsibility, not something the package can know about; (3) authorization — the endpoint must be publicly reachable (Google calls it) but must not be usable by third parties to forge grants, which is precisely what signature verification buys, so verification cannot be optional or bypassable in any environment including staging.
Technical risk.
key_id, URL-encoding of the query string before verification) silently fails open or fails closed. This is the highest-severity risk and is not addressed by the changelog.Key questions.
composer.json constraints only, or is there a CI matrix actually running the test suite on Laravel 12 and 13? Is Laravel 13 covered by tests or merely permitted by constraints?transaction_id/replay-handling contract, or is idempotency entirely on us?Stack fit. Requires a Laravel app on the 8.x+ PHP line currently supported by Laravel 11/12/13, with the standard HTTP kernel, service provider auto-discovery, and either a queue worker or synchronous listener capacity. No database, cache, or queue is strictly required, though a cache store is effectively required to avoid a key fetch per callback. Fits cleanly into an existing Laravel monolith or a dedicated "monetization" service; less clean in a polyglot stack where the callback could land on a non-PHP service.
Migration path. From nothing: add the dependency, publish config, register the route, wire the listener, test with a captured real callback (or a fixture signed by a test key). From a hand-rolled verifier: run both in parallel behind a flag on the same endpoint is not advisable — instead verify the package's behavior against recorded production callbacks in a non-production environment, diff the accept/reject decisions, then cut over. From v1.4.0: this is a constraint bump; treat as a routine patch unless the diff shows verifier changes, and confirm Laravel 13 is only adopted deliberately, not as a transitive surprise.
Compatibility. Confirm PHP version alignment with Laravel 13's minimum, and confirm that the package's constraint widening does not drag in an unsupported transitive dependency. Pin the package version in composer.json rather than floating, given the small release volume — you want upgrades to be intentional. If the app is on Laravel 11 today, v1.5.0 is a no-op functionally and can be taken at leisure; the value is unblocking a future Laravel 12/13 upgrade.
Sequencing.
transaction_id) and the listener's failure semantics (retry vs. drop) before production cutover — this is the actual engineering work, not the package install.Maintenance. Low surface area, low churn: the package is a middleware plus a key fetcher, and the last release is a compatibility bump. Ongoing cost is dominated by (a) tracking Laravel major releases and confirming the package keeps up, and (b) the periodic review of the verifier whenever it changes. Budget a few hours per Laravel upgrade cycle, not per sprint.
Support. Community-only: GitHub issues, no vendor SLA, no security disclosure policy observed in the release notes. For a security-relevant endpoint this is the weakest operational dimension. Mitigation is to vendor or fork the verifier if the project becomes load-bearing — the code is small enough that forking is realistic, and doing so converts a supply-chain risk into an owned maintenance line.
Scaling. Verification itself is cheap (one ECDSA verify per callback) and will not be your bottleneck. Two things do scale non-linearly: key fetch traffic (must be cached; a per-callback fetch against Google's endpoint under reward-ad burst load is the realistic capacity failure) and downstream grant processing (must be queued and idempotent, or you will double-grant under retry). Callback volume tracks ad impressions on rewarded formats, which is spiky by nature — size the queue and the idempotency store for peak, not mean.
Failure modes.
Ramp-up. Half a day for a Laravel-fluent engineer to install, wire, and test against a captured callback. Add one to two days for the parts the package does not own: idempotency, failure semantics, monitoring, and a documented replay-test procedure. No specialist crypto knowledge required to operate it, but someone on the team should be able to read and reason about the verification code, because you are trusting it with entitlement decisions.
How can I help you explore Laravel packages today?