Lapis Pixel
Install the Lapis pixel with one script tag to track ChatGPT ad visits and conversions in the browser.
The Lapis Pixel is the browser half of Lapis conversion tracking. It records visits from ChatGPT ads, opens an attributed session, and lets you track conversions that happen in the browser. The Conversion API is the server half, and it handles verified conversions that only your backend can see.
This page covers the four things you need to do: install the pixel, set up your ad URLs, track conversions, and read the click ID for server-side attribution.
1. Install the pixel
Add this script tag to every page of your website, just before the closing </body> tag:
<script
src="https://cdn.trylapis.com/pixel/v1/lapis-pixel.js"
data-key="YOUR_API_KEY"
></script>
Replace YOUR_API_KEY with the pixel API key from Lapis. It looks like pk_79de89010be148c5a5a631ae.
Once the pixel loads, it exposes a global lapis() function on window, but only for visitors who arrived from a ChatGPT ad. For every other visitor the function is not defined. Always guard your calls with if (window.lapis) so your code never throws on organic traffic.
Tip: The pixel is lightweight (about 2KB), loads asynchronously, and never blocks your page from rendering.
For platform-specific install steps (Shopify theme code, Framer custom code, WordPress, GTM, and more), see Platform setup.
Installing via Google Tag Manager
If you use GTM, you can add the pixel there instead of editing your site code directly:
- Go to Tags → New → Custom HTML
- Paste the code below
- Set the trigger to All Pages
- Click Publish
<script src="https://cdn.trylapis.com/pixel/v1/lapis-pixel.js" data-key="YOUR_API_KEY"></script>
2. Set up your ChatGPT ad URLs
When you create ads in the ChatGPT Ads platform, add parameters to the destination URL so Lapis can attribute conversions back to the right campaign, ad group, and ad.
URL format
https://yoursite.com/?utm_source=chatgpt&lapis_campaign=CAMPAIGN_NAME&lapis_adgroup=AD_GROUP_NAME&lapis_ad=AD_ID
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
utm_source |
Required | Must be chatgpt or openai. This is what activates the pixel. |
chatgpt |
lapis_campaign |
Recommended | Your campaign name | spring_launch |
lapis_adgroup |
Recommended | Your ad group name | us_designers |
lapis_ad |
Recommended | The specific ad identifier | ad_001 |
The utm_source value is the only thing the pixel needs to start tracking. The three lapis_ parameters are optional, but without them your conversions all roll up under one unnamed campaign, so add them if you want per-ad reporting.
Example URLs
Minimum required:
https://yoursite.com/?utm_source=chatgpt
Full attribution (recommended):
https://yoursite.com/?utm_source=chatgpt&lapis_campaign=spring_launch&lapis_adgroup=us_designers&lapis_ad=ad_001
UTM fallbacks
If you already tag your URLs with standard UTM parameters, the pixel reads those automatically when the lapis_ versions are missing:
| Lapis parameter | UTM fallback |
|---|---|
lapis_campaign |
utm_campaign |
lapis_adgroup |
utm_content |
lapis_ad |
utm_term |
3. Track conversions
Page views are tracked for you automatically. For conversions such as purchases and signups, call lapis() at the moment the event happens.
Purchase
lapis("purchase", {
value: 149.99,
currency: "USD",
order_id: "ORD-123"
});
Signup
lapis("signup");
Lead
lapis("lead", { value: 50 });
Add to cart
lapis("add_to_cart", { value: 29.99 });
Custom events
You can track any event name with any custom data:
lapis("subscribe", { plan: "pro", interval: "yearly", value: 199 });
lapis("form_submit", { form_name: "contact", source: "footer" });
lapis("download", { file: "whitepaper.pdf" });
Conversion data fields
| Field | Type | Description |
|---|---|---|
value |
Number | Monetary value (for example, 149.99) |
currency |
String | ISO currency code, defaults to "USD" |
order_id |
String | Unique order identifier, used for deduplication |
You can include any additional fields. Lapis stores all of them and makes them available in your dashboard.
Note: Browser events are best-effort by nature. Ad blockers and closed tabs mean some never arrive. Send your verified conversions (orders, signups) server-side through the Conversion API instead. It deduplicates against browser events by event ID, so you get reliable numbers without double-counting.
4. How it works
- A visitor clicks your ChatGPT ad and lands on your site with the tracking parameters in the URL.
- The pixel sees
utm_source=chatgptand opens a session. - It sets the
lapis_sidcookie for 30 days to follow the visitor across pages. - Every page view is recorded automatically.
- When you call
lapis(), the conversion is recorded and attributed to the original campaign. - Everything shows up in your Lapis dashboard.
Note: The pixel only activates for visitors coming from ChatGPT ads. For all other traffic it does nothing, and
lapis()stays undefined.
The lapis_sid cookie and click ID
The cookie value is JSON that contains a sid field. That sid is the Lapis click ID. To attribute a conversion server-side, read the click ID out of the cookie, carry it through your signup or checkout flow, and include it as lapis_click_id in your Conversion API events:
function getLapisClickId() {
const cookie = document.cookie
.split("; ")
.find((entry) => entry.startsWith("lapis_sid="));
if (!cookie) return null;
try {
const session = JSON.parse(
decodeURIComponent(cookie.split("=").slice(1).join("="))
);
return session.sid || null;
} catch {
return null;
}
}
If the cookie is missing, there is no click ID, which means the visitor did not arrive through a tracked ad. Never invent one.
5. Integration examples
Shopify
Add the pixel script in Settings → Custom Code → Before </body> tag, then track purchases on the order confirmation page:
<script>
if (window.lapis && Shopify.checkout) {
lapis("purchase", {
value: Shopify.checkout.total_price / 100,
currency: Shopify.checkout.currency,
order_id: Shopify.checkout.order_id
});
}
</script>
For the full Shopify integration, including reliable server-side order tracking, see the Shopify platform guide.
React / Next.js
function CheckoutSuccess({ order }) {
useEffect(() => {
if (window.lapis) {
lapis("purchase", {
value: order.total,
currency: order.currency,
order_id: order.id
});
}
}, []);
return <div>Thank you for your purchase!</div>;
}
Signup form
<form id="signup-form">
<input type="email" name="email" />
<button type="submit">Sign Up</button>
</form>
<script>
document.getElementById("signup-form")
.addEventListener("submit", function () {
if (window.lapis) {
lapis("signup");
}
});
</script>
Content Security Policy
If your site enforces CSP, allow https://cdn.trylapis.com in script-src and https://api.trylapis.com in connect-src.
FAQ
Does the pixel slow down my site?
No. The script is about 2KB and loads asynchronously, so it never blocks page rendering.
What if a visitor comes back days later?
The session cookie lasts 30 days. If a visitor from a ChatGPT ad returns within that window, their page views and conversions still attribute to the original campaign.
Does it track all my visitors?
No. The pixel only tracks visitors who arrived from a ChatGPT ad (identified by the utm_source parameter). All other traffic is ignored completely.
What if lapis() is called but the visitor didn’t come from ChatGPT?
Nothing happens, because lapis() is only defined for ChatGPT ad visitors. Always check if (window.lapis) before calling it so your code never errors.
Can I use multiple API keys on one site?
No. Use one API key per site. Each key maps to a single Lapis account.