Overview
What it does
Section titled “What it does”Experiments allocates consented visitors between weighted variants, records goal events, and compares each variant with a control. It can target a page, campaign, or generic subject and can vary public text slots without putting admin metadata into cached page HTML.
Setup requirements
Section titled “Setup requirements”Run the package migrations and keep Laravel’s scheduler running. capell:experiments:sync-statuses runs every five minutes, without overlapping and on one server: scheduled experiments start when their start time arrives, and scheduled or active experiments end at their end time. Draft and paused experiments are not activated automatically. capell:experiments:prune runs daily for retained history.
The public runtime also needs an active Capell site domain, or a host-to-site mapping under capell-experiments.runtime.sites. Allocation happens only after analytics consent. Confirm that the application’s consent layer writes the configured consent cookie (default capell_consent_analytics=granted) before relying on public results.
Build an experiment
Section titled “Build an experiment”Go to Experiments in the admin and create the parent experiment first. Choose its site, page/campaign/generic subject, traffic percentage, allocation strategy, and optional start/end dates. A site-specific experiment and all of its child records are restricted to users assigned to that site.
Then configure:
- Variants with stable keys, positive weights, active state, one control variant, and a payload. The browser runtime only applies string values under
payload.slotsto matchingdata-experiment-slotelements as text; other payload structures require a companion integration. - Goals with stable keys, page-view, click, form-submission, or custom-event type, optional value, and active/primary state. A goal must be emitted by the public runtime or an integration; creating the record alone does not detect that behaviour.
- Audience rules for attribute, path, query, referrer, UTM, or segment context. Every required rule must match. When optional rules exist, at least one optional rule must match as well.
Sticky weighted allocation reuses the visitor’s variant for that experiment. Weighted creates a fresh weighted allocation instead. Traffic percentage controls eligibility before variant weights are applied; variant weights are relative values and do not need to total 100. Inactive or zero-weight variants receive no new allocations.
Runtime privacy and failure boundaries
Section titled “Runtime privacy and failure boundaries”The allocation route is signed, rate-limited to 60 requests per minute, origin-checked, site-bound, and returned with private, no-store. It does nothing without consent and honours Global Privacy Control and Do Not Track. A successful public allocation sets an HTTP-only, same-site Lax visitor cookie for one year; the database stores the allocation key and hash, selected variant, source/context, and allocation time.
Goal submission uses an encrypted allocation/site token that expires after one day. Forged, expired, cross-site, or unknown goal tokens are rejected, and a keyed public goal is recorded once per allocation and goal. When an allocation came from Insights and still has an Insights visit identity, the conversion is also sent to Insights.
If no experiment is active, the audience misses, consent is absent, the site cannot be resolved, or every variant is inactive/zero-weight, the visitor receives no variant. Check dates, status, domain mapping, consent, audience inputs, traffic percentage, and weights before treating a lack of allocations as a runtime fault.
Read and act on results
Section titled “Read and act on results”Open Results from an experiment. The default report uses the primary active goal (or first active goal), requires at least 100 allocations for the control and candidate, and tests at 95% confidence. Repeat goal events do not inflate the unique conversion count. A raw conversion-rate leader is not labelled a winner until it beats the control and passes both gates.
The current Results page reports evidence but does not publish variant content or declare a winner. Rollout is a separate change in the owning page, campaign, or integration. The package action available to integrations refuses to declare a winner without statistical significance and, when used with its default behaviour, stores the report and ends the experiment.
Permissions, data, and retention
Section titled “Permissions, data, and retention”Experiments, variants, goals, and audience rules each use their own view, create, update, and delete permissions. Lists and record policies enforce the parent experiment’s site for child records; global experiments are available across sites, while global administrators bypass site assignment.
Allocation context can include URL/path, referrer, query and UTM data, attributes, segments, and an external identifier. Allocation and goal-event fields are not encrypted. Avoid personal data in audience values, variant payloads, URLs, keys, or metadata, and include experiment tables and backups in the analytics privacy policy.
The default retention window is 180 days. The daily prune deletes old allocations and goal events only when their experiment has status Ended; active, paused, scheduled, and draft history is retained even when old. Experiment definitions, variants, goals, audience rules, and stored winner reports are not removed by this task.
For how to use Experiments, see the admin guide. For developers: see the README.