> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customize search results by device

> Learn how to customize your search results based on whether your user is on a mobile or desktop device.

export const Records = () => <Tooltip tip="A record is a searchable object in an Algolia index. Each record consists of named attributes." cta="Algolia records" href="/doc/guides/sending-and-managing-data/prepare-your-data#algolia-records">
    records
  </Tooltip>;

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

export const Filter = () => <Tooltip tip="A filter is a condition that limits which records Algolia returns. Filters often use one or more facet-value pairs, such as brand:Apple AND color:red. You can also filter by numeric values, dates, tags, booleans, or geographic constraints." cta="Filtering" href="/doc/guides/managing-results/refine-results/faceting">
    filter
  </Tooltip>;

Search needs to be flexible.
Depending on the user's context, results can vary.
For example, because some products are more likely to be bought or viewed from phones than desktops, you may want to promote items based on the user's device.

To do this:

1. Identify your user's device.
2. Assign a `mobile` context when users search from mobile devices. A context is a string passed as a search parameter to InstantSearch or one of the Algolia API clients.
3. Create a contextual rule that acts on the `mobile` context.

<Note>
  To help understand user behavior across devices, pair your device-specific experience with analytics.
  You can even use the same context string to tag search queries for analytics.
  These [`analyticsTags`](/doc/guides/search-analytics/guides/segments) help you group search analytics into different segments.
</Note>

## Example scenario

Suppose you work for a movie database company.
Research shows that mobile users, unlike desktop users, tend to see a film in theaters after it has appeared in their search results.
To capitalize on this, you partner with a movie theater chain and decide to promote newly released movies to your mobile users.

The <Records /> in your Algolia <Index /> include a `release_date` attribute,
in [Unix timestamp](https://www.unixtimestamp.com/) format, this is useful for identifying newly released movies.

```json JSON icon=braces theme={"system"}
{
  "title": "Fargo",
  "year": 1996,
  "director": "Joel Coen",
  "release_date": 841795200,
  "rating": 93
}
```

By creating a mobile context and contextual rules,
you can promote recent movies to mobile users.

## Identify your user's device

Before assigning a mobile context to searches,
write a function that detects what device the app is running on,
and return "desktop" or "mobile" depending on what it finds:

```js JavaScript icon=code theme={"system"}
const getPlatform = () => {
  // const isMobile = ...
  // Your logic to determine whether a user is on a mobile or desktop device
  return isMobile ? "mobile" : "desktop";
};
```

## Assign context

You can assign context with InstantSearch or one of the Algolia API clients.

### Assign context with InstantSearch

Set the user's device context at the beginning of their search session by adding it to the `searchParameters` setting of your InstantSearch instance [during initialization](/doc/api-reference/widgets/instantsearch/js).

<CodeGroup>
  ```js JavaScript theme={"system"}
  const platformTag = getPlatform();

  instantsearch.widgets.configure({
    ruleContexts: [platformTag],
  });
  ```

  ```swift Swift theme={"system"}
  let platform = getPlatform()

  let searcher = HitsSearcher(appId: "YourAppId", apiKey: "ALGOLIA_API_KEY", indexName: "YourIndexName")

  searcher.request.query.ruleContexts = [platform]
  ```

  ```jsx React theme={"system"}
  import { Configure } from 'react-instantsearch';

  const platformTag = getPlatform()

  <Configure
    ruleContexts=[platformTag]
  />
  ```

  ```vue Vue theme={"system"}
  <script>
  export default {
    data() {
      return {
        ruleContexts: getPlatform(),
      };
    },
  };
  </script>
  ```

  ```kotlin Android theme={"system"}
  val platform: String = getPlatform()
  val query = query {
      ruleContexts {
          +platform
      }
  }

  val searcher = HitsSearcher(movies, query)
  ```
</CodeGroup>

### Assign context with an API client

To run the code examples on this page, [install the latest API client](/doc/libraries/sdk/install).

Pass the user's device context as a search parameter whenever you search your index.

<CodeGroup>
  ```cs C# theme={"system"}
  namespace Algolia;

  using System;
  using System.Collections.Generic;
  using System.Net.Http;
  using System.Text.Json;
  using Algolia.Search.Clients;
  using Algolia.Search.Http;
  using Algolia.Search.Models.Search;

  class SearchWithRuleContexts
  {
    private static string GetPlatformTag()
    {
      return ""; // Implement your logic here
    }

    async Task Main(string[] args)
    {
      var client = new SearchClient(new SearchConfig("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY"));
      var platformTag = GetPlatformTag();
      var searchParams = new SearchParams(
        new SearchParamsObject { Query = "SEARCH_QUERY", RuleContexts = [platformTag] }
      );

      await client.SearchSingleIndexAsync<Hit>("INDEX_NAME", searchParams);
    }
  }

  ```

  ```dart Dart theme={"system"}
  import 'package:algolia_client_search/algolia_client_search.dart';

  String getPlatformTag() {
    return ""; // Implement your logic here
  }

  void searchWithRuleContexts() async {
    final client =
        SearchClient(appId: 'ALGOLIA_APPLICATION_ID', apiKey: 'ALGOLIA_API_KEY');

    final platformTag = getPlatformTag();
    final searchParams = SearchParamsObject(
        query: "SEARCH_QUERY", ruleContexts: [platformTag]);

    await client.searchSingleIndex(
      indexName: "INDEX_NAME",
      searchParams: searchParams,
    );
  }

  ```

  ```go Go theme={"system"}
  package main

  import (
  	"github.com/algolia/algoliasearch-client-go/v4/algolia/search"
  )

  func getPlatformTag() (string, error) {
  	return "", nil // Implement your logic here
  }

  func searchWithRuleContexts() {
  	client, err := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  	if err != nil {
  		// The client can fail to initialize if you pass an invalid parameter.
  		panic(err)
  	}

  	platformTag, err := getPlatformTag()
  	if err != nil {
  		panic(err)
  	}

  	searchParams := search.SearchParamsObjectAsSearchParams(
  		search.NewSearchParamsObject().
  			SetQuery("SEARCH_QUERY").
  			SetRuleContexts([]string{platformTag}),
  	)

  	_, err = client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
  		"INDEX_NAME").WithSearchParams(searchParams))
  	if err != nil {
  		panic(err)
  	}
  }

  ```

  ```java Java theme={"system"}
  package com.algolia;

  import com.algolia.api.SearchClient;
  import com.algolia.config.*;
  import com.algolia.model.search.*;
  import java.util.List;

  public class searchWithRuleContexts {

    private static String getPlatformTag() {
      return ""; // Implement your logic here
    }

    public static void main(String[] args) throws Exception {
      try (SearchClient client = new SearchClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")) {
        String platformTag = getPlatformTag();
        SearchParams searchParams = new SearchParamsObject().setQuery("SEARCH_QUERY").setRuleContexts(List.of(platformTag));

        client.searchSingleIndex("INDEX_NAME", searchParams, Hit.class);
      } catch (Exception e) {
        System.out.println("An error occurred: " + e.getMessage());
      }
    }
  }

  ```

  ```js JavaScript theme={"system"}
  import { algoliasearch } from 'algoliasearch';

  import type { SearchParams } from 'algoliasearch';

  const getPlatformTag = () => {
    return ''; // Implement your logic here
  };

  const client = algoliasearch('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY');

  const platformTag = getPlatformTag();
  const searchParams: SearchParams = {
    query: 'SEARCH_QUERY',
    ruleContexts: [platformTag],
  };

  await client.searchSingleIndex({ indexName: 'indexName', searchParams: searchParams });

  ```

  ```kotlin Kotlin theme={"system"}
  import com.algolia.client.api.SearchClient
  import com.algolia.client.configuration.*
  import com.algolia.client.extensions.*
  import com.algolia.client.model.search.*
  import com.algolia.client.transport.*

  val getPlatformTag: () -> String = {
    "" // Implement your logic here
  }

  suspend fun searchWithRuleContexts() {
    val client = SearchClient(appId = "ALGOLIA_APPLICATION_ID", apiKey = "ALGOLIA_API_KEY")

    val platformTag = getPlatformTag()
    val searchParams =
      SearchParamsObject(query = "SEARCH_QUERY", ruleContexts = listOf(platformTag))

    client.searchSingleIndex(indexName = "INDEX_NAME", searchParams = searchParams)
  }

  ```

  ```php PHP theme={"system"}
  <?php

  require __DIR__.'/../vendor/autoload.php';
  use Algolia\AlgoliaSearch\Api\SearchClient;
  use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject;

  $getPlatformTag = function (): string {
      // Implement your logic here
      return '';
  };

  $client = SearchClient::create('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY');

  // get the buyer account information
  $platformTag = $getPlatformTag();
  $searchParams = (new SearchParamsObject())
      ->setQuery('SEARCH_QUERY')
      ->setRuleContexts([$platformTag])
  ;

  $client->searchSingleIndex(
      'INDEX_NAME',
      $searchParams,
  );

  ```

  ```python Python theme={"system"}
  from algoliasearch.search.client import SearchClientSync

  from algoliasearch.search.models.search_params import SearchParams


  def _get_platform_tag() -> str:
      # Implement your logic here
      return ""


  _client = SearchClientSync("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")


  # get the buyer account information
  platform_tag = _get_platform_tag()
  search_params = SearchParams(
      query="SEARCH_QUERY",
      rule_contexts=[platform_tag],
  )

  _client.search_single_index(
      index_name="INDEX_NAME",
      search_params=search_params,
  )

  ```

  ```ruby Ruby theme={"system"}
  require "algolia"

  def get_platform_tag
    # Implement your logic here
    ""
  end

  client = Algolia::SearchClient.create("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")

  # get the buyer account information
  platform_tag = get_platform_tag
  search_params = Algolia::Search::SearchParamsObject.new(
    query: "SEARCH_QUERY",
    rule_contexts: [platform_tag]
  )

  client.search_single_index("INDEX_NAME", search_params)

  ```

  ```scala Scala theme={"system"}
  import scala.concurrent.Future
  import scala.concurrent.ExecutionContext.Implicits.global

  import algoliasearch.api.SearchClient
  import algoliasearch.config.*
  import algoliasearch.extension.SearchClientExtensions
  import algoliasearch.search.SearchParamsObject

  val getPlatformTag: String = {
    "" // Implement your logic here
  }

  def searchWithRuleContexts(): Future[Unit] = {
    val client = SearchClient(appId = "ALGOLIA_APPLICATION_ID", apiKey = "ALGOLIA_API_KEY")

    val platformTag = getPlatformTag
    val searchParams = SearchParamsObject(
      query = Some("SEARCH_QUERY"),
      ruleContexts = Some(Seq(platformTag))
    )

    client
      .searchSingleIndex(
        indexName = "INDEX_NAME",
        searchParams = Some(searchParams)
      )
      .map { response =>
        println(response)
      }
      .recover { case ex: Exception =>
        println(s"An error occurred: ${ex.getMessage}")
      }
  }

  ```

  ```swift Swift theme={"system"}
  import Foundation
  #if os(Linux) // For linux interop
      import FoundationNetworking
  #endif

  import AlgoliaCore
  import AlgoliaSearch

  let getPlatformTag = { "" } // Implement your logic here

  func searchWithRuleContexts() async throws {
      let client = try SearchClient(appID: "ALGOLIA_APPLICATION_ID", apiKey: "ALGOLIA_API_KEY")

      let platformTag = getPlatformTag()
      let searchParams = SearchSearchParams.searchSearchParamsObject(
          SearchSearchParamsObject(query: "SEARCH_QUERY", ruleContexts: [platformTag])
      )

      let response: SearchResponse<Hit> = try await client.searchSingleIndex(
          indexName: "INDEX_NAME",
          searchParams: searchParams
      )
      print(response)
  }

  ```
</CodeGroup>

## Create a contextual rule

You can create a mobile contextual rule with an API client or from the Algolia dashboard.

### Create a contextual rule with an API client

Use the [`saveRule`](/doc/libraries/sdk/methods/search/save-rule) method to create a context-dependent rule.
For example, to promote movies released after January 1, 2020, for mobile users:

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.SaveRuleAsync(
    "INDEX_NAME",
    "a-rule-id",
    new Rule
    {
      ObjectID = "a-rule-id",
      Conditions = new List<Condition> { new Condition { Context = "mobile" } },
      Consequence = new Consequence
      {
        Params = new ConsequenceParams { Filters = "release_date >= 1577836800" },
      },
    }
  );
  ```

  ```dart Dart theme={"system"}
  final response = await client.saveRule(
    indexName: "INDEX_NAME",
    objectID: "a-rule-id",
    rule: Rule(
      objectID: "a-rule-id",
      conditions: [
        Condition(
          context: "mobile",
        ),
      ],
      consequence: Consequence(
        params: ConsequenceParams(
          filters: "release_date >= 1577836800",
        ),
      ),
    ),
  );
  ```

  ```go Go theme={"system"}
  response, err := client.SaveRule(client.NewApiSaveRuleRequest(
    "INDEX_NAME", "a-rule-id",
    search.NewEmptyRule().SetObjectID("a-rule-id").SetConditions(
      []search.Condition{*search.NewEmptyCondition().SetContext("mobile")}).SetConsequence(
      search.NewEmptyConsequence().SetParams(
        search.NewEmptyConsequenceParams().SetFilters("release_date >= 1577836800")))))
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  UpdatedAtResponse response = client.saveRule(
    "INDEX_NAME",
    "a-rule-id",
    new Rule()
      .setObjectID("a-rule-id")
      .setConditions(Arrays.asList(new Condition().setContext("mobile")))
      .setConsequence(new Consequence().setParams(new ConsequenceParams().setFilters("release_date >= 1577836800")))
  );
  ```

  ```js JavaScript theme={"system"}
  const response = await client.saveRule({
    indexName: 'indexName',
    objectID: 'a-rule-id',
    rule: {
      objectID: 'a-rule-id',
      conditions: [{ context: 'mobile' }],
      consequence: { params: { filters: 'release_date >= 1577836800' } },
    },
  });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.saveRule(
      indexName = "INDEX_NAME",
      objectID = "a-rule-id",
      rule =
        Rule(
          objectID = "a-rule-id",
          conditions = listOf(Condition(context = "mobile")),
          consequence =
            Consequence(params = ConsequenceParams(filters = "release_date >= 1577836800")),
        ),
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->saveRule(
      'INDEX_NAME',
      'a-rule-id',
      ['objectID' => 'a-rule-id',
          'conditions' => [
              ['context' => 'mobile',
              ],
          ],
          'consequence' => ['params' => ['filters' => 'release_date >= 1577836800',
          ],
          ],
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.save_rule(
      index_name="INDEX_NAME",
      object_id="a-rule-id",
      rule={
          "objectID": "a-rule-id",
          "conditions": [
              {
                  "context": "mobile",
              },
          ],
          "consequence": {
              "params": {
                  "filters": "release_date >= 1577836800",
              },
          },
      },
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.save_rule(
    "INDEX_NAME",
    "a-rule-id",
    Algolia::Search::Rule.new(
      algolia_object_id: "a-rule-id",
      conditions: [Algolia::Search::Condition.new(context: "mobile")],
      consequence: Algolia::Search::Consequence.new(
        params: Algolia::Search::ConsequenceParams.new(filters: "release_date >= 1577836800")
      )
    )
  )
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.saveRule(
      indexName = "INDEX_NAME",
      objectID = "a-rule-id",
      rule = Rule(
        objectID = "a-rule-id",
        conditions = Some(
          Seq(
            Condition(
              context = Some("mobile")
            )
          )
        ),
        consequence = Consequence(
          params = Some(
            ConsequenceParams(
              filters = Some("release_date >= 1577836800")
            )
          )
        )
      )
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.saveRule(
      indexName: "INDEX_NAME",
      objectID: "a-rule-id",
      rule: Rule(
          objectID: "a-rule-id",
          conditions: [SearchCondition(context: "mobile")],
          consequence: SearchConsequence(params: SearchConsequenceParams(filters: "release_date >= 1577836800"))
      )
  )
  ```
</CodeGroup>

### Create a contextual rule with the dashboard

1. Select the **Search** product icon on your dashboard.
2. Select the **Rules** section from the left sidebar menu in the [Algolia dashboard](https://dashboard.algolia.com/rules).
3. Under the heading **Rules**, select the index to which you're adding a rule.
4. Select **Create your first rule** or **New rule**. In the drop-down menu, click the **Manual Editor** option.
5. In the **Condition(s)** section, toggle **Context** on and toggle **Query** off.
6. Enter "mobile" in the context input field.
7. In the **Consequence(s)** sections, click **Add Consequence** and select the **Add Query Parameter** consequence.
8. In the editor, add a <Filter /> for the `release_date` attribute. For example, to show all movies released since 2020 (`1577836800` is the Unix timestamp for January 1, 2020), enter: `{ "filters": "release_date >= 1577836800" }`
9. If you wish, you can add other consequences by clicking **Add consequence**. For example, there may be movies that you want to pin to a specific location or rank at the top,
10. Save your changes.
