phattarachai/watchtower-laravel
Watchtower is a lightweight monitoring companion for Laravel applications, giving you a simple way to keep an eye on your app's health and catch problems early. Quick to install, easy to configure, and built to fit naturally into any Laravel project.
Watchtower is a self-hosted error/event monitor for Laravel: it captures server-side exceptions and browser-side events (JS errors, chunk-load failures) and groups them into issues.
composer require phattarachai/watchtower-laravel — v1.6.0 requires phattarachai/watchtower-core ^1.3, so let Composer resolve the pair together.php artisan vendor:publish --tag=watchtower (config)php artisan vendor:publish --tag=watchtower-js --force (browser helper + resources/js/vendor/noise.js)WATCHTOWER_DROP_BOT_EVENTS (default true); leave it on unless you have a reason not to.resources/js/app.js) and build.import() in your frontend and confirm you get one chunk-load-error issue rather than one issue per chunk hash.Where to look first: the published config file (ingest mode, sampling, bot filtering), then resources/js/vendor/noise.js — in 1.6.0 that file is where all the crawler- and chunk-error-deduplication rules live, and it is the intended place to customise.
Server-side capture. Wire Watchtower into bootstrap/app.php / the exception handler's report() path (or via the package's reportable) so unhandled exceptions are captured automatically. Anything you report() manually is also captured — use that for caught exceptions in jobs and queued listeners, which otherwise silently disappear.
Browser capture via the published helper. Import the helper after your framework bootstraps but before app code runs, so early errors are not missed. Because the helper now fingerprints chunk-load failures as ['chunk-load-error'], all four variants (Chrome, Safari, Firefox, Vite CSS preload) collapse into a single issue — your triage workflow becomes "one chunk-load issue, investigate the latest deploy" instead of scrolling a wall of hashed module names.
// resources/js/app.js
import './vendor/watchtower' // published helper — includes noise.js rules
import './vendor/noise' // if you split them; keep your own edits in a separate file
Standalone vs dual ingest. Standalone sends browser events straight to the Watchtower endpoint; dual ingest proxies them through your Laravel app. Dual ingest survives ad-blockers and gives you a single place to enforce WATCHTOWER_DROP_BOT_EVENTS, at the cost of extra request volume on your app. Standalone is cheaper but must also drop bots (it does, same flag). Pick one per environment — mixing them on the same project produces duplicate issues.
Deployment workflow. Treat the published helper like a dependency, not a scaffold: pin it in VCS, and on every package upgrade run vendor:publish --tag=watchtower-js --force, then git diff that file. Ship the diff through your normal asset pipeline so the cache-busted bundle actually reaches clients.
Custom fingerprinting. Follow the pattern the package now uses for chunk errors — pass a stable fingerprint array for any error class you know is recurrent but low-signal (a third-party widget, a known Safari quirk on one page). Grouping at ingest is far cheaper than resolving duplicates by hand later.
CI and smoke tests. HeadlessChrome browser tests still report by design. That's useful for asserting errors during E2E runs, but noisy in load/perf pipelines — gate the helper behind an env flag in those builds rather than turning off bot filtering globally.
--force overwrites your edits. If you customised the old helper, the upgrade publish quietly destroys it. Keep local UA patterns and fingerprints in your own module that imports/extends the vendor file, or you will re-lose them next release.Failed to fetch dynamically imported module per-hash issue is still open and no longer accumulating events. Bulk-resolve them post-deploy or your issue list stays permanently noisy.WATCHTOWER_DROP_BOT_EVENTS. If crawler traffic inflates your numbers, that's SSR/prerender requests hitting Laravel — filter them in the app, not in the helper.noise.js for the ones you see in your data rather than guessing.noise.js is tree-shaken, imported behind a conditional, or loaded before the helper initialises, filtering silently doesn't apply and you'll think the release is broken. Verify in the network tab that the outgoing payload for a simulated bot UA is absent — don't infer it from the config alone.^1.3 requirement fails hard against a project pinned to watchtower-core ^1.2; bump core in the same commit so you don't get a half-upgraded vendor tree.noise.js rules ran, (c) the fingerprint array is present on chunk errors. Those three checks isolate almost every misconfiguration.noise.js is the sanctioned surface for filtering and grouping logic — keep changes there small and commented, since you'll be re-diffing it on each upgrade.How can I help you explore Laravel packages today?