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

# Show ads

> Render ads in your UI — pre-built React variants or your own component.

## The pre-built React component

```tsx theme={null}
import { GravityAd } from '@gravity-ai/react';

<GravityAd ad={ads[0]} variant="card" />
```

That's the minimum. `GravityAd` takes the ad object from your server, renders it, fires the impression pixel on visibility (`IntersectionObserver`), and routes clicks through the tracked URL. You do not need to manage any of that yourself.

## Variants — pick what fits your UI

The component ships 20+ visual treatments out of the box:

| Variant                                                                                                                                                                             | Shape                                                                                                                     |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `card`                                                                                                                                                                              | Bordered card with favicon, title, body, CTA. Most common.                                                                |
| `inline`                                                                                                                                                                            | Compact inline chip.                                                                                                      |
| `minimal`                                                                                                                                                                           | Single-line text with subtle CTA.                                                                                         |
| `bubble`                                                                                                                                                                            | Chat-bubble-styled.                                                                                                       |
| `pill`                                                                                                                                                                              | Horizontal pill.                                                                                                          |
| `banner`                                                                                                                                                                            | Horizontal banner, full-width.                                                                                            |
| `hyperlink`                                                                                                                                                                         | Underlined link only.                                                                                                     |
| `text-link`                                                                                                                                                                         | Text with inline link.                                                                                                    |
| `spotlight`, `accent`, `side-panel`, `labeled`, `embed`, `split-action`, `divider`, `toolbar`, `tooltip`, `notification`, `contextual`, `native`, `footnote`, `quote`, `suggestion` | Additional styles — see playground.                                                                                       |
| `lead_form`                                                                                                                                                                         | **Interactive** — captures a lead inline instead of clicking through. See [Lead-form ad units](/ai-platforms/lead-forms). |

Try variants live at [`react-sandbox.trygravity.ai`](https://react-sandbox.trygravity.ai).

## Lead-form ad units

When an advertiser runs a lead-form campaign, the served ad carries a `leadForm`
envelope and `GravityAd` renders an inline form (the user submits without leaving
your app) instead of a click-through. It needs two extra props — `sessionId`
(must match the ad request) and `apiKey`:

```tsx theme={null}
<GravityAd ad={ads[0]} sessionId={sessionId} apiKey={process.env.GRAVITY_API_KEY} />
```

The same component renders normal ads when `ad.leadForm` is absent, so a single
integration covers both. Full reference — display modes, identity pre-fill, the
submission endpoint, and styling — is in the [Lead-form ads
guide](/ai-platforms/lead-forms).

## Style overrides

Pass `slotProps` to override individual elements:

```tsx theme={null}
<GravityAd
  ad={ads[0]}
  variant="card"
  slotProps={{
    container: { style: { borderRadius: 16, maxWidth: 640 } },
    title: { className: 'my-title-class' },
    cta: { style: { backgroundColor: '#6366F1' } },
  }}
/>
```

Available slots: `container`, `inner`, `header`, `favicon`, `brand`, `label`, `body`, `title`, `text`, `cta`, plus variant-specific slots (`iconWrapper`, `accentBar`, `secondaryCta`, `footer`, `arrow`, `contextHeader`).

## Props reference

| Prop                        | Type                 | Description                                          |
| --------------------------- | -------------------- | ---------------------------------------------------- |
| `ad`                        | `AdResponse \| null` | The ad from `gravity.getAds()`.                      |
| `variant`                   | variant name         | Visual treatment.                                    |
| `className`, `style`        | CSS props            | Applied to the outer wrapper.                        |
| `slotProps`                 | object               | Targeted style/className overrides (see above).      |
| `showLabel`                 | boolean              | Show/hide the "Sponsored" label. Default `true`.     |
| `labelText`                 | string               | Override the label text. Default `"Sponsored"`.      |
| `onClick`                   | `() => void`         | Fires on click.                                      |
| `onImpression`              | `() => void`         | Fires when impression pixel fires.                   |
| `onClickTracked`            | `() => void`         | Fires after the click tracking URL hits.             |
| `fallback`                  | ReactNode            | What to render when `ad` is `null`. Default nothing. |
| `disableImpressionTracking` | boolean              | Skip auto impression pixel — you fire it yourself.   |
| `openInNewTab`              | boolean              | Open landing page in new tab. Default `true`.        |

## Custom rendering

You don't have to use `GravityAd`. The ad object is all you need:

```tsx theme={null}
function MyAd({ ad }) {
  // Fire impression when visible
  const ref = useRef(null);
  useEffect(() => {
    if (!ref.current || !ad) return;
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        new Image().src = ad.impUrl;  // fire impression pixel
        observer.disconnect();
      }
    });
    observer.observe(ref.current);
    return () => observer.disconnect();
  }, [ad]);

  if (!ad) return null;

  return (
    <a ref={ref} href={ad.clickUrl} target="_blank" rel="noopener">
      <img src={ad.favicon} alt="" />
      <span>{ad.brandName}</span>
      <p>{ad.adText}</p>
      <button>{ad.cta}</button>
    </a>
  );
}
```

Two must-dos for custom renderers:

1. **Use `ad.clickUrl`** as the href — never `ad.url` directly. `clickUrl` routes through Gravity's tracking and 302s to the landing page, ensuring the click is counted for billing and reporting.
2. **Fire `ad.impUrl`** exactly once, when the ad first becomes visible. A single pixel request: `new Image().src = ad.impUrl`.

## Multiple placements

```tsx theme={null}
<div className="response">
  <p>{response}</p>
  {ads[0] && <GravityAd ad={ads[0]} variant="card" />}
</div>

<aside className="sidebar">
  {ads[1] && <GravityAd ad={ads[1]} variant="side-panel" />}
</aside>
```

The `ads` array is ordered to match the `placements` array you sent on the request.

## Variants for the engine to choose

When [experiments](/ai-platforms/experiments) are active, the engine assigns a variant per session. Let the engine's choice win by default:

```tsx theme={null}
<GravityAd ad={ad} variant={ad.variant ?? 'card'} />
```

If the engine has no opinion (no experiment running), `ad.variant` is undefined and your `'card'` default applies.

## Next

<CardGroup cols={2}>
  <Card title="Experiments" icon="flask" href="/ai-platforms/experiments">
    How the engine optimizes your creative mix.
  </Card>

  <Card title="Pixel" icon="code" href="/ai-platforms/pixel">
    Drop `gr-pix.js` on your site — SDK auto-picks up the visitor ID for better attribution.
  </Card>
</CardGroup>
