# SplitLaunch Agent Skills

SplitLaunch is a package-first A/B testing platform for customer-owned pages.
The user keeps their own website. SplitLaunch provides the package, browser
pixel, experiment API, data collection, conversion tracking, and reporting API.

This file is written for AI agents. Treat it as the operating manual for
installing SplitLaunch, creating projects, allowlisting domains, launching URL
A/B tests, firing custom conversion events, and retrieving results.

## Agent Operating Rules

1. Never put the private API key in browser code.
2. Browser code only receives the public pixel ID, for example `px_abc123`.
3. Use the API key only in terminal, server, CI, or agent-side calls.
4. For agency/client accounts, create or select the correct project before
   creating experiments. Each project has its own pixel ID.
5. Always allowlist the customer's domain before launching a redirecting test.
6. Prefer creating the experiment in `draft`, verifying URLs/domains/goals,
   then setting status to `running`.
7. Use `projectId` on commands when the account has multiple projects.
8. If a command changes project, domain, experiment, or goal configuration,
   explain the change to the user in plain language.

## Installation Flow

User-facing setup:

1. User signs in to SplitLaunch and activates a subscription.
2. User copies the account API key from the dashboard.
3. In the user's website or app repository, the user or coding agent runs:

```bash
npm install @splitlaunch/ab
npx splitlaunch init
```

4. The terminal asks for the API key.
5. The CLI validates the key and retrieves the public pixel ID.
6. The CLI writes local setup configuration and prints the pixel install snippet.
7. The agent can read this Skills file and use the API commands below.

Non-interactive setup for CI or agent automation:

```bash
SPLITLAUNCH_API_KEY=sl_live_... npx splitlaunch init
```

For a specific client/project after the account has multiple projects:

```bash
SPLITLAUNCH_API_KEY=sl_live_... npx splitlaunch init --project PROJECT_ID
```

Useful CLI commands:

```bash
npx splitlaunch projects list
npx splitlaunch docs
npx splitlaunch skills
npx splitlaunch pixel status
```

## Auth

Use the API key as a bearer token for server, terminal, or AI-agent calls:

```txt
Authorization: Bearer sl_live_...
```

Main command endpoint:

```txt
POST https://www.splitlaunch.dev/api/external/v1/commands
```

Request shape:

```json
{
  "command": "experiments.create",
  "input": {}
}
```

Response shape:

```json
{
  "command": "experiments.create",
  "data": {}
}
```

## Projects And Pixel IDs

One account can have multiple projects. This is important for agencies and
expert users managing multiple client websites. Each project has:

- its own `projectId`,
- its own public `pixelId`,
- its own allowed domains,
- its own experiments,
- its own conversion goals,
- its own usage records.

If an API key is account-level, it can manage multiple projects. If an API key
is project-scoped, it can only access that project and cannot create new
projects.

Create a client project:

```bash
curl -X POST "https://www.splitlaunch.dev/api/external/v1/commands" \
  -H "Authorization: Bearer sl_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "command": "projects.create",
    "input": {
      "name": "Acme Client",
      "allowedDomains": ["acme.com", "www.acme.com"],
      "reportingTimezone": "America/New_York"
    }
  }'
```

List available projects:

```json
{
  "command": "projects.list",
  "input": {
    "perPage": 25
  }
}
```

Retrieve one project and its pixel ID:

```json
{
  "command": "projects.get",
  "input": {
    "projectId": "PROJECT_ID"
  }
}
```

Agent guidance: when the user says "create a test for Client A", first map
Client A to the right `projectId`. If no project exists, create one and use
the returned `pixelId` for installation.

## Domain Allowlisting

SplitLaunch should only run pixels and redirects on domains the user controls.
Before launching an experiment, add the control and variation hostnames.

Add a domain:

```json
{
  "command": "domains.add",
  "input": {
    "projectId": "PROJECT_ID",
    "hostname": "example.com"
  }
}
```

List allowed domains:

```json
{
  "command": "domains.list",
  "input": {
    "projectId": "PROJECT_ID"
  }
}
```

Hostname rules:

- Use hostnames, not full page URLs: `example.com`, not
  `https://example.com/pricing`.
- Add both apex and subdomain if both are used: `example.com` and
  `www.example.com`.
- Add every hostname used by the control URL and variation URL.
- If the customer tests across subdomains, allowlist each participating
  hostname.

## Pixel Installation

The pixel is loaded with a public pixel ID. Example:

```html
<script async src="https://www.splitlaunch.dev/pixel/px_your_pixel_id.js"></script>
```

The pixel collects page/session/event/exposure metadata including:

- page URL and path,
- referrer URL and referrer host,
- visitor ID and session ID,
- visitor type,
- device type,
- browser language,
- timezone,
- viewport bucket,
- UTMs,
- ad click IDs such as gclid, fbclid, msclkid, ttclid, li_fat_id,
- query snapshot,
- country and region when available,
- in-app browser detection,
- experiment ID,
- assigned variant,
- custom event data after sanitisation.

## Creating An A/B Test

Minimum experiment creation:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "Homepage headline test",
    "controlUrl": "https://example.com/",
    "variationUrl": "https://example.com/homepage-v2",
    "trafficAllocation": 50
  }
}
```

`trafficAllocation` means the percentage of eligible visitors assigned to the
variation URL. Agents may send `50` or `0.5`; both represent 50%.

Recommended agent checklist before creating:

1. Confirm the project.
2. Confirm the control URL.
3. Confirm the variation URL.
4. Add/verify allowed domains.
5. Decide traffic allocation.
6. Decide targeting filters.
7. Decide conversion goal event names.
8. Create the experiment.
9. Keep it in draft until the user approves launch.
10. Set status to running.

## Targeting Examples

Desktop-only experiment:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "Desktop pricing layout",
    "controlUrl": "https://example.com/pricing",
    "variationUrl": "https://example.com/pricing-v2",
    "trafficAllocation": 25,
    "targeting": {
      "deviceType": "desktop-only"
    }
  }
}
```

New visitors only:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "New visitor offer",
    "controlUrl": "https://example.com/",
    "variationUrl": "https://example.com/new-offer",
    "trafficAllocation": 50,
    "targeting": {
      "visitorType": "new-visitors"
    }
  }
}
```

UTM/source-specific traffic:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "Paid search landing test",
    "controlUrl": "https://example.com/landing",
    "variationUrl": "https://example.com/landing-v2",
    "trafficAllocation": 50,
    "targeting": {
      "trafficFilters": {
        "utm_source": "google",
        "utm_medium": "cpc"
      }
    }
  }
}
```

Country targeting:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "US/AU offer test",
    "controlUrl": "https://example.com/",
    "variationUrl": "https://example.com/us-au-offer",
    "trafficAllocation": 50,
    "targeting": {
      "geoFilters": {
        "countries": {
          "type": "include",
          "countryCodes": ["US", "AU"],
          "includeUnknown": false
        }
      }
    }
  }
}
```

URL pattern rules for matching multiple pages:

```json
{
  "command": "experiments.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "All product pages CTA",
    "controlUrl": "https://example.com/products/widget",
    "variationUrl": "https://example.com/products/widget-v2",
    "trafficAllocation": 50,
    "urlPatternRules": [
      {
        "conditions": [
          {
            "operator": "starts_with",
            "value": "/products/"
          }
        ]
      }
    ]
  }
}
```

Supported URL pattern operators:

- `is`
- `contains`
- `starts_with`
- `ends_with`

## Launching, Pausing, Ending

Create experiments as draft, then launch:

```json
{
  "command": "experiments.set_status",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "status": "running"
  }
}
```

Pause:

```json
{
  "command": "experiments.set_status",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "status": "paused"
  }
}
```

End:

```json
{
  "command": "experiments.set_status",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "status": "ended"
  }
}
```

## Conversion Goals And Custom Events

Create a goal:

```json
{
  "command": "goals.create",
  "input": {
    "projectId": "PROJECT_ID",
    "name": "Lead",
    "eventName": "Lead",
    "value": 100
  }
}
```

Fire the conversion in browser code after the desired user action:

```js
window.splitlaunch("track", "Lead", {
  value: 100,
  form: "Demo request",
  plan: "Pro"
});
```

Common event names:

- `Lead`
- `Signup`
- `TrialStarted`
- `Purchase`
- `DemoBooked`
- `Subscribe`
- `ContactFormSubmitted`

Agent guidance: if the user asks to track a form, add the event after a
successful submit, not on initial click. If the user asks to track purchases,
fire the event only after confirmed checkout/payment success.

## Reporting

List experiments:

```json
{
  "command": "experiments.list",
  "input": {
    "projectId": "PROJECT_ID",
    "status": "running",
    "perPage": 20
  }
}
```

Get experiment details:

```json
{
  "command": "reports.experiment.details",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "goal": "Lead",
    "from": "2026-07-01",
    "to": "2026-07-14"
  }
}
```

Get chart/time-series data:

```json
{
  "command": "reports.experiment.chart",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "interval": "day",
    "goal": "Lead"
  }
}
```

Get channel/acquisition breakdown:

```json
{
  "command": "reports.experiment.channels",
  "input": {
    "projectId": "PROJECT_ID",
    "experimentId": "EXPERIMENT_ID",
    "goal": "Lead"
  }
}
```

When explaining results, agents should mention:

- sample size,
- exposure count,
- conversion count,
- conversion rate by variant,
- absolute difference,
- relative lift,
- whether the result looks directional or needs more data,
- any obvious channel/device skew.

## Usage And Billing

Usage summary:

```json
{
  "command": "usage.summary",
  "input": {
    "projectId": "PROJECT_ID",
    "from": "2026-07-01",
    "to": "2026-07-31"
  }
}
```

Billing portal:

```json
{
  "command": "billing.portal",
  "input": {
    "returnUrl": "https://www.splitlaunch.dev/dashboard"
  }
}
```

## Commands

### projects.create

- Category: Project
- Mode: write
- Input: name, allowedDomains?, reportingTimezone?
- Use: Create a new client/project workspace and allocate a unique public pixel ID.

### projects.list

- Category: Project
- Mode: read-only
- Input: page?, perPage?
- Use: List projects available to the API key's account, including each public pixel ID.

### projects.get

- Category: Project
- Mode: read-only
- Input: projectId?
- Use: Return the current project, public pixel ID, allowed domains, and plan limits.

### projects.update

- Category: Project
- Mode: write
- Input: projectId?, name?, allowedDomains?
- Use: Update project name, allowed domains, or default reporting settings.

### experiments.create

- Category: Experiments
- Mode: write
- Input: projectId?, name, controlUrl, variationUrl, trafficAllocation, targeting?, urlPatternRules?, preserveRedirectParams?
- Use: Create an external URL A/B test with control URL, variation URL, traffic split, and targeting filters.

### experiments.update

- Category: Experiments
- Mode: write
- Input: projectId?, experimentId, name?, controlUrl?, variationUrl?, trafficAllocation?, targeting?, urlPatternRules?, preserveRedirectParams?
- Use: Change an experiment's URLs, allocation, filters, URL pattern rules, or selected conversion goals.

### experiments.set_status

- Category: Experiments
- Mode: write
- Input: projectId?, experimentId, status
- Use: Move an experiment through draft, running, paused, and ended states.

### experiments.list

- Category: Experiments
- Mode: read-only
- Input: projectId?, status?, page?, perPage?
- Use: List experiments for the project with status and URL filters.

### reports.experiment.details

- Category: Reports
- Mode: read-only
- Input: projectId?, experimentId, from?, to?, goal?
- Use: Return experiment totals, variants, visitors, exposures, conversions, rates, lift, and selected goal data.

### reports.experiment.chart

- Category: Reports
- Mode: read-only
- Input: projectId?, experimentId, from?, to?, interval?, goal?
- Use: Return time-series experiment performance for agent analysis.

### reports.experiment.channels

- Category: Reports
- Mode: read-only
- Input: projectId?, experimentId, from?, to?, goal?
- Use: Return acquisition channel and metadata performance using the pixel's collected UTMs, click IDs, referrers, and browser context.

### goals.create

- Category: Goals
- Mode: write
- Input: projectId?, name, eventName, value?
- Use: Create a conversion goal that can be fired by the browser pixel or documented for an AI agent.

### goals.list

- Category: Goals
- Mode: read-only
- Input: projectId?, active?
- Use: List conversion goals available for experiments and reporting.

### domains.list

- Category: Domains
- Mode: read-only
- Input: projectId?
- Use: List allowed customer-owned domains for pixel and redirect safety.

### domains.add

- Category: Domains
- Mode: write
- Input: projectId?, hostname
- Use: Add a customer-owned domain that may load the pixel or participate in redirects.

### usage.summary

- Category: Usage
- Mode: read-only
- Input: projectId?, from?, to?
- Use: Return billing usage such as events, sessions, exposures, active experiments, and plan limits.

### billing.portal

- Category: Billing
- Mode: write
- Input: returnUrl?
- Use: Create or return a billing portal link for subscription management.
