Recommendations API
Reference for fetching recommendation sections and sending attribution events. For a guided walkthrough, see Loading Recommendations.
useRecommendations()
React hook that fetches recommendation sections for the current page. Must be used within a <GloodProvider> whose client has the recommendations app registered.
Signature
function useRecommendations(
params: GetSectionsParams,
options?: UseRecommendationsOptions
): UseRecommendationsResult
Parameters — GetSectionsParams
| Parameter | Type | Required | Description |
|---|
pageType | PageType | Yes | Page the visitor is on: 'home', 'product_page', 'collection', 'cart', 'blog', 'order_confirm', 'checkout', 'ajax_cart', 'returns', '404', 'other' |
pageUrl | string | No | Full URL of the current page. Defaults to window.location.href in the browser |
locale | string | No | Locale code, e.g. 'en-US'. Defaults to navigator.language in the browser |
productId | string | number | No | Numeric Shopify product id (not GID). Required for product_page recommendations |
cartProductIds | (string | number)[] | No | Numeric product ids currently in the cart |
sections | number[] | No | Specific Glood section ids to fetch. Empty = all enabled sections for the page |
clientId | string | No | Glood client id. Defaults to the _glood_client_id cookie in the browser |
userId | string | No | Logged-in user id |
customerId | string | No | Shopify customer id |
market | string | No | Market id for multi-market shops |
currency | string | No | Currency code |
cartValue | string | No | Cart total value (used for targeting rules) |
collection | number | No | Numeric collection id (for collection pages) |
qs | string | No | Query string used for experience assignment |
preview | boolean | No | Include disabled sections (preview mode). Default false |
Options — UseRecommendationsOptions
| Option | Type | Required | Description |
|---|
skip | boolean | No | Skip fetching until required params are ready. Default false |
Returns — UseRecommendationsResult
| Attribute | Type | Description |
|---|
sections | RecommendationSection[] | Sections with full product data. Empty array while loading or when none configured |
data | SectionsResponse | null | Full API response (request_id, experience, visit_id, config, …) |
loading | boolean | true while the request is in flight |
error | Error | null | GloodApiError on API failures, Error on setup problems |
refetch | () => void | Re-run the request with the same params |
trackRender | (track: SectionTrack) => void | Send a glood:section:render attribution event |
trackView | (track: SectionTrack) => void | Send a glood:section:view attribution event |
trackClick | (track: SectionTrack) => void | Send a glood:section:click attribution event |
trackAddToCart | (track: SectionTrack) => void | Send a glood:section:add_to_cart attribution event |
Basic Usage
import { useRecommendations } from '@glood/hydrogen';
const { sections, loading, error } = useRecommendations({
pageType: 'product_page',
productId: '8977367564515',
});
With All Options
const { sections, data, loading, error, refetch, trackClick } =
useRecommendations(
{
pageType: 'cart',
cartProductIds: ['8977367564515', '9311227838783'],
cartValue: '199.00',
currency: 'USD',
customerId: '7412356789',
sections: [218966], // only this section
},
{ skip: false },
);
fetchRecommendationSections()
Framework-agnostic fetcher for the sections API. Works server-side (Hydrogen route loaders) and in the browser. The useRecommendations hook uses this internally.
Signature
async function fetchRecommendationSections(
options: FetchSectionsOptions,
params: GetSectionsParams
): Promise<SectionsResponse>
Options — FetchSectionsOptions
| Option | Type | Required | Description |
|---|
apiKey | string | Yes | Glood storefront token (same value as GloodConfig.apiKey) |
myShopifyDomain | string | Yes | Shop domain, e.g. 'store-name.myshopify.com' |
endpoint | string | No | Endpoint override. Defaults to https://storefront.glood.ai |
debug | boolean | No | Log request/response details to the console |
The second argument is the same GetSectionsParams as the hook, except pageUrl and locale are required outside the browser (there are no defaults on the server).
Server-Side Usage (Hydrogen Loader)
import { fetchRecommendationSections } from '@glood/hydrogen';
export async function loader({ request, params, context }) {
const recommendations = await fetchRecommendationSections(
{
apiKey: context.env.GLOOD_API_KEY,
myShopifyDomain: 'your-store.myshopify.com',
},
{
pageType: 'product_page',
pageUrl: request.url,
locale: 'en-US',
productId: params.productId,
},
).catch(() => null);
return { recommendations };
}
Errors — GloodApiError
Thrown on any non-2xx response:
class GloodApiError extends Error {
/** HTTP status code, e.g. 401 */
readonly status: number;
/** Parsed JSON error body, e.g. { error: 'Invalid authentication' } */
readonly body: unknown;
}
import { GloodApiError } from '@glood/hydrogen';
try {
await fetchRecommendationSections(options, params);
} catch (error) {
if (error instanceof GloodApiError && error.status === 401) {
// Invalid or mismatched API key
}
}
RecommendationsApp
The app instance registered via client.use(recommendations()). Retrieve it from the client for advanced usage:
import { RecommendationsApp } from '@glood/hydrogen';
const app = client.getApp('recommendations') as RecommendationsApp;
Methods
| Method | Returns | Description |
|---|
getSections(params) | Promise<SectionsResponse> | Fetch sections using the client’s credentials and the app’s endpoint |
trackRender(track) | void | Send glood:section:render |
trackView(track) | void | Send glood:section:view |
trackClick(track) | void | Send glood:section:click |
trackAddToCart(track) | void | Send glood:section:add_to_cart |
sendCustomEvent(name, track) | void | Generic form — send any glood:section:* event by name |
const data = await app.getSections({ pageType: 'home' });
app.trackClick({
section: '218966',
sectionServeId: data.sections[0].section_serve_id,
products: [{ productId: '9311227838783' }],
});
Attribution events respect the app’s pixel configuration: if pixel.enabled is false, they are not sent.
SectionTrack Object
Links an attribution event to the exact section render it came from:
| Attribute | Type | Required | Description |
|---|
section | string | No | Glood section id (as a string) |
sectionServeId | string | Recommended | section_serve_id from the sections response — ties the event to this specific render |
requestId | string | No | request_id from the sections response |
page | string | No | Page type where the interaction happened |
parent | { productId?, variantId? } | No | Context product (e.g. the product page the section rendered on) |
products | SectionTrackProduct[] | No | Products involved: { productId, variantId?, quantity? } |
const track: SectionTrack = {
section: '218966',
sectionServeId: '56a98d2d-a014-4dd7-ab2d-1a5191b84262',
requestId: '671778ec-8382-4d9e-9671-fb91daccf049',
page: 'product_page',
parent: { productId: '8977367564515' },
products: [
{ productId: '9311227838783', variantId: '48792371233087', quantity: 1 },
],
};
Response Shape — SectionsResponse
interface SectionsResponse {
/** Unique id for this request — pass to attribution events */
request_id: string;
/** Sections with full product data */
sections: RecommendationSection[];
/** Current product details (product pages), or null */
product: Record<string, any> | null;
/** Shopify storefront access token from the shop config */
token: string | null;
/** Shop configuration (currency, money format, integrations, ...) */
config: Record<string, any>;
/** Assigned A/B experience id — persisted to localStorage automatically */
experience: string | null;
/** Unique id for this visit */
visit_id: string | null;
}
See TypeScript Types for the full RecommendationSection and SectionProduct definitions.
Example Response
{
"request_id": "671778ec-8382-4d9e-9671-fb91daccf049",
"sections": [
{
"id": 218966,
"section_serve_id": "56a98d2d-a014-4dd7-ab2d-1a5191b84262",
"page_type": "home",
"experience_id": 27647,
"layout": "horizontal_grid",
"location": "MainContent",
"type": "bestsellers",
"position": 3,
"title": "Bestsellers",
"extra": {},
"discount_config": { "enabled": false },
"show_discount_label": false,
"translations": {},
"products": [
{
"product_id": 9311227838783,
"title": "The Collection Snowboard: Oxygen",
"handle": "the-collection-snowboard-oxygen",
"vendor": "Hydrogen Vendor",
"product_type": "snowboard",
"tags": "Premium, Snow",
"price": 1025,
"compare_at_price": null,
"image": { "url": "https://cdn.shopify.com/..." },
"options": [
{ "id": 1, "name": "Title", "values": ["Default Title"], "position": 1 }
],
"variants": [
{
"variant_id": 48792371233087,
"title": "Default Title",
"price": 1025,
"compare_at_price": null,
"sku": "",
"selected_options": [{ "name": "Title", "value": "Default Title" }]
}
],
"metafields": []
}
],
"cursor": null,
"hasMore": false
}
],
"product": null,
"token": "shpat_...",
"config": { "shop": { "currency": "USD", "money_format": "${{amount}}" } },
"experience": "27647",
"visit_id": "fc300769-ea40-43d9-8bf3-6b721913fea8"
}
See Also