# Getting started

SplitHub is analytics and experiments in one install, for websites and apps whose code is written with a coding agent. An analytics property counts pageviews (or app screens) and the events you send with `track()`; experiments (A/B, multivariate, redirect) are declared in `splithub.config.ts` or the dashboard, rendered with React, Next.js or React Native (or decided by a drop-in script; iOS and Android have native SDKs), and read from the CLI, the MCP server, the dashboard or an email. Events go to your own database or to SplitHub Cloud.

## One command

In the folder of your app:

```bash
npx splithub
```

The interactive menu covers experiments, analytics, short links, alerts, notes and allowed domains. On a new app, "Set up this app" walks through: sign in through a link (no key to paste), create or pick a cloud project, write `splithub.config.ts` and the framework files, print the provider integration snippet, install the agent skills and the MCP server entry, create the first experiment, push it. Analytics → Set up connects an analytics property. Every step is also a subcommand with flags and `--json`, which is what an agent uses:

```bash
npx splithub init --mode cloud --yes      # or --mode self for your own database
npx splithub analytics connect            # pick or create a property, name it on your provider
npx splithub create --kind value --id hero-title --variants control,bold \
  --value "control=Old headline" --value "bold=New headline" --goal signup --yes
npx splithub push
npx splithub results hero-title
```

Prefer to let the agent do it? Open the project in Claude Code, Cursor or Codex and say: *"Set up SplitHub analytics and A/B test the headline on the home page."* After `init` the agent has the [skills](/docs/agent-skills) and the [MCP server](/docs/mcp) it needs.

## What `init` writes

| File | Purpose |
|---|---|
| `splithub.config.ts` | Goals, analytics properties and experiments. The source of truth. |
| Provider snippet in the command output | Add it to `app/layout.tsx` or `main.tsx` to wrap the app in the provider. |
| `middleware.ts` (Next.js) | Visitor cookie, redirect experiments, header for Server Components. |
| `app/api/splithub/[[...path]]/route.ts` (self mode) | Ingest and results handler with a store. |
| `splithub/store.ts` (self mode, `--db postgres` or `mysql`) | A working store for your database. |
| `.claude/skills/*`, `.cursor/rules/splithub.mdc`, `AGENTS.md` or `CLAUDE.md` section | Agent skills. |
| `.mcp.json`, `.cursor/mcp.json` | MCP server registration (skip with `--no-mcp`). |
| `app/_layout.tsx` or `App.tsx` (React Native, Expo) | Wrapped in `<SplitHubProvider>` with `<ExpoRouterScreens />` or `<NavigationScreens />`. |

## In a mobile app

`init` notices React Native and Expo projects, installs `@splithub/react-native` and wraps the app entry with screen tracking. In an Xcode or Gradle project it prints the Swift package or Gradle line and a quick start instead: native apps take their experiments from SplitHub Cloud, so there is no config file to write. Start with [Apps](/docs/apps), then [React Native and Expo](/docs/react-native), [iOS](/docs/ios) or [Android](/docs/android).

## Turn on analytics

```bash
npx splithub analytics connect
```

It picks the project's property (or creates one; ids look like `sh-x1h78w`) and adds `property="sh-…"` to the `<SplitHubProvider>` in your code. In cloud mode the property is live at once, no push needed. From then on the provider sends a pageview on load and on every client-side navigation, and every `track(name, props?)` call is recorded as an event. Any event name works; nothing to declare first. Without the SDK, the `sh.js` tag with `data-property="sh-…"` does the same. See [Analytics](/docs/analytics) and [Reports](/docs/analytics-reports).

## Render a variant

```tsx
import { useValue, useTrack } from '@splithub/react';

export function Hero() {
  const title = useValue<string>('hero-title');
  const track = useTrack();
  return <h1 onClick={() => track('signup')}>{title}</h1>;
}
```

The experiment's goal can be any event your app sends with `track()`: the same call feeds the analytics property and the experiments that measure it, one row per action.

`create` writes the experiment as `running`: it goes live for every visitor when you deploy the code that renders it. Check it locally first with `?sh_force=<id>:<variant>`; development never sends events to the cloud. To hold an experiment, create it with `--status draft` and start it later with `npx splithub start <id>`, or pause it in the dashboard.

A `value` experiment changes data (text, a URL, a number, JSON) without new components. A `component` experiment renders different JSX per variant with `<Experiment id="…"><Variant name="control">…</Variant></Experiment>`. A `redirect` experiment sends each variant to its own page. An `mvt` experiment changes several things at once and reads each one on its own. See [React](/docs/react), [Next.js](/docs/nextjs), [Redirect experiments](/docs/redirect-experiments) and [splithub.config.ts](/docs/config).

## Read the verdict

```bash
npx splithub status            # every experiment: status, visitors, days, verdict headline; in the cloud also each property's last 7 days
npx splithub results hero-title
```

In SplitHub Cloud the verdict is one of `no_data`, `insufficient_sample`, `srm_detected`, `winner_found`, `no_significant_difference`, `guardrail_breached`, with a message and the numbers behind it: visitors and conversions per variant, relative lift, an always-valid p-value and confidence interval, probability to beat, sample quality and a data-quality score of 0 to 5 stars. The test is safe to check any time. The [statistics page](/docs/statistics) explains each part. A self-hosted endpoint answers the raw numbers (visitors, conversions, rate, revenue per variant); verdicts come with SplitHub Cloud.

How many visitors will it take? `npx splithub plan --baseline 0.05 --mde 0.1` answers before you start, no account needed.

## Finish

```bash
npx splithub finish hero-title
npx splithub ship hero-title --keep bold --dry-run   # then without --dry-run
```

`ship` finishes the experiment, removes it from the config and rewrites the code to the kept variant; `--dry-run` shows the diff first. In cloud mode a finished experiment stops accepting events at the edge; nothing more is stored or billed.

## Next

- [How it works](/docs/concepts) explains properties, assignment, exposures, events and goals.
- [splithub.config.ts](/docs/config) lists every option.
- [Self-hosted](/docs/self-hosted) if the events must stay in your database.
- [SplitHub Cloud](/docs/cloud) for the dashboard, reports, live overrides, alerts and AI reviews.
