← Guides

Connecting your project to dif cloud

Your experiments already live in the repo. Dif Cloud sits on top of that repo and gives the whole team a live read: it mirrors the spec, ingests the events your app fires, and computes the lift and significance behind every running test. Git stays the source of truth. When Cloud has a change to make, it arrives as a pull request.

Connect a repo and you get a live pulse of every experiment, one metrics catalog the whole team shares, and concluded decisions drafted straight into the file as a PR.

Before you start

This guide picks up where your first experiment leaves off. It assumes a dif/ workspace in a GitHub repo: experiments authored, dif build run, and the whole thing pushed to your default branch. If dif/experiments/active/ holds at least one file, you are ready.

Two connections to make

Connecting has two halves, and they feed different parts of Cloud.

  • The repo. Installing the GitHub App lets Cloud read your dif/ folder: experiments, surfaces, config. This drives the pulse, the surfaces view, the decision history, and the pull requests.
  • The SDK. A publishable key lets your app send exposure and metric events. This is what fills in the numbers: exposure counts, lift, and the metrics catalog.

Do the repo half first and your experiments show up with no data yet. Wire the SDK and they come to life.

1. Sign in

Open cloud.dif.sh and sign in with a magic link or your GitHub account. A Cloud project maps to one repo, so connecting GitHub is the next move.

2. Connect the repo

In your project, go to Settings, then Integrations, then GitHub, and click Connect. GitHub sends you off to install the dif Cloud app and choose which repository it can see. Pick the one with your dif/ folder.

Cloud links the repo and runs a first sync right away. It reads the tree on your default branch and mirrors:

  • dif/experiments/active/ and dif/experiments/concluded/
  • dif/surfaces/
  • dif/config.yaml

The sync is keyed on file content, so unchanged files are skipped, a file you delete in the repo drops out of Cloud, and the activity feed logs each run (Repo synced, 6 experiments, 4 surfaces). After this, every push to your default branch re-syncs within seconds over a webhook. There is also a Sync project button on the Pulse page for when you want to pull right now.

roles
Connecting, disconnecting, and changing the repo are owner and admin actions. Any editor can run Sync project; viewers cannot.

3. Send events from the SDK

The repo gives Cloud the spec. The SDK gives it the data, in two steps.

First, create a key. In Settings, open Keys and mint a publishable one. Choose live or test, add your app's origins (leave it empty only in development), and copy the key when it appears. Cloud stores a hash, not the key itself, so you see the plaintext once. It reads dif_pk_live_….

Make sure the SDK is installed:

$ npm install @dif.sh/sdk

Then point the SDK at Cloud. The only new lines in your existing dif.init are publishableKey and apiUrl:

// register the generated client once, at boot
import "./dif/generated/client";
import { attributes } from "./dif/generated/audiences";
import { dif } from "@dif.sh/sdk";

dif.init({
  project: "acme-shop",
  publishableKey: "dif_pk_live_…",
  apiUrl: "https://cloud.dif.sh",
  userId: () => currentUser?.id ?? null,
  attributes: () => attributes(),
});

With a publishableKey set, the SDK attaches a Cloud sink for you. Every exposure from a dif(...) call site, and every dif.track(...), posts to cloud.dif.sh. Track your primary metric wherever the conversion happens:

// fire your primary metric where the conversion happens
dif.track("completed_checkout", { value: 49, currency: "USD" });
self-host
Running your own instance from dif-sh/dif-cloud? Set apiUrl to your URL. The SDK posts to /v1/exposure and /v1/track, and Cloud maps those to its API routes, so http://localhost:3000 works in development.

What connecting gives you

A live pulse

Your project home is the Pulse. Connect the repo and your active experiments appear at once, mirrored from the files. Wire the SDK and the numbers fill in: events over the last 24 hours, a 14-day exposure sparkline per experiment, lift with a 95% confidence interval, a sample-ratio check against your declared weights, and a flag when a result is ready to conclude. Analysis reruns every five minutes, so the read is never more than a few minutes old.

A shared metrics catalog

Open Metrics and you find every metric your app fires. You never register one by hand: the first time Cloud sees a metric on a track call, it adds the metric as new, and a teammate promotes it to active. Each row shows the kind (conversion, revenue, duration, count), the surface it belongs to, how often it fires, which experiments depend on it, and whether it is a guardrail. Cloud watches guardrail metrics for drift, so a checkout win that quietly raises refunds gets caught before it ships.

Decisions that come back as pull requests

This is the part that keeps git in charge. When a variant clears the bar, Cloud writes the verdict into the experiment's ## Decision block and opens a pull request:

Ship Variant A. It beat control by +2.1% on completed_checkout at 95% confidence across 184,312 exposures. No guardrails tripped.

Cloud also drafts the next experiment from your surface logs and concluded history, with a hypothesis, a primary metric, an audience, and the reasoning behind it, again as a PR. You review the diff and merge, or you close it and keep running. Nothing edits your experiments behind your back. Cloud proposes; you merge.

That is the loop: experiments in the repo, a live read in Cloud, decisions back as PRs. For event shapes, sinks, and server-side tracking, see the SDK reference. For limits and pricing, see Cloud pricing.