Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Watchtower Laravel Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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.

  1. composer require phattarachai/watchtower-laravel — v1.6.0 requires phattarachai/watchtower-core ^1.3, so let Composer resolve the pair together.
  2. Publish the config and the JS helper:
    • php artisan vendor:publish --tag=watchtower (config)
    • php artisan vendor:publish --tag=watchtower-js --force (browser helper + resources/js/vendor/noise.js)
  3. Set the env keys you actually need. The one that matters in v1.6.0 is WATCHTOWER_DROP_BOT_EVENTS (default true); leave it on unless you have a reason not to.
  4. Import the published helper once in your entrypoint (resources/js/app.js) and build.
  5. First use case: throw a deliberate exception in a route and confirm it lands as a server-side event; then break a dynamic 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.

Implementation Patterns

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.

Gotchas and Tips

  • --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.
  • Old issues don't close themselves. After upgrading, every previously reported 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.
  • Bot filtering is browser-side only. Server-side events still report regardless of 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.
  • Not all bots are filtered. The UA list covers Googlebot, GoogleOther, bingbot, AdsBot and similar; uptime monitors, link previewers, and generic HTTP clients will still send events. Add patterns in noise.js for the ones you see in your data rather than guessing.
  • HeadlessChrome intentionally bypasses the filter. Puppeteer/Playwright smoke tests and Lighthouse runs in production will generate real issues. Either disable the helper for those user agents or tag the environment.
  • Bundler traps. If 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.
  • Asset cache is the usual "it didn't work" cause. A stale CDN/edge copy of the old helper keeps sending unfiltered events for hours after deploy. Purge or bump the asset hash, then confirm the new file is what the browser actually executed.
  • Composer conflicts on core. The ^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.
  • Debugging tip. Reproduce with the payload open in devtools: confirm (a) the helper loaded, (b) noise.js rules ran, (c) the fingerprint array is present on chunk errors. Those three checks isolate almost every misconfiguration.
  • Extension point. 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.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource