Customizations

1. Custom Response Processing

Override the fetcher method to customize response processing:

// In a code.js block
if (searchClient && searchClient.fetcher) {
  const originalFetcher = searchClient.fetcher.bind(searchClient)

  searchClient.fetcher = async function (params) {
    const result = await originalFetcher(params)

    // Custom processing
    result.products = result.products.map((product) => ({
      ...product,
      customField: "customValue",
    }))

    return result
  }
}

2. Custom Filter Processing

Override filter methods to add custom logic:

// Custom filter application
if (searchClient) {
  const originalSetFilter = searchClient.setFilter.bind(searchClient)

  searchClient.setFilter = async function (filter) {
    // Add custom pre-processing
    if (filter.key === "price") {
      filter.value = formatPrice(filter.value)
    }

    return originalSetFilter(filter)
  }
}

3. Custom Sort Options

Modify sort option resolution:

if (searchClient) {
  const originalResolveSortOptions =
    searchClient.resolveSortOptions?.bind(searchClient)

  searchClient.resolveSortOptions = function (label) {
    // Custom sort mapping
    const customSortMap = {
      popularity: "custom_popularity_score",
      newest: "created_at_desc",
    }

    return customSortMap[label] || originalResolveSortOptions?.(label) || label
  }
}

Integration-Specific Customizations

Algolia

Search Parameters Customization

// Override search parameters to add custom filters
searchClient.setSearchParametersOnHelper = function (searchParameters) {
  const existingFilters = searchParameters.filters
  const customFilter = "(inStock:true) AND isOnline:true AND (NOT isNfs:true)"

  searchParameters.filters = existingFilters
    ? `${existingFilters} AND ${customFilter}`
    : customFilter

  return searchParameters
}

Query and Index Management

// Set search query
searchClient.setQueryOnHelper("search term")

// Set search index for sorting
searchClient.setIndexOnHelper("products_price_asc")

// Override rule contexts for custom merchandising behavior
searchClient.setRuleContextsOnHelper = function () {
  // Access the helper via this.helper
  if (this.collectionHandle) {
    const customRuleContext = `custom-${this.collectionHandle}`
    this.helper.setState(
      this.helper.state.setQueryParameter("ruleContexts", [customRuleContext])
    )
  }
}

Note: setRuleContextsOnHelper is a method to override, not just invoke. It will replace the default rule context behavior.

Access Algolia Helper Directly

// Access Algolia-specific helper for advanced customizations
// Modify search parameters directly
searchClient.helper.setState(
  searchClient.helper.state.setQueryParameter("analyticsTags", ["custom-tag"])
)

// Add custom facet configuration
searchClient.helper.setState(
  searchClient.helper.state.addFacet("custom_attribute")
)

Important: Direct helper access is best used within overridden search client methods (like setRuleContextsOnHelper, or applyBaseParamsToIntegration). Accessing the helper outside of these methods can lead to unintended results, as the search client may reset or override your changes during its internal operations. Always prefer method overrides when possible for more predictable behavior.

Response Formatting

// Custom response formatting for Algolia results
searchClient.formatResponse = function ({ results, isFacetsOnly }) {
  // Custom logic here
  return {
    products: results.hits,
    page: results.page,
    totalPages: results.nbPages,
    totalProducts: results.nbHits,
    hasMore: results.page + 1 < results.nbPages,
    nextPage: results.page + 1 < results.nbPages ? results.page + 1 : null,
    // Add custom fields
    customField: "custom value",
    facets: results.facets,
  }
}

SearchSpring Client

Request Parameters

// Customize request parameters
if (searchClient.buildRequestParams) {
  const original = searchClient.buildRequestParams.bind(searchClient)

  searchClient.buildRequestParams = function (params) {
    const result = original(params)
    // Add custom parameters
    result.append("customParam", "customValue")
    result.append("boost", "featured:1.5")
    return result
  }
}

Response Formatting

// Custom response formatting for SearchSpring
if (searchClient.formatSearchSpringResponse) {
  searchClient.formatSearchSpringResponse = function (response) {
    // Return null to use default formatting, or return custom response
    return {
      products: response.results,
      page: response.pagination.currentPage - 1,
      totalPages: response.pagination.totalPages,
      totalProducts: response.pagination.totalResults,
      hasMore: response.pagination.currentPage < response.pagination.totalPages,
      nextPage:
        response.pagination.currentPage < response.pagination.totalPages
          ? response.pagination.currentPage
          : null,
      // Add custom metadata
      searchMetadata: response.merchandising || {},
    }
  }
}

URL Building

// Custom URL building for SearchSpring requests
if (searchClient.buildSearchSpringUrl) {
  searchClient.buildSearchSpringUrl = function (baseUrl, params) {
    // Add custom query parameters or modify URL structure
    return `${baseUrl}?${params.toString()}&customParam=value&tracking=enabled`
  }
}

Merchandising Rules

// Apply custom merchandising rules
if (searchClient.applyMerchandisingRules) {
  searchClient.applyMerchandisingRules = function (params) {
    params.append("boost", "featured:true")
    params.append("merchandising", "seasonal_promotion")
    params.append("pin", "productId:12345:1") // Pin product to position 1
  }
}

Custom Headers

// Set custom headers for SearchSpring requests
if (searchClient.setCustomHeaders) {
  searchClient.setCustomHeaders({
    "X-Custom-Header": "value",
    "X-Store-Context": "premium",
    Authorization: "Bearer token",
  })
}

Nosto Search Client

Custom Rules and Segments

// Set custom rules for Nosto search
if (searchClient.setCustomRules) {
  searchClient.setCustomRules([
    {
      field: "category",
      operation: "equals",
      value: "featured",
    },
    {
      field: "price",
      operation: "range",
      value: { min: 10, max: 100 },
    },
  ])
}

// Set user segments for personalization
if (searchClient.setSegments) {
  searchClient.setSegments([
    "premium_customers",
    "mobile_users",
    "returning_visitors",
  ])
}

// Set session parameters for tracking
if (searchClient.setSessionParams) {
  searchClient.setSessionParams({
    userId: "user123",
    sessionId: "session456",
    visitorId: "visitor789",
  })
}

Request Headers

// Set custom headers for Nosto requests
if (searchClient.setRequestHeaders) {
  searchClient.setRequestHeaders({
    "X-Custom-Header": "value",
    "X-User-Segment": "premium",
    "X-Device-Type": "mobile",
  })
}

GraphQL Operation Name

// Set GraphQL operation name for Nosto
if (searchClient.setOperationName) {
  searchClient.setOperationName("CustomProductSearch")
}

Request Parameters

// Customize request parameters for Nosto
if (searchClient.buildRequestParams) {
  const original = searchClient.buildRequestParams.bind(searchClient)

  searchClient.buildRequestParams = function (baseParams) {
    const params = original(baseParams)
    // Add custom logic
    params.customField = "customValue"
    params.personalization = true
    return params
  }
}

Response Formatting

// Custom response formatting for Nosto
if (searchClient.formatNostoResponse) {
  searchClient.formatNostoResponse = function (result) {
    // Return null to use default formatting, or return custom response
    const hits = result.search.products.hits || []
    const totalProducts = result.search.products.total || 0

    return {
      products: hits, // Will be processed through fetchProductsByNostoHits
      page: 0,
      totalPages: Math.ceil(totalProducts / this.productsPerPage),
      totalProducts,
      hasMore: hits.length === this.productsPerPage,
      nextPage: hits.length === this.productsPerPage ? 1 : null,
      // Add Nosto-specific metadata
      recommendations: result.recommendations || [],
      segments: result.segments || [],
    }
  }
}