> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trygravity.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Going live

> The checklist to run before flipping to production.

## Flip the switch

<CodeGroup>
  ```ts Node / JS / TS theme={null}
  const gravity = new Gravity({ production: true });
  ```

  ```python Python theme={null}
  gravity = Gravity(production=True)
  ```
</CodeGroup>

That's the only code change. Once `production: true` is set, the engine returns real ads matched to real campaigns, impressions and clicks count toward your revenue, and everything flows through to your dashboard.

## Pre-flight checklist

Before flipping, verify each of these end-to-end in test mode:

<Steps>
  <Step title="API key in your server env">
    `GRAVITY_API_KEY` set on your production host. The SDK picks it up automatically. `new Gravity({ apiKey: '...' })` also works if you manage secrets differently.
  </Step>

  <Step title="Ads render in every placement">
    For each `placement_id` you request, confirm the ad shows up in the right spot in the UI. Test modes return a placeholder ad so you should always see *something*.
  </Step>

  <Step title="Impressions fire on visibility">
    Scroll the ad into view. Network tab should show a request to `api.trygravity.ai/ack`. Using `GravityAd`? That's automatic via IntersectionObserver. Using a custom renderer? Fire `new Image().src = ad.impUrl` on visibility yourself.
  </Step>

  <Step title="Clicks route through tracking">
    Click the ad. The request should go to `api.trygravity.ai/track/click` first and 302 to the advertiser's URL. Never link `ad.url` directly — always `ad.clickUrl`.
  </Step>

  <Step title="Gravity pixel installed (required)">
    Install the [Gravity pixel](/ai-platforms/pixel) on your site. This is required for attribution and payouts. If you have a native app with an in-app browser, also run the [in-app browser install](/ai-platforms/pixel#in-app-browser-webview) inside your WebView.
  </Step>

  <Step title="Session IDs are stable">
    Every ad request from the same conversation should carry the same `sessionId`. This powers frequency capping and experiment bucketing.
  </Step>

  <Step title="Device signals reach the engine">
    Confirm each ad request body includes a `device` object with the end user's `ua` **and** `ip` — both are **required**; requests missing either are rejected with HTTP `400`. The browser SDK collects this via `gravityContext()` — make sure your backend **forwards** it to the ad request instead of dropping it. See [Device signals](/ai-platforms/request-ads#device-signals).
  </Step>

  <Step title="Error handling tested">
    Stop the Gravity API network. Your UI should still render. LLM stream should still work. No exceptions leak.
  </Step>
</Steps>

## After you flip

<Steps>
  <Step title="Check the dashboard">
    `app.trygravity.ai` → your AI platform account. Requests, impressions, clicks, and revenue all update in near-real-time.
  </Step>

  <Step title="Watch fill rate">
    Fill rate = served / requested ads. New AI platforms often see lower fill rates for the first week as campaigns learn your audience. Raising the relevancy threshold or restricting placements can push fill up or down deliberately.
  </Step>

  <Step title="Monitor latency">
    The SDK's ad request has a 3s default timeout. If your p99 hits that, you can bump the timeout via `timeoutMs` on the constructor — but typically a 3s ad timeout just means your LLM streams without the ad that cycle, which is the graceful-degradation behavior you want.
  </Step>
</Steps>

## Rollback

Flip `production: false` on the constructor and deploy. You'll immediately go back to test ads and stop accruing revenue. Nothing else changes.

## What's next

<CardGroup cols={2}>
  <Card title="Payouts & analytics" icon="dollar-sign" href="/ai-platforms/payouts">
    How money moves and what the dashboard tracks.
  </Card>

  <Card title="Experiments" icon="flask" href="/ai-platforms/experiments">
    Let the engine optimize your creative mix automatically.
  </Card>
</CardGroup>
