Manual Recommendation Integration Copy page Copy link View Markdown Use this guide when your application requests and renders recommendations without the frontend SDK owning the request and rendering flow. This is the primary method for backend, mobile, and custom API integrations. This step requires a synchronized item catalog. Page and business event tracking should already be live before recommendation placements are enabled. Before you start Define modules, list names, page types, channels, and expected response fields. Review the Recommendation Request Model. Apply the identity and consent contract. Configure OAuth authentication for the Recommendations API. Request lifecycle Obtain and cache a valid bearer token on a trusted backend. Build the request from the agreed lists, page context, identity, histories, filters, and exclusions. Send the request to the environment-specific Recommendations API endpoint. Read the returned lists and preserve their attribution metadata. Render the selected items or apply the agreed fallback behavior. Send an impression for every recommendation shown and a click_on_recommendation for every recommendation clicked. For endpoint paths, exact fields, and response schemas, see the Recommendations API Reference. To show more than the initial results, follow pagination. Authentication and request domain Keep OAuth client credentials on a backend and send the resulting bearer token with authenticated recommendation requests. If you use a custom hostname, follow Custom Domain (CNAME) and replace the default request host consistently. Recommendation requests require the OAuth bearer token described above. Tracked events remain unauthenticated and must not reuse the recommendation Authorization header. Build the request The request shape is shared across integration methods. Use Recommendation Request Model for the behavior of lists, aliases, context, histories, exclusions, filters, and response enrichment. Ensure that: context_item and history item IDs exist in the synchronized catalog. context_item_type accompanies context_item. device_id and user_id follow the shared identity and consent rules. Each placement uses the agreed list_name, page type, and channel. Pagination To paginate a recommendation result, request a ranked list and return only its first items in the initial response. Then use the returned list_key to fetch further slices. Pagination must be enabled for your environment; contact Froomle if you need it. For example, send POST /{environment}/recommendations/requests with this list in the request body: { "list_name": "reco_list_001", "list_size": 5, "limit": 2 } Include it in the request’s lists array with the usual page and identity fields. list_size requests a ranked list of up to five items; limit returns up to two of them in the initial response, starting at rank 1. Save the list_key in that response’s list alongside the attribution fields described below. Fetch another slice with GET /{environment}/recommendations/lists?list_key={list_key}&offset=3&limit=2. Despite the route name, this is the pagination request: offset is the 1-based rank of the first item to return, and limit is the maximum number of items to return. offset is neither a page number nor the number of items to skip. Request offset limit Ranks returned if five items are available Initial POST — 2 1, 2 Next GET 3 2 3, 4 Following GET 5 2 5 GET from the beginning again 1 2 1, 2 Use each response’s item ranks and attribution when rendering and tracking that slice. The list may contain fewer items than requested, and its list_key is available only for a limited time. An unknown or expired key returns 404. See the Pagination endpoint reference for the complete request and response schema. Preserve response attribution Do not discard request_id, list_name, or an applicable user_group before rendering. The returned user_group can be required to choose what to render even when it must be omitted from the outbound event. Manual recommendation events always retain request and placement attribution; they include user_group only for externally assigned customer/control traffic. Your application owns rendering in this method. It must therefore retain enough state to associate every rendered item with the recommendation response that supplied it. Benchmarking Follow the shared A/B testing and benchmarking contract. When Froomle assigns the branch, use the returned user_group as the rendering authority. Do not echo that returned group in manually tracked events; Froomle assigns the version and group server-side. For customer-managed control traffic, pass the agreed externally assigned control group on the request and on its manually tracked recommendation events. For customer-managed treatment/Froomle traffic, omit the group from both. Do not invent or hard-code a request_id. Froomle-managed request example Send a standard request to POST /{environment}/recommendations/requests without user_group: { "device_id": "device-123", "user_id": "user-123", "page_type": "home", "lists": [ { "list_name": "home_page_trending", "list_size": 10 } ] } For a customer-vs-Froomle benchmark, a customer/control response can contain an empty recommendation list: { "request_id": "req-abc-123", "user_group": "customer", "lists": [ { "list_name": "home_page_trending", "items": [] } ] } Render the customer/control content because user_group resolves that branch, not merely because items is empty. Customer-managed request example For the customer/control branch, pass the group name agreed with Froomle: { "device_id": "device-123", "user_id": "user-123", "page_type": "home", "user_group": "customer", "lists": [ { "list_name": "home_page_trending", "list_size": 10 } ] } For the treatment/Froomle branch, send the same request without user_group so normal Froomle version resolution applies. Hybrid browser tracking A backend may fetch recommendations while the frontend SDK tracks browser events. For this supported advanced pattern, preserve the returned attribution metadata in the rendered DOM as described in Backend-Fetched Recommendations and SDK Event Tracking. Failure handling Set an application-level timeout and ensure recommendation failures do not block the main page or application flow. Handle empty responses and request failures using the agreed fallback strategy. See Resilience and fallbacks for production patterns. Related topics Manual event integration Modules and placements Filters and constraints QA and monitoring