laravel-notification-channels/google-chat
Send Laravel notifications to Google Chat with this dedicated channel. Post messages to Google Chat spaces via incoming webhooks using a simple, familiar notification API—no custom HTTP code required.
Check your platform first (v4.0.0 is a hard floor). The 4.x line requires PHP 8.3+ (8.4 and 8.5 are explicitly supported) and Laravel 12 or 13. PHP 8.1/8.2 and Laravel 9/10/11 were dropped in v4.0.0. If you are still on those, pin ^3.3 — the notification/card API is unchanged between the two majors, so nothing else in this assessment differs.
Install and wire up a space (5 minutes).
Laravel Alerts) and copy the URL. Treat that URL as a secret — it is the only credential.composer require laravel-notification-channels/google-chatconfig/services.php:'google_chat' => [
'webhook' => env('GOOGLE_CHAT_WEBHOOK'),
],
via() at the channel:php artisan make:notification DeploymentFailed
class DeploymentFailed extends Notification
{
public function via($notifiable): array
{
return [GoogleChatChannel::class];
}
public function toGoogleChat($notifiable): GoogleChatMessage
{
return GoogleChatMessage::create()
->text("Deploy #{$this->id} failed on `{$this->env}`");
}
}
routeNotificationForGoogleChat() on a notifiable model, or use an on-demand route:Notification::route('googleChat', config('services.google_chat.webhook'))
->notify(new DeploymentFailed($deploy));
Where to look first. The package's own test suite is the real documentation — the card/widget builders mirror Google Chat's card schema, and method names track that schema more closely than the README does. Read tests/ for exact signatures before building anything fancy.
First real use case. Failed-job and deployment alerting is the sweet spot: a queued ShouldQueue notification fired from App\Exceptions\Handler, a failed() job hook, or a scheduled health check. It is a one-way alert pipe, not an interactive bot.
One webhook per space, routed per notification. Keep URLs in config and let the notification decide the destination rather than hardcoding strings in via(). When a package version supports a configured channel instance (e.g. GoogleChatChannel::webhook($url) returned from via()), that is the cleanest way to send one notification to a specific space without touching the model:
public function via($notifiable): array
{
return [
GoogleChatChannel::webhook(config('services.google_chat.deploy_room')),
];
}
Verify the exact static-method name against the source; older releases only support routeNotificationForGoogleChat().
Cards over plain text for anything actionable. Text is fine for "job failed"; use the card builder for anything with context — commit SHA, environment, a link to logs. Compose Card → Section → TextParagraph / KeyValue / Button (names follow Google Chat's card entities). Buttons are link buttons (openLink), not callback buttons — see Gotchas.
Wrap the builder. Card construction is verbose and schema-coupled. Put a GoogleChatMessage::create()->card(...) factory in a small App\Support\ChatCards helper, or expose domain methods (ChatCards::deployFailed($deploy)). This isolates you from schema changes and keeps notification classes readable. It also makes the v3 → v4 jump a one-line composer.json change, because v4.0.0 is a platform-only release with no builder changes.
Queue and debounce. Always implements ShouldQueue for anything user-facing, and set public $tries/backoff. For bursty events (a job that fails 500 times) aggregate first — a Notification::route(...)->notify() per failure will hit webhook quotas and spam the room. Batch into one digest message every N minutes.
Test with fakes plus payload assertions. Notification::fake() proves you sent the notification; it does not prove the payload is valid. Add one test that captures the generated message (or fakes the HTTP client) and asserts the JSON shape — a malformed card silently 400s in production.
Scheduled digest pattern. Schedule::command('report:digest')->hourly() building one card with a KeyValue per metric is a much better fit for Chat than per-event notifications.
Pin the major, upgrade deliberately. "laravel-notification-channels/google-chat": "^4.0" on Laravel 12/13, "^3.3" on Laravel 9–11. Since v4 is only a support-matrix bump, the upgrade itself is mechanical — but it forces the Laravel 12/13 and PHP 8.3+ move on your schedule, not the package's, so treat the major as a proxy for your framework upgrade deadline.
composer why-not. If composer require refuses v4, composer why-not laravel-notification-channels/google-chat ^4.0 names the blocking package or the PHP constraint. Do not --ignore-platform-reqs — the PHP 8.1/8.2 drop is real and untested against those runtimes.cards payload shape. Newer widget types (grid, image cropping, decorators) won't be available, and Google has been steering apps toward cards v2. v4.0.0 did not change the payload shape, so this limitation carries over unchanged — check the emitted JSON before designing a rich card.text() call and keep content inside the card body.storage/ paths behind auth will render broken.curl -X POST -H 'Content-Type: application/json' -d @payload.json $WEBHOOK first; if that works, log the package's outgoing payload and diff. If the package uses Laravel's HTTP client, Http::fake() / Http::preventStrayRequests() work; if it ships its own Guzzle client, Http::fake() will not intercept and you'll need a snapshot test instead.via() and return [] when the URL is missing, so local/CI environments degrade quietly.composer.json, keep card construction behind your own helper, and be prepared to swap in a 30-line Http::post() channel if the package stalls. The core of what it does is one POST with a JSON body — and note that a maintenance-only release like v4.0.0 is itself a signal to keep that escape hatch warm rather than expand your dependency on the builder API.How can I help you explore Laravel packages today?