> ## 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.

# Pixel

> Install the Gravity pixel on your website — required for attribution, measurement, and payouts.

The **Gravity pixel** (`gr-pix.js`) is a **required** install on your site. It captures attribution context so Gravity can tie ad impressions and clicks back to real outcomes — without it, we can't measure performance or pay you.

<Warning>
  **The pixel is required.** Without it, Gravity cannot attribute conversions or calculate payouts. Install it before going live.
</Warning>

## Web install

Drop this snippet on every page — ideally in your base template / layout:

```html theme={null}
<!-- Before </body> -->
<script>
  !function(w,d,t,u,n,a,m){w['GravityPixelObject']=n;w[n]=w[n]||function(){
  (w[n].q=w[n].q||[]).push(arguments)},w[n].l=1*new Date();a=d.createElement(t),
  m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
  }(window,document,'script','https://code.trygravity.ai/gr-pix.js','gravity');
  gravity('init', 'YOUR_PIXEL_ID');
</script>
```

Find `YOUR_PIXEL_ID` in your dashboard under **Settings → Platform Settings**. It's a UUID.

### Verify it's firing

1. Load any page with the pixel installed.
2. Open your browser DevTools → Network tab and look for a request to `api.trygravity.ai/track/gr-events`.
3. A `200` response means the pixel is firing correctly. Events typically appear in your dashboard within \~10 minutes.

## In-app browser (WebView)

If your app opens Gravity ad links **inside** an in-app WebView rather than the system browser, install the pixel inside the WebView too with the `inAppBrowser: true` flag. This preserves attribution when a user clicks an ad and lands on the advertiser's page inside your app.

<Tip>
  **Skip this section if** your app opens ad links in the system browser (`UIApplication.shared.open(url)` or equivalent). The web install above is all you need.
</Tip>

### Swift (iOS / iPadOS)

```swift theme={null}
import WebKit

let contentController = WKUserContentController()

// Step 1: config at document start
let configScript = WKUserScript(
    source: """
    window.GRAVITY_PIXEL_CONFIG = {
      inAppBrowser: true,
      pixel_id: "YOUR_PIXEL_ID"
    };
    """,
    injectionTime: .atDocumentStart,
    forMainFrameOnly: true
)
contentController.addUserScript(configScript)

// Step 2: pixel loader + init at document end
let pixelScript = WKUserScript(
    source: """
    !function(w,d,t,u,n,a,m){w['GravityPixelObject']=n;w[n]=w[n]||function(){
    (w[n].q=w[n].q||[]).push(arguments)},w[n].l=1*new Date();a=d.createElement(t),
    m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
    }(window,document,'script','https://code.trygravity.ai/gr-pix.js','gravity');
    gravity('init', 'YOUR_PIXEL_ID');
    """,
    injectionTime: .atDocumentEnd,
    forMainFrameOnly: true
)
contentController.addUserScript(pixelScript)

let config = WKWebViewConfiguration()
config.userContentController = contentController
let webView = WKWebView(frame: .zero, configuration: config)
```

### React Native

```jsx theme={null}
import { WebView } from 'react-native-webview';

const INJECT_BEFORE = `
  window.GRAVITY_PIXEL_CONFIG = {
    inAppBrowser: true,
    pixel_id: "YOUR_PIXEL_ID"
  };
  true;
`;

const INJECT_AFTER = `
  !function(w,d,t,u,n,a,m){w['GravityPixelObject']=n;w[n]=w[n]||function(){
  (w[n].q=w[n].q||[]).push(arguments)},w[n].l=1*new Date();a=d.createElement(t),
  m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
  }(window,document,'script','https://code.trygravity.ai/gr-pix.js','gravity');
  gravity('init', 'YOUR_PIXEL_ID');
  true;
`;

<WebView
  source={{ uri: url }}
  injectedJavaScriptBeforeContentLoaded={INJECT_BEFORE}
  injectedJavaScript={INJECT_AFTER}
/>
```

### Flutter

```dart theme={null}
import 'package:webview_flutter/webview_flutter.dart';

final controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setNavigationDelegate(NavigationDelegate(
    onPageStarted: (_) async {
      await controller.runJavaScript('''
        window.GRAVITY_PIXEL_CONFIG = {
          inAppBrowser: true,
          pixel_id: "YOUR_PIXEL_ID"
        };
      ''');
    },
    onPageFinished: (_) async {
      await controller.runJavaScript('''
        !function(w,d,t,u,n,a,m){w['GravityPixelObject']=n;w[n]=w[n]||function(){
        (w[n].q=w[n].q||[]).push(arguments)},w[n].l=1*new Date();a=d.createElement(t),
        m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
        }(window,document,'script','https://code.trygravity.ai/gr-pix.js','gravity');
        gravity('init', 'YOUR_PIXEL_ID');
      ''');
    },
  ));
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Pixel doesn't fire on a web page">
    * Make sure the script loads last in the document (before `</body>`).
    * Check DevTools Network tab for a request to `code.trygravity.ai/gr-pix.js`.
    * Check the console for errors. If another script throws before the pixel runs, the pixel load order may need adjusting.
  </Accordion>

  <Accordion title="Pixel fires but events don't show in dashboard">
    * Confirm `YOUR_PIXEL_ID` matches the Pixel ID in **Settings → Platform Settings**. It's separate from your API key.
    * Check DevTools Network for `api.trygravity.ai/track/gr-events` POST requests. A 200 response means we got it; dashboard updates within \~10 minutes.
  </Accordion>

  <Accordion title="WebView events not arriving">
    * iOS WebKit needs `WKWebsiteDataStore.default()` (the default). `.nonPersistentDataStore()` breaks cookie persistence.
    * Verify `injectionTime` / `onPageFinished` actually fires — `console.log` from inside the injected script and capture via `WKScriptMessageHandler` (Swift) or `onMessage` (RN).
  </Accordion>
</AccordionGroup>

## Next

<Card title="Going live" icon="rocket" href="/ai-platforms/going-live">
  Final checklist before flipping `production: true`.
</Card>
