API
API reference for the Product Listing Pages Engine
PLP API — Design Overview
Purpose
The PLP API powers collection-based product listing pages while supporting:
- Accurate attribution across views, clicks, and conversions
- Flexible retrieval via pagination and infinite scroll
- Frontend-driven execution with backend-managed intelligence
- Collection-governed behavior with merchandising, pinning, and banner injection
Core Endpoints
PLP runtime behavior mirrors Malachyte Search's endpoint pattern, but is collection-governed and routed through PLP-specific endpoints.
| Endpoint | Description |
|---|---|
POST /v1/plp | Returns the ranked product grid for a Shopify collection |
POST /v1/plp/filter | Applies filters to an existing PLP result set |
POST /v1/plp/sort | Applies a sort order to an existing PLP result set |
POST /v1/plp
Returns the ranked product grid for a Shopify collection, including pinning, banner injection, and ranking layers.
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
collection_id | string | Yes | Shopify Collection ID |
strategy_name | string | Yes | Always "plp" |
k | number | Conditionally | Required for first request or large-k mode |
from_portal | boolean | Yes | Must be false for end-user traffic |
log_response | boolean | Yes | Must be true for attribution |
visitor_id | string (UUID) | Yes | Persistent identifier for analytics |
Example Request
POST /v1/plp
{
"collection_id": "gid://shopify/Collection/123456789",
"strategy_name": "plp",
"k": 24,
"from_portal": false,
"log_response": true,
"visitor_id": "3e92322a-d473-4c81-ab80-82dba7c31e65"
}Response
The response includes:
- Ranked products with merchandising rules applied
- Pinned products in their designated positions
- Injected banners at their configured slots
- Available filters from
allowed_filter_attributes - Pagination metadata for subsequent requests
Pagination & Infinite Scroll
PLPs support pagination and infinite scroll using the same pattern as Search.
First Request
Option A — Payload-driven
- Include
kin the request body - Do not include query parameters in the URL
Option B — Query-driven
- Include
pageandsizein the query string - Do not include
kin the request body
Subsequent Requests
For infinite scroll or pagination:
POST /v1/plp?page=2&size=24
{
"collection_id": "gid://shopify/Collection/123456789",
"strategy_name": "plp",
"from_portal": false,
"log_response": true,
"visitor_id": "3e92322a-d473-4c81-ab80-82dba7c31e65"
}[!IMPORTANT] Subsequent page requests retrieve additional slices of the same shaped dataset. Pinning, banners, and ranking are already applied and remain consistent across pages.
POST /v1/plp/filter
Applies filters to an existing PLP result set. Mirrors /v1/search/filter but is collection-scoped and whitelist-enforced.
Request Fields
| Field | Type | Description |
|---|---|---|
results | array | Current PLP result set (or opaque reference) |
filters | object | Filters to apply |
Behavior
- Filters are validated against
allowed_filter_attributes(post-reconciliation) - Filter application occurs within the bounds of the collection dataset
- Invalid filters (not in whitelist) are rejected
Example Request
POST /v1/plp/filter
{
"results": "plp_result_reference_id",
"filters": {
"color": ["Black", "White"],
"size": ["M", "L"]
}
}POST /v1/plp/sort
Applies a sort order to an existing PLP result set. Mirrors /v1/search/sort.
Supported Sort Orders
| Value | Description |
|---|---|
RECOMMENDED | Default relevance/ranking score |
A_Z | Alphabetical (A to Z) |
Z_A | Alphabetical (Z to A) |
HIGH_LOW | Price: High to Low |
LOW_HIGH | Price: Low to High |
NEW_OLD | Newest to Oldest |
OLD_NEW | Oldest to Newest |
Example Request
POST /v1/plp/sort
{
"results": "plp_result_reference_id",
"sort": "LOW_HIGH"
}[!NOTE] Sorting must not override dataset-shaping rules (Hide / Only Show) nor explicit positional controls (Pinning). Pinned products remain in position regardless of sort order.
Filter API (Portal)
Display (Read)
GET /collections/:id/filters
Returns candidate attributes and allowed filter attributes for a collection.
Steps:
- Compute
candidateAttributesfrom collection products - Read
allowed_filter_attributes - Reconcile (remove dead attributes)
- Return both arrays
Response:
{
"candidateAttributes": ["color", "size", "material", "price", "vendor"],
"allowed_filter_attributes": ["color", "size", "price"]
}Edit (Write)
PUT /collections/:id/filters
Updates the allowed filter attributes for a collection.
Steps:
- Compute
candidateAttributes - Filter submitted array against candidates
- Save as new
allowed_filter_attributes - Return updated array
Attribution & Identity
[!TIP] Data Integrity & Tracking These fields are essential for measuring PLP performance and ROI.
log_response = true— Enables full attribution tracking across views, clicks, and conversionsvisitor_id— A persistent identifier (UUID) ensuring consistent identity and accurate analytics across sessions