Developer guide
Adding Jingo to your storefront
Jingo is a shopping assistant that appears on your product pages. It knows your catalog, answers shopper questions, and recommends from your own range. The integration is one script tag, one empty div, and a product feed URL — on any platform. Budget about an hour.
Before you start
You need two things, both on your Jingo dashboard.
| What | Looks like |
|---|---|
| Shop key | jgo_2f2dd7af34f47d6208facc82 |
| Allowed origins | https://acme.com |
Your shop key is not a secret — it sits in a public script tag on a public page. What protects your store is the allowed origins list: Jingo only renders on domains you have registered.
Staging
Send us your product feed
Jingo can't recommend products it hasn't seen, so this comes first. Send us a product feed URL — if you already advertise on Google Shopping, that same URL is fine. We accept Google Merchant Center XML or CSV, and poll it hourly.
| Field | Why we need it |
|---|---|
id | Unique product identifier |
title | Product name |
link | The product page URL — this is how we match a page to a product |
image_link | Product image |
price | With currency, e.g. 248.00 USD |
availability | in stock / out of stock |
brand | Brand name |
description | What the assistant draws on to answer questions |
Add item_group_id, size and color if your products have variants.
Check this one
Add the script tag
Put this in your site's global template so it loads on every page. The footer is fine. Google Tag Manager works identically.
<script async src="https://cdn.jingo.app/embed/loader.js"
data-jingo-shop="YOUR_SHOP_KEY"></script>That's the whole installation. It loads asynchronously and blocks nothing.
Don't pin a version
Content Security Policy
If your site sends a CSP header, allow these three:
script-src https://cdn.jingo.app
frame-src https://api.jingo.app
connect-src https://api.jingo.appAdd the slot
The script needs somewhere to render. Put an empty div on your product page template, wherever you want the assistant — under the buy button is the usual spot.
<div id="assistant-slot"></div>It has no styles of its own and fills the width of its container. The assistant renders in an iframe inside it, so your CSS can't break it and it can't break your page. data-jingo-slot works too if an id is inconvenient.
At this point you're live. Load a product page and the assistant should appear.
Tell us which product
By default Jingo works out which product a page shows by reading the page's <link rel="canonical"> URL — matched against your feed's link field — and then the schema.org/Product JSON-LD block if one is present.
That's enough on most stores. If your pages have no canonical tag, or your JSON-LD has no sku, say so explicitly:
<script>
window.jingo = window.jingo || function () {
(jingo.q = jingo.q || []).push(arguments)
}
jingo('page', { type: 'pdp', productId: 'OV-MRS-0142' })
</script>The first two lines are a queue stub — include them once, above any jingo() call. They let you call jingo() before the script has loaded; the calls replay once it does. productId should match the id in your feed.
If we can't identify it
Single-page storefronts
If selecting a size or colour changes the URL without a page reload, Jingo picks it up automatically — it watches pushState, replaceState and popstate. Nothing for you to do.
Consent
Off by default
Tell Jingo when your consent banner resolves:
jingo('consent', true) // shopper accepted analytics
jingo('consent', false) // shopper declinedOr set a global that Jingo reads on its own:
window.__consent = { analytics: true }If you use a CMP — OneTrust, Cookiebot, Osano — you'll need to add Jingo to your vendor list. At larger companies that takes longer than the code does, so start it early.
Tracking shopper actions
One event is automatic: product_viewed, sent whenever the assistant identifies a product page. The rest you send as they happen.
jingo('track', 'product_added_to_cart', {
productId: 'OV-MRS-0142',
variantTitle: 'US 4 / Ink & Ivory',
quantity: 1,
price: '248.00',
currency: 'USD'
})
jingo('track', 'search_submitted', {
query: 'silk dress',
resultProductIds: ['OV-MRS-0142', 'CO-INS-0088']
})
jingo('track', 'checkout_started', {
productIds: ['OV-MRS-0142'],
totalPrice: '248.00',
currency: 'USD'
})
jingo('track', 'purchase', {
orderId: 'ORD-5521',
orderTotal: '248.00',
currency: 'USD'
})Event reference
The loader adds clientId, shop and consentGranted to every event — you never send those yourself. Bold fields are required; an event without one is dropped.
| Event | Sent by | Fields |
|---|---|---|
product_viewed | Automatic | productId, handle, productTitle, variantId, variantTitle, price, currency |
search_submitted | You | query, resultProductIds |
product_added_to_cart | You | productId, handle, productTitle, variantId, variantTitle, quantity, price, currency |
collection_viewed | You | collectionId, collectionTitle, resultProductIds |
checkout_started | You | productIds, totalPrice, currency |
purchase | You | orderId, orderTotal, currency |
Field formats
- Prices are numeric strings —
"248.00", not"$248.00". The loader normalises what it reads from JSON-LD; what you pass tojingo('track', …)is sent as-is. currencyis a 3-letter ISO code.queryis capped at 200 characters. ID arrays are capped at 10.- IDs must match the
idin your feed, or we can't resolve them.
Why purchase needs an order id
Same events as Shopify
Checking it works
Add ?jingo_debug=1 to any product page URL. Jingo logs what it's doing to the browser console.
| What you see | What it means |
|---|---|
no slot found | The div isn’t on the page. Check it’s on the product template, not just one page. |
nothing identifiable | No canonical URL and no JSON-LD sku. Declare it with jingo(‘page’, …). |
not a product page | Jingo doesn’t think this is a PDP. Declare it explicitly. |
| Nothing in the console at all | The script isn’t loading. Check your CSP, and that the tag is in the rendered HTML. |
| Works live, not on staging | Your staging domain isn’t in the allowed origins list. Send it to us. |
| No events arriving | Consent hasn’t been granted. See step 5. |
| Renders, but doesn’t know the product | It’s missing from the feed, or its link doesn’t match the page’s canonical URL. |
What Jingo stores
- A visitor ID we generate, in
localStorageon your domain under_jingo_cid. A random identifier — no personal data. - The events you send us, linked to that ID.
We set no cookies on your domain. On Safari the visitor ID lasts about seven days, which is a browser limit rather than a choice of ours.
Reference
Script tag attributes
| Attribute | Required | Description |
|---|---|---|
data-jingo-shop | Yes | Your shop key |
data-jingo-api | No | Override the API origin, for testing |
data-jingo-debug | No | Set to 1 to always log |
JavaScript API
| Call | Description |
|---|---|
jingo('page', { type, productId }) | Declare what this page shows |
jingo('track', event, payload) | Send a shopper event |
jingo('consent', bool) | Set analytics consent |
jingo('getClientId', fn) | Read the visitor ID |