Skip to main content
A user profile is the plain-text string you send with each search request to personalize results. Meilisearch does not yet generate user profiles automatically. You build them on your backend by aggregating data about each user (potentially using analytics events), then pass the profile as a string in the personalize search parameter. This guide covers strategies for collecting user signals, structuring them into a profile string, and sending that profile with search requests.

Strategies for building user context

Browsing history

Track which pages, categories, or items a user views. Summarize their recent activity into preference signals. Raw data: User viewed 12 electronics products, 3 kitchen items, and 1 clothing item in the last 7 days. Context string: "Interested in electronics and gadgets, occasionally browses kitchen appliances."

Purchase history

Analyze past purchases to identify brand loyalty, price ranges, and product categories. Raw data: User bought 4 Samsung products and 2 Apple products in the last 6 months, average order value $85. Context string: "Frequently buys Samsung and Apple electronics, mid-range budget around $85 per item."

Explicit preferences

Use data from user profiles, preference surveys, or onboarding flows. Raw data: User selected “Running” and “Yoga” as interests, set size to “Medium”. Context string: "Interested in running and yoga gear, prefers size Medium."

Demographic and contextual data

Incorporate location, language, or seasonal context when relevant. Raw data: User is located in Montreal, Canada. Current season is winter. Context string: "Based in Montreal, Canada. Currently winter season, likely interested in cold-weather products."

Structure the context string

Combine multiple signals into a single profile string. The re-ranking model works best with affirmatively stated preferences. Focus on what the user likes rather than what they dislike. Good: "Prefers organic food, shops for family of four, budget-conscious, favors local brands." Less effective: "Does not like expensive items, never buys imported goods." Keep the context string concise (1 to 3 sentences). Include the most relevant and recent signals. There is no hard maximum length, but longer context strings increase latency and cost without improving results. Overly long descriptions dilute the most important signals.

When to regenerate context

You build and send the user context string yourself, which gives you full flexibility over when to update it. The context is not stored by Meilisearch. It is sent as a parameter with each search request, so you can change it at any time. Common strategies:
  • Per-session: regenerate the context string when a user starts a new session. This balances freshness with compute cost.
  • After key actions: update the context immediately after a purchase, a category switch, or an explicit preference change. This ensures the next search reflects the latest intent.
  • Per-request: for maximum personalization, recompute the context before every search. This is useful if the context changes rapidly (for example, a user browsing multiple categories in quick succession).
  • Asynchronous batch: precompute context strings for all users on a schedule (daily, hourly) and cache them. This works well for large user bases where per-request generation would be too expensive.
Since you control the context string, you can mix strategies. For example, use a cached daily profile as a baseline and enrich it with the current session’s browsing data before each request.

Send context with a search request

Pass the user profile in the personalize parameter of your search request. The personalize object must contain a userContext field with your profile string:
curl \
  -X POST 'MEILISEARCH_URL/indexes/products/search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "q": "running shoes",
    "personalize": {
      "userContext": "Prefers lightweight trail running shoes from Salomon or Hoka, mid-range budget, runs 30 miles per week."
    }
  }'
Meilisearch retrieves results matching the query, then re-ranks them based on the user profile you provided. Documents that better match the profile appear higher in the results.

Example: building context from a user profile

Here is a simplified backend example that constructs a context string from stored user data:
function buildUserContext(user) {
  const parts = [];

  if (user.favoriteCategories?.length > 0) {
    parts.push(`Interested in ${user.favoriteCategories.join(', ')}.`);
  }

  if (user.favoriteBrands?.length > 0) {
    parts.push(`Prefers brands like ${user.favoriteBrands.join(', ')}.`);
  }

  if (user.averageOrderValue) {
    const budget = user.averageOrderValue < 50 ? 'budget-conscious'
      : user.averageOrderValue < 150 ? 'mid-range budget'
      : 'premium shopper';
    parts.push(`Typically a ${budget}.`);
  }

  if (user.location) {
    parts.push(`Based in ${user.location}.`);
  }

  return parts.join(' ');
}

// Result: "Interested in electronics, fitness gear. Prefers brands like Samsung, Nike. Typically a mid-range budget. Based in Berlin, Germany."

Next steps

Getting started with personalization

Enable personalization and perform your first personalized search

Personalization overview

Understand how search personalization works

Personalize ecommerce search

End-to-end ecommerce personalization example