Gate snowplow tracker entry on frontend tracking being configured

WHAT

Gate the snowplow tracker entry in app/views/layouts/_snowplow.html.haml on whether the frontend can send any event at all.

Gitlab::Tracking.frontend_client_options.present? doesn't work as a gate: when Snowplow is disabled it falls back to product_usage_events_options, so it's never blank.

Instead, add a class method on Gitlab::Tracking::EventEligibilityChecker, next to only_send_duo_events?, mirroring how eligible? is split:

  • CE: !only_send_duo_events?
  • EE override: super || internal_duo_events.any?

Then = webpack_bundle_tag 'tracker' if <predicate>.

Removing the bundle is safe: Tracker.enabled() checks typeof window.snowplow === 'function', which is only defined in entrypoints/tracker.js, so every tracking call no-ops.

WHY

The tracker chunk (~68 KB minified / ~23 KB gzipped) ships on every page even when EventForwardController would drop every event the browser sends.

In practice, the gate is only false on CE/FOSS instances with both Snowplow and product usage data disabled. EE always has duo events defined, so it keeps loading the bundle. It's a small, niche win, so keep the change to the predicate plus a one-line gate.

Possible follow-up, out of scope here: EE instances with self-hosted models (Ai::Setting.self_hosted?) drop duo events on the backend too, but that check is a DB query on every page render.

SUCCESS METRIC (action-based)

On a CE instance with Snowplow and product usage data disabled, the tracker chunk isn't loaded. Specs cover the predicate (CE and EE) and both branches of _snowplow.html.haml.

Edited by 🤖 GitLab Bot 🤖