Google AI Mode shopping results
The product cards, sponsored products and videos inside AI Mode answers, with prices and stores.
shoppingCards carries the products in the answer, ads the sponsored products with their store and price, and videos its video cards. inlineProducts comes back empty: Google shows an inline product mention without a name or price.
include.expandProducts is not available yet: a request that sets it is refused with a 400 and not charged.
Returned in result
| Field |
|---|
shoppingCards |
inlineProducts |
videos |
ads |
Request
curl -X POST "https://api.answerline.dev/v1/monitor/aimode" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"Family-friendly hotels in Lisbon","country":"PT","hl":"en"}'
import { Client } from "@answerline/sdk";
const client = new Client({ apiKey: process.env.API_KEY! });
const answer = await client.monitor.aimode({
"prompt": "Family-friendly hotels in Lisbon",
"country": "PT",
"hl": "en"
});
import os
from answerline import Client
with Client(os.environ["API_KEY"]) as client:
answer = client.monitor.aimode(
prompt="Family-friendly hotels in Lisbon",
country="PT",
hl="en",
)
What AI Mode shopping results are
AI Mode shopping results are the commercial blocks Google’s AI Mode places inside a conversational answer: a carousel of product cards, product cards embedded in the answer text, a sponsored section, and video cards. This API returns them as shoppingCards, ads and videos. inlineProducts is in the contract and comes back empty: Google shows an inline product mention without a name or price.
They show which merchants hold the carousel positions for a category query, the price band and who is discounting (from numeric price.value and oldPrice.value), which stores buy the sponsored section, and which channels’ videos appear next to the products.
Field reference
result.shoppingCards[]
| Field | Type | Meaning |
|---|---|---|
title |
string | Product title. |
price.value |
number | Numeric price. |
price.currency |
string | Currency symbol. |
price.raw |
string | Raw price string as displayed, for example "$129.99". |
oldPrice.value, .currency, .raw |
number, string, string | Original price before discount, same shape as price. |
store |
string | Merchant or store name. |
rating |
number | Product rating. |
reviews |
string | Review count, as a string. |
thumbnail |
string | Product image. |
productLink |
string | Direct product URL. |
snippet |
string | Product description snippet. |
snippet_links[] |
array of {text, link, redirectLink} |
Links inside the snippet; redirectLink only when Google served a redirect. |
position |
integer | Position in the shopping carousel, 0-indexed. |
result.inlineProducts[]
Empty on the answers served today. The contract’s fields:
| Field | Type | Meaning |
|---|---|---|
title |
string | Product title. |
position |
integer | 1-indexed rank in display order. |
price.value, price.currency |
number, string | Numeric price and currency symbol. |
oldPrice.value, oldPrice.currency |
number, string | Original price before discount. |
store |
string | Merchant or store name. |
thumbnail |
string | Product image URL. |
productLink |
string | Direct product URL. |
result.ads
| Field | Type | Meaning |
|---|---|---|
title |
string | Section title for the ads. |
ads[].title |
string | Ad product title. |
ads[].url |
string | Ad click-through URL. |
ads[].position |
integer | Position index of the ad. |
ads[].price.value, ads[].price.currency |
number, string | Numeric price and currency symbol. |
ads[].store |
string | Merchant or store name. |
ads[].rating |
number | Product rating. |
ads[].reviews |
string | Review count, as a string. |
ads[].redirectLink |
string | Google’s /goto redirect, present only when Google served one. |
result.videos[]
| Field | Type | Meaning |
|---|---|---|
title |
string, required | Video title. |
link |
string, required | Canonical watch URL, timestamp parameters stripped. |
platform |
string | Hosting platform. |
channel |
string | Channel or uploader name. |
duration |
string | Visible duration label, mm:ss or hh:mm:ss. |
thumbnail |
string | Public thumbnail URL. |
redirectLink |
string | Google’s /goto redirect, present only when Google served one. |
Annotated excerpt
Values are illustrative; field names and types follow the POST /v1/monitor/aimode result schema.
{
"success": true,
"result": {
"text": "For small apartments, a compact standing desk with a 48-inch top...",
"shoppingCards": [
{
"title": "Example Lift Desk 48\"",
"price": { "value": 279.0, "currency": "$", "raw": "$279.00" },
"oldPrice": { "value": 329.0, "currency": "$", "raw": "$329.00" },
"store": "Example Home",
"rating": 4.5,
"reviews": "1.2K", // string, not an integer
"productLink": "https://www.example-home.com/desks/lift-48",
"snippet": "Dual motor, memory presets...",
"position": 0 // 0-indexed carousel slot
}
],
"inlineProducts": [], // empty on the answers served today
// An object: section title plus the ads in it.
"ads": {
"title": "Sponsored",
"ads": [
{
"title": "Example Pro Standing Desk",
"url": "https://www.example-desks.com/pro",
"position": 1,
"price": { "value": 349.0, "currency": "$" },
"store": "Example Desks",
"redirectLink": "https://www.google.com/goto?url=example"
}
]
},
"videos": [
{
"title": "Standing desks for tiny apartments",
"link": "https://www.youtube.com/watch?v=example",
"platform": "YouTube",
"channel": "Example Workspace",
"duration": "9:41"
}
]
}
}
Cost and include flag
shoppingCards, inlineProducts, ads and videos need no flag. An AI Mode request costs $0.00206 on every tier.
include.expandProducts, merchant offers for the products in the answer, is not available yet: a request that sets it is refused with a 400 and not charged. include.googleGoto is deprecated and ignored.
Example: store share of product slots and advertiser share
The script samples a set of product queries and reports each store’s share of all product slots, its share of first slots, the share of its slots shown with an old price, and each store’s share of ad slots.
import os
import time
from collections import Counter
from datetime import date
import requests
API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
PROMPTS = ["best standing desk for a small apartment", "standing desk under $300"]
SAMPLES = 4
DAY = date.today().isoformat()
def run_tasks(tasks):
resp = requests.post(f"{API}/v1/async/task/batch", headers=HEADERS, json=tasks, timeout=60)
resp.raise_for_status()
pending = {item["task"]["id"] for item in resp.json()["results"] if item["success"]}
results = []
while pending:
time.sleep(10)
for task_id in list(pending):
body = requests.get(f"{API}/v1/async/task/{task_id}", headers=HEADERS, timeout=30).json()
status = body["task"]["status"]
if status in ("COMPLETED", "FAILED"):
pending.discard(task_id)
if status == "COMPLETED":
results.append(body["response"]["result"])
return results
tasks = [
{
"taskType": "AIMODE",
"payload": {"prompt": prompt, "country": "US", "hl": "en"},
"idempotencyKey": f"desks-shop-{p}-s{s}-{DAY}",
}
for p, prompt in enumerate(PROMPTS)
for s in range(SAMPLES)
]
answers = run_tasks(tasks)
slots, first, discounted, ads = Counter(), Counter(), Counter(), Counter()
with_products = with_ads = 0
for result in answers:
# Normalise both arrays to 1-based ranks.
products = [(c.get("position", 0) + 1, c) for c in result.get("shoppingCards", [])]
products += [(i.get("position", 0), i) for i in result.get("inlineProducts", [])]
with_products += bool(products)
for rank, item in products:
store = item.get("store") or "?"
slots[store] += 1
first[store] += rank == 1
discounted[store] += bool((item.get("oldPrice") or {}).get("value"))
ad_items = (result.get("ads") or {}).get("ads", [])
with_ads += bool(ad_items)
ads.update(ad.get("store") or "?" for ad in ad_items)
n = len(answers) or 1
total_slots, total_ads = sum(slots.values()) or 1, sum(ads.values()) or 1
print(f"{len(answers)} answers; products in {with_products / n:.0%}, ads in {with_ads / n:.0%}")
for store, count in slots.most_common(10):
print(f"{store:28} slots {count / total_slots:5.0%} first {first[store]:3} discounted {discounted[store] / count:5.0%}")
for store, count in ads.most_common(10):
print(f"ad {store:24} {count / total_ads:5.0%}")
Pitfalls
shoppingCards[].position starts at 0 and inlineProducts[].position at 1. Normalize once, at ingestion.
reviews on shopping cards and ads is a string such as 1.2K. Convert it before doing arithmetic, and keep the original text.
currency is a symbol, and $ is shared by several currencies. Pair it with the request’s country when comparing markets.
ads is an object: read result["ads"]["ads"], and handle a missing ads key.
A product can fill more than one slot in an answer. Deduplicate on productLink when counting distinct products; keep every slot when counting slots.
Product and ad blocks vary between runs, so compare periods on several samples each (AI answer volatility).
Related
- AI Mode engine guide: calls, webhooks, targeting and billing.
- AI Mode sources and AI Mode places.
- Tracking ads in AI answers and Google Search ads.
- Compare with ChatGPT shopping.
- Competitor analysis and credits.
Questions
What is the difference between shoppingCards and inlineProducts in AI Mode?
shoppingCards are the product cards in the shopping carousel, with price, old price, store, rating, reviews, snippet and snippet links. inlineProducts is the contract field for products inside the answer text; it comes back empty, because Google shows an inline product mention without a name or price.
Are AI Mode product positions 0-based or 1-based?
shoppingCards[].position is 0-indexed within the carousel. inlineProducts[].position is 1-indexed in display order. Normalize both before storing ranks.
Can I get merchant offers with include.expandProducts?
Not available yet: a request that sets it is refused with a 400 and not charged.
Is the AI Mode ads field an array?
No. ads is an object with a section title and an ads array. Each ad has title, url, position, price, store, rating, reviews and, when Google served a redirect, redirectLink.
Do shopping cards, videos and ads cost extra in AI Mode?
No. They are part of the AI Mode result at $2.06 per 1,000 on every tier. The endpoint has no add-ons.