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

# X Pixel

> Install an X Pixel and map conversion events for X Ads on your Replo site.

export const DemoVideo = ({src, poster, label}) => {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  async function togglePlayback() {
    const video = videoRef.current;
    if (!video) return;
    if (!video.paused) {
      video.pause();
      return;
    }
    try {
      await video.play();
    } catch {
      setIsPlaying(false);
    }
  }
  return <div style={{
    position: "relative"
  }}>
      <video ref={videoRef} controls playsInline preload="none" poster={poster} aria-label={label} width="100%" style={{
    display: "block"
  }} onPlay={() => setIsPlaying(true)} onPause={() => setIsPlaying(false)} onEnded={() => setIsPlaying(false)}>
        <source src={src} type="video/mp4" />
        <a href={src}>Download the demo</a>
      </video>
      <button type="button" aria-label={`${isPlaying ? "Pause" : "Play"} demo: ${label}`} onClick={togglePlayback} style={{
    position: "absolute",
    top: 0,
    right: 0,
    bottom: 54,
    left: 0,
    border: 0,
    padding: 0,
    background: "transparent",
    cursor: "pointer",
    borderRadius: 8
  }} />
    </div>;
};

export const TryPromptButton = ({prompt, imageSrc, imageAlt = "Template preview", imageStyles = {}, buttonCta = "Build in Replo"}) => {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  const PUBLISHER_API_BASE_URL = "https://publisher.replo.app";
  const APP_URL = "https://dashboard.replo.app";
  const LoaderIcon = <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{
    animation: "spin 1s linear infinite"
  }}>
      <path d="M21 12a9 9 0 1 1-6.219-8.56" />
    </svg>;
  const ChevronIcon = <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="m9 18 6-6-6-6" />
    </svg>;
  async function postJSON(url, body, headers = {}, timeoutMs = 120000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...headers
        },
        body: JSON.stringify(body ?? ({})),
        signal: controller.signal
      });
      const responseText = await response.text();
      if (!response.ok) throw new Error(`API Error: ${response.status}`);
      return responseText ? JSON.parse(responseText) : {};
    } finally {
      clearTimeout(timeoutId);
    }
  }
  async function handleTryPrompt(event) {
    event.preventDefault();
    event.stopPropagation();
    setIsLoading(true);
    setError(null);
    try {
      const body = {
        prompt,
        file: null
      };
      const {seed} = await postJSON(`${PUBLISHER_API_BASE_URL}/api/v1/marketing/issue-marketing-site-jwt`, body);
      if (!seed) throw new Error("No seed returned from API");
      const url = new URL(APP_URL);
      url.searchParams.set("type", "agent");
      url.hash = `seed=${encodeURIComponent(seed)}`;
      window.open(url.toString(), "_blank");
    } catch (caughtError) {
      console.error("Failed to generate prompt:", caughtError);
      setError("Something went wrong. Please try again.");
    } finally {
      setIsLoading(false);
    }
  }
  return <div style={{
    position: "relative",
    display: "inline-block",
    width: "100%"
  }}>
      {}
      {imageSrc && <img src={imageSrc} alt={imageAlt} style={{
    width: "100%",
    height: "auto",
    display: "block",
    borderRadius: "8px",
    opacity: 0.8,
    ...imageStyles
  }} />}

      {}
      <div style={imageSrc ? {
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    zIndex: 10
  } : {
    display: "flex",
    justifyContent: "flex-start",
    margin: "1.25rem 0"
  }}>
        <button type="button" className="try-replo-btn" onClick={handleTryPrompt} disabled={isLoading} style={{
    backgroundColor: "#274AE2",
    color: "#ffffff",
    padding: "0.5rem 1.1rem",
    fontSize: "0.875rem",
    fontWeight: 600,
    fontFamily: "inherit",
    border: "none",
    borderRadius: "9999px",
    cursor: isLoading ? "not-allowed" : "pointer",
    lineHeight: 1.4,
    whiteSpace: "nowrap",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    WebkitFontSmoothing: "antialiased",
    boxSizing: "border-box",
    opacity: isLoading ? 0.7 : 1,
    boxShadow: "0 1px 2px rgba(15, 23, 42, 0.08)",
    transition: "background-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease"
  }}>
          <span style={{
    visibility: isLoading ? "hidden" : "visible",
    display: "inline-flex",
    alignItems: "center",
    gap: "0.375rem"
  }}>
            {buttonCta}
            {ChevronIcon}
          </span>
          {isLoading && <span style={{
    position: "absolute",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center"
  }}>
              {LoaderIcon}
            </span>}
        </button>
      </div>

      {}
      <style>
        {`
          @keyframes spin {
            from {
              transform: rotate(0deg);
            }
            to {
              transform: rotate(360deg);
            }
          }
          .try-replo-btn:hover:not(:disabled) {
            background-color: #1f3ec0 !important;
            box-shadow: 0 4px 12px rgba(39, 74, 226, 0.35);
            transform: translateY(-1px);
          }
          .try-replo-btn:active:not(:disabled) {
            transform: translateY(0);
            box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
          }
          .try-replo-btn:focus-visible {
            outline: 2px solid #274AE2;
            outline-offset: 2px;
          }
        `}
      </style>

      {}
      {error && <div style={{
    marginTop: "12px",
    padding: "12px 16px",
    backgroundColor: "#fee",
    border: "1px solid #fcc",
    borderRadius: "6px",
    color: "#c33",
    fontSize: "14px",
    textAlign: "center"
  }} role="alert">
          {error}
        </div>}
    </div>;
};

The X Pixel records site visits for X Ads. Conversion events are optional: you create each event in X Ads Events Manager, then map its event ID in Replo.

The pixel uses Replo's [consent layer](/features/cookie-consent). When cookie consent is enabled, it waits for marketing consent by default. **Off** mode does not request consent; an external consent manager still controls tracking if configured.

## Add the X Pixel

You can add the pixel in chat or in Site settings.

### Add it with Replo

Give Replo your **Pixel ID** and ask it to add the pixel, then publish.

```text theme={null}
Add my X Pixel with ID o6ou1 to my site, then publish
```

<TryPromptButton prompt="Add my X Pixel with ID o6ou1 to my site, then publish" />

If you also have conversion event IDs from X Ads Events Manager (`tw-<pixel ID>-…`), include them in the same request. Replo maps only the events you provide.

### Add it in Site settings

<DemoVideo src="https://assets.replocdn.com/product-assets/announcements/3030d96c-750a-4e16-8acb-0b2c837027bb/x-pixel-setup.mp4" poster="https://assets.replocdn.com/product-assets/announcements/5cf964a7-d3b4-42bc-9c7f-4bfd6c11e97c/x-pixel-setup-poster.jpg" label="Find your Pixel ID in X Ads and connect X Pixel in Replo" />

1. Open the [Site Builder](/apps/website-builder).
2. Open **Settings** in the top bar and choose **Site settings**.
3. Select the [Scripts & Pixels](/features/scripts) tab and click **X Pixel**.
4. Paste the pixel ID from X Ads → Tools → Events Manager (the value in `twq('config', '…')` in your base code).
5. Click **Connect**.
6. [Publish your site](/publishing) to make the pixel live.

<Note>
  If this site's SDK is older than X Pixel support, Replo asks you to update the site's `@replohq/sdk` first and does not change your scripts. Add the pixel after that update.
</Note>

<Note>
  Add the pixel only once. If Google Tag Manager, Elevar, or Segment already fires X, skip connecting it here. If the site already loads `static.ads-twitter.com/uwt.js` as custom code, reuse that pixel ID and remove the old tag so visits are not counted twice.
</Note>

## Map conversion events

The pixel ID alone records site visits and landing page views. To count conversions, create each event in X Ads Events Manager, then paste its event ID.

1. Open **X Pixel** in Scripts & Pixels after it is connected.
2. Under **Conversion events**, paste an event ID for each event you want Replo to send. Leave a field blank to skip that event.
3. Click **Save events**.
4. [Publish your site](/publishing) to make the updated event mappings live.

Event IDs look like `tw-<your pixel ID>-abcde`. An ID from a different pixel is rejected.

* **Page view:** landing page and in-site page changes, after consent allows tracking
* **Product view:** a visitor opens a product. X has no product-view type; use a Custom event
* **Add to cart:** a visitor adds a product to the cart
* **Checkout started:** a visitor starts checkout. X has no checkout type; use a Custom event. Skipped when Shopify hosts checkout
* **Purchase:** only when your site reports the order. Skipped when Shopify hosts checkout; use X's Shopify app for those purchases

Catalog matching for Dynamic Product Ads is not supported.

## Finding your Pixel ID

1. Log in to X Ads.
2. Open **Tools**, then **Events Manager**.
3. Your **Pixel ID** is the value in `twq('config', '…')` in the base code.

## Shopify checkout

When Shopify hosts checkout, Replo does not send checkout or purchase events from the site. Use X's Shopify app for those purchases, and keep the same pixel ID in Replo and in Shopify.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.