Error tracking

Capture unhandled JS errors with the browser SDK, or install the PHP or Laravel SDK for automatic backend exception capture.

Error tracking surfaces application errors — grouped by fingerprint, not a raw log dump — right on the site dashboard, and can trigger error rate alert rules.

Browser errors (JS SDK)

Add one script tag to your site, using the site's public key from its settings page:

<script src="https://downctl.com/sdk/downctl.js" data-key="YOUR_PUBLIC_KEY" defer></script>

That's it — it auto-initializes and starts capturing:

  • Unhandled JS errors (window.onerror)
  • Unhandled promise rejections

Errors are queued and flushed in the background, so page performance isn't affected.

Manual capture

The SDK exposes window.downctl for capturing errors and log messages yourself:

downctl.capture(new Error('something broke'), { userId: 42 });
downctl.log('warning', 'Low disk space', { disk: '95%' });

log() accepts error, warning, or info as the level. Context values are converted to strings automatically.

Backend errors (Laravel)

Install bluecapapps/downctl-laravel:

composer require bluecapapps/downctl-laravel

Add your site's secret key to .env:

DOWNCTL_API_KEY=your-secret-api-key

That's it — the package listens for Laravel's MessageLogged event and forwards anything at or above error level automatically, no exception handler changes required. Verify it's wired up with:

php artisan downctl:test

Capture manually with the facade when you want more control:

use Bluecapapps\DownctlLaravel\Facades\Downctl;

Downctl::captureException($e, context: ['order_id' => $order->id]);
Downctl::report('Stripe webhook signature invalid', level: 'error');

Other things worth knowing:

  • DOWNCTL_CAPTURE_LEVEL controls the minimum level auto-captured (error by default); set it blank to disable automatic capture and only report manually.
  • DOWNCTL_QUEUE=true sends reports through your queue instead of a synchronous HTTP call, with 3 retries and a 30s backoff.
  • Context is redacted by default — high-confidence secret keys (password, api_key, authorization, etc.) are stripped before anything is sent, at any nesting level.
  • The package also provides a ->cronMonitor() schedule macro — see API, port, ping, and cron monitors.

Visit the downctl-laravel GitHub repo for the full README, source, and issue tracker.

Backend errors (plain PHP)

Not on Laravel? Use bluecapapps/downctl-php directly — zero dependencies beyond the curl extension:

composer require bluecapapps/downctl-php
use Bluecapapps\Downctl\Client;
use Bluecapapps\Downctl\Config;

$client = new Client(Config::fromEnv()); // reads DOWNCTL_API_KEY from the environment

try {
    riskyOperation();
} catch (\Throwable $e) {
    $client->captureException($e, context: ['user_id' => $userId]);
}

By default the client is silent — network failures or a bad API key are swallowed so the SDK can never crash your app. Set silent: false locally to catch misconfiguration early.

Visit the downctl-php GitHub repo for the full README, source, and issue tracker.

Backend errors (raw API)

No PHP? Report directly to the API from any language using the site's secret key:

curl -X POST https://downctl.com/api/v1/errors \
  -H "X-Downctl-Key: YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "level": "error",
    "message": "RuntimeException: DB connection failed",
    "stack_trace": "#0 app/Services/Db.php(42): ...",
    "context": {"user_id": "123"}
  }'

See the API reference for the full payload shape.

Grouping

Errors are grouped on a fingerprint derived from the message and the first stack trace line — repeated occurrences of the same error increment a counter on the dashboard instead of creating duplicate entries.

Next steps

Ready to be first
to know?

Add your first site in 30 seconds. Start your free trial today.

14-day free trial · No credit card required · Cancel anytime