Documentation
Feedback
Guides
VTEX IO Apps

VTEX IO Apps
Data Model
vtex.search-session
Version: 0.8.0
Latest version: 0.8.0

vtex.search-session is a thin transform service that converts shopper-side session inputs into the storefront search.facets value consumed by Intelligent Search. It owns no persistent data.

Session namespace contract

The contract is declared in vtex.session/configuration.json:


_19
{
_19
"search": {
_19
"input": {
_19
"public": [
_19
"facets",
_19
"postalCode",
_19
"geoCoordinates",
_19
"country",
_19
"region_id"
_19
],
_19
"profile": ["email", "isAuthenticated"],
_19
"storefront-permissions": ["organization"]
_19
},
_19
"output": {
_19
"search": ["facets"],
_19
"public": ["postalCode", "country", "geoCoordinates"]
_19
}
_19
}
_19
}

Inputs are read by transform from the request body (it is called by the VTEX session runtime). Outputs are written back to the session in the search.facets.value and public.* slots.

Request/response shape

POST /_v/search/session/transform/ body:


_16
type Body = {
_16
public: {
_16
facets: { value: string } // "key=value;..." (mixed)
_16
region_id: { value: string } // base64 "vtex:BRA:0000000"
_16
postalCode: { value: string }
_16
country: { value: string }
_16
geoCoordinates: { value: string } // "lon,lat" (typo from checkout API)
_16
}
_16
'storefront-permissions': {
_16
organization: { value: string } // B2B ACL key
_16
}
_16
profile: {
_16
email: { value: string }
_16
isAuthenticated: { value: string } // 'true' | 'false'
_16
}
_16
}

Response (in ctx.response.body):


_11
{
_11
search: {
_11
facets: { value: string } // serialized via stringifyFacets()
_11
},
_11
public: {
_11
// Only set when region_id is the source of truth:
_11
postalCode?: { value: string }
_11
country?: { value: string }
_11
geoCoordinates?: { value: string }
_11
}
_11
}

Transform pipeline


_15
POST /_v/search/session/transform/
_15
├─► checkProviderImplementation
_15
│ └─ ctx.hasImplementationApp = apps has `vtex.search-segment-graphql@0.1.1`
_15
└─► transform
_15
├─ parseFacetsString(public.facets.value) → SelectedFacet[] (excludes delivery-promises keys)
_15
├─ if hasImplementationApp:
_15
│ └─ graphqlServer.query(searchSegmentQuery, { userEmail, isAuthenticated, selectedFacets })
_15
│ → selectedFacetsResult (overrides default facets)
_15
├─ if storefront-permissions.organization: append { key: 'accesscontrollist', value: organization }
_15
├─ deliveryPromises(ctx, body):
_15
│ ├─ Source of truth priority: public > facets (zip-code, country, coordinates)
_15
│ ├─ Fallback: parse region_id (base64 "vtex:BRA:0000000") + checkout.getGeocoordinates
_15
│ └─ logisticShipping.deliveryZones / pickupPoints → { deliveryZonesHash, pickupPointsHash }
_15
├─ Append deliveryZonesHash / pickupPointsHash to selectedFacetsResult
_15
└─ Respond { search.facets: stringifyFacets(...), public: { ...region } }

Facets wire format

The facets string flows through three pure utilities in node/utils.ts:

FunctionRole
parseFacetsString(str)Splits "k=v;..." into SelectedFacet[], excluding delivery-promises keys (zip-code, country, coordinates).
parseDeliveryPromisesInput(str)Same input, only keeps delivery-promises keys → Record<string, string>.
stringifyFacets(facets)Serializes SelectedFacet[] back to "k=v;k=v;" (trailing ;).

Outbound clients

ClientFileTalks toPolicy
graphqlServernode/clients/graphqlServer.tsvtex.graphql-server:resolve-graphql (in-account GraphQL)vtex.graphql-server:resolve-graphql
logisticShippingnode/clients/logisticShipping.tsportal.vtexcommercestable.com.br/api/logistics-shipping/*outbound-access (declared in manifest.json)
checkoutnode/clients/checkout.tsportal.vtexcommercestable.com.br/api/checkout/pub/* (geocoordinates resolution)outbound-access

@vtex/api default options: retries: 2, timeout: 6000ms (MEDIUM_TIMEOUT_MS).

Test surface

FileCovers
node/__tests__/utils.test.tsparseFacetsString, parseDeliveryPromisesInput, stringifyFacets — wire-format contract
node/__tests__/trasnform.test.tsLegacy / stale — references an older transform shape that mutated body.public.facets.value in place. Current transform returns a new shape via ctx.response.body. Slated for rewrite.
See also
Vtex.search Session
VTEX IO Apps
VTEX App Store
VTEX IO Apps
Was this helpful?