Skip to content

Tracking And Consent

Insights records first-party activity through two public endpoints and a frontend render hook. The package should stay invisible to admin pages, Livewire traffic, debug tooling, and any path listed in capell-insights.ignored_paths.

  1. RegisterInsightsTrackerHook injects the tracker when capell-insights.enabled is true and the frontend render hook registry is bound.
  2. The browser posts event batches to POST /capell/insights/events by default.
  3. Consent changes post to POST /capell/insights/consent.
  4. Controllers turn request payloads into InsightsBeaconData, InsightsConsentData, and InsightsEventData.
  5. Actions write InsightsVisit, InsightsConsent, and InsightsEvent rows.

The route prefix comes from capell-insights.route_prefix. Both endpoints use the web middleware group, skip CSRF, and apply throttle:60,1.

KeyUse
capell-insights.enabledTurns tracker registration on or off.
capell-insights.route_prefixPrefix for beacon and consent routes.
capell-insights.track_page_viewsRecords page-view events when enabled.
capell-insights.track_clicksRecords click events when enabled.
capell-insights.automatic_click_trackingLets the frontend tracker capture clicks automatically.
capell-insights.require_consent_for_all_regionsBlocks tracking until consent exists, regardless of detected region.
capell-insights.default_consent_regionFallback consent region when the request cannot resolve one.
capell-insights.policy_versionStored with consent records so policy updates can be audited.
capell-insights.retention_daysDefault cleanup window for insights:purge.
capell-insights.hash_visitor_dataHashes visitor identifiers before storage.
capell-insights.hash_saltSalt used for hashing. Set this before production traffic.
capell-insights.ignored_pathsPaths that should never be tracked.
capell-insights.ignored_selectorsClick targets the frontend tracker should skip.
capell-insights.tables.*Table-name overrides, also used when registering protected tables.

Use RecordCustomActionAction for server-side events that are not browser clicks or page views.

use Capell\Insights\Actions\RecordCustomActionAction;
use Capell\Insights\Data\InsightsEventData;
use Capell\Insights\Enums\InsightsEventType;
RecordCustomActionAction::run(
visitUuid: 'visit_01HXZ8QY9J2N3R4S5T6V7W8X9Y',
data: new InsightsEventData(
type: InsightsEventType::Custom,
url: 'https://example.test/newsletter',
eventName: 'newsletter_signup',
label: 'Footer signup',
),
);

Keep custom event names stable. Store identifiers and dimensions, not full request bodies.

Consent writes should go through UpdateInsightsConsentAction so the stored region, category, status, and policy version stay consistent.

use Capell\Insights\Actions\UpdateInsightsConsentAction;
use Capell\Insights\Data\InsightsConsentData;
use Capell\Insights\Enums\InsightsConsentRegion;
use Capell\Insights\Enums\InsightsConsentStatus;
use Illuminate\Http\Request;
final class ConsentController
{
public function __invoke(Request $request)
{
return UpdateInsightsConsentAction::run(
request: $request,
data: new InsightsConsentData(
insights: true,
marketing: false,
preferences: true,
),
status: InsightsConsentStatus::Granular,
region: InsightsConsentRegion::UkOrEurope,
);
}
}

If the constructor shape changes, update this doc with the action in the same change.

Use the package command for cleanup in the host app. In this repository, test the behavior directly:

Terminal window
vendor/bin/pest packages/insights/tests --configuration=phpunit.xml

The runtime command is insights:purge {--days=} in the host application. This repository does not run php artisan.

  • Keep admin, Livewire, debug, storage, and beacon paths in ignored_paths.
  • Set hash_salt before recording production data. Changing it later breaks visitor continuity.
  • Treat raw IP addresses and user agents as sensitive. Prefer hashed fields unless a product requirement says otherwise.