Install guides / Laravel

Bug reports from your Laravel app

The widget goes in your main Blade layout, once, before </body>. That covers Blade and Livewire apps, and Inertia apps through their root template.

The tag, in your layout

Usually resources/views/layouts/app.blade.php; for Inertia, the root template resources/views/app.blade.php.

resources/views/layouts/app.blade.php
<body>
    {{ $slot }}

    <script
      src="https://app.brainbox.sh/widget.js"
      data-project="pk_your_project_key"
      data-endpoint="https://app.brainbox.sh/ingest"
    ></script>
</body>

Who is signed in

After the tag, pass the user with Js::from, which encodes it safely for a script:

resources/views/layouts/app.blade.php
@auth
    <script>
        window.Brainbox.identify({{ Js::from([
            'id' => (string) auth()->id(),
            'email' => auth()->user()->email,
            'name' => auth()->user()->name,
        ]) }});
    </script>
@endauth

Livewire and wire:navigate

wire:navigate swaps in the next page's <body> and runs its scripts again. The widget moves itself into each new body, and a second run of the tag does nothing, so there is one widget, with anything the user had open still open. The identify script runs again too, which keeps the user current.

Inertia

Inertia only re-renders its own root element, so the tag stays put. The Blade identify above runs on the first full load; to follow sign-ins that happen without one, identify from your shared props when the page changes:

resources/js/app.ts
import { router } from "@inertiajs/vue3" // or @inertiajs/react

router.on("navigate", (event) => {
  const user = event.detail.page.props.auth?.user
  if (user) window.Brainbox?.identify({ id: String(user.id), email: user.email, name: user.name })
})

Your own button

Any element marked data-brainbox opens the widget, in any Blade view or component. screenshot goes straight to marking up the page, record to a recording of the page and feature to a feature request; an empty value opens the chooser. Clicks are delegated, so elements rendered later work too.

<button data-brainbox="screenshot">Report a bug</button>
<button data-brainbox="feature">Request a feature</button>

From code, window.Brainbox.open() shows the chooser and window.Brainbox.start("feature") goes straight to one flow. To hide our floating button and keep only yours, add data-mode="mount" to the tag.

Passwords and personal data

Typed values are always masked in recordings, so passwords, emails and card numbers never leave the browser as plain text. Add the rr-block or rr-mask class to anything else you want kept out.

Try it before you install it

The button in the corner of this page is the real widget. Report something on this page and it lands in our inbox, the way your users’ reports will land in yours.

Get started