Display promotional or informational banners in your Algolia results using Rules.
Search isn’t only about retrieving results.
Depending on the query, you might want to show banners, such as informational or promotional content.For example, consider an online bookstore that wants to display a discount for users looking for Harry Potter titles.
You can display a banner for specific queries using a rule.You can add banners in two ways:
InstantSearch banners: use a rule to add banner data to the renderingContent.widgets.banners field, so that supported InstantSearch widgets render the banner for you.
Custom banners: use a rule to add banner data to the userData field. Your own UI code reads this data and renders the banner.
If your site already uses an InstantSearch Hits or InfiniteHits
widget, you can display banners automatically based on a Visual Editor rule which adds banner data to the search response.
This requires InstantSearch.js version 4.73.0 or later, React InstantSearch version 7.12.0 or later, or Vue InstantSearch version 4.19.0 or later.
Create a Visual Editor rule with a banner consequence
Click Create your first Rule or New rule and select Visual Editor.
In the It all starts here section, click Set query conditions.
In the Your query field, enter harry potter and click Apply.
In the What do you want to do? section, click Add Banner.
Enter the required content for your banner: the URL for your banner image and click Apply.
Review the banner preview above the results.
Confirm your changes by clicking Review and Publish.
Make sure your search UI uses a supported InstantSearch widget (Hits or InfiniteHits) and
is deployed on your website so it can display banners from the renderingContent.widgets.banners property in the API response.
Create a rule with a banner consequence using the API
To run the code examples on this page, install the latest API client.To add a rule with a banner consequence using the API, use the saveRule method.
When adding a rule, you need to define a condition and a consequence.
In the consequence, add search parameters and configure renderingContent using the following template:
JSON
{ "renderingContent": { "widgets": { "banners": [ { "image": { "urls": [ { "url": "https://www.algolia.com/banner.jpg" } ], "title": "20% OFF on all Harry Potter books!" }, "link": { "url": "https://www.algolia.com/harry-potter-promo", "target": "_blank" } } ] } }}
After adding the rule, you can display the banner in your UI with the InstantSearch Hits or InfiniteHits widgets.The banner renders automatically unless you configure the widget to hide it.
For example:
// Don't display the banner in the Hits widgetsearch.addWidgets([ instantsearch.widgets.hits({ container: "#hits", templates: { banner: (_results) => null, }, }),]);
// Don't display the banner in the Hits widget<Hits bannerComponent={false} />;
<!-- Don't display the banner in the Hits widget --><ais-hits :showBanner="false" />
If you want to motivate users to buy Harry Potter books,
you can display a special promotional banner at the top of search results whenever their search query contains harry potter.
To display the banner:
Create a rule that returns the banner data in the userData field.
Update your search UI to read and render this userData.
To add a rule, you need to use the saveRule method.
When setting a rule, you need to define a condition and a consequence.For the preceding example, you want to show the banner whenever the query contains harry potter.
The match doesn’t need to be exact.
If the query is harry potter azkaban or books harry potter, you still want to display the promotion.
var response = await client.SaveRuleAsync( "INDEX_NAME", "harry-potter-rule", new Rule { ObjectID = "harry-potter-rule", Conditions = new List<Condition> { new Condition { Pattern = "harry potter", Anchoring = Enum.Parse<Anchoring>("Contains") }, }, Consequence = new Consequence { UserData = new Dictionary<string, string> { { "promo_content", "20% OFF on all Harry Potter books!" }, }, }, });
final response = await client.saveRule( indexName: "INDEX_NAME", objectID: "harry-potter-rule", rule: Rule( objectID: "harry-potter-rule", conditions: [ Condition( pattern: "harry potter", anchoring: Anchoring.fromJson("contains"), ), ], consequence: Consequence( userData: { 'promo_content': "20% OFF on all Harry Potter books!", }, ), ),);
response, err := client.SaveRule(client.NewApiSaveRuleRequest( "INDEX_NAME", "harry-potter-rule", search.NewEmptyRule().SetObjectID("harry-potter-rule").SetConditions( []search.Condition{*search.NewEmptyCondition().SetPattern("harry potter").SetAnchoring(search.Anchoring("contains"))}).SetConsequence( search.NewEmptyConsequence().SetUserData(map[string]any{"promo_content": "20% OFF on all Harry Potter books!"}))))if err != nil { // handle the eventual error panic(err)}
UpdatedAtResponse response = client.saveRule( "INDEX_NAME", "harry-potter-rule", new Rule() .setObjectID("harry-potter-rule") .setConditions(Arrays.asList(new Condition().setPattern("harry potter").setAnchoring(Anchoring.CONTAINS))) .setConsequence( new Consequence().setUserData( new HashMap() { { put("promo_content", "20% OFF on all Harry Potter books!"); } } ) ));
const response = await client.saveRule({ indexName: 'indexName', objectID: 'harry-potter-rule', rule: { objectID: 'harry-potter-rule', conditions: [{ pattern: 'harry potter', anchoring: 'contains' }], consequence: { userData: { promo_content: '20% OFF on all Harry Potter books!' } }, },});
var response = client.saveRule( indexName = "INDEX_NAME", objectID = "harry-potter-rule", rule = Rule( objectID = "harry-potter-rule", conditions = listOf( Condition( pattern = "harry potter", anchoring = Anchoring.entries.first { it.value == "contains" }, ) ), consequence = Consequence( userData = buildJsonObject { put("promo_content", JsonPrimitive("20% OFF on all Harry Potter books!")) } ), ), )
$response = $client->saveRule( 'INDEX_NAME', 'harry-potter-rule', ['objectID' => 'harry-potter-rule', 'conditions' => [ ['pattern' => 'harry potter', 'anchoring' => 'contains', ], ], 'consequence' => ['userData' => ['promo_content' => '20% OFF on all Harry Potter books!', ], ], ],);
response = client.save_rule( index_name="INDEX_NAME", object_id="harry-potter-rule", rule={ "objectID": "harry-potter-rule", "conditions": [ { "pattern": "harry potter", "anchoring": "contains", }, ], "consequence": { "userData": { "promo_content": "20% OFF on all Harry Potter books!", }, }, },)
response = client.save_rule( "INDEX_NAME", "harry-potter-rule", Algolia::Search::Rule.new( algolia_object_id: "harry-potter-rule", conditions: [Algolia::Search::Condition.new(pattern: "harry potter", anchoring: "contains")], consequence: Algolia::Search::Consequence.new(user_data: {promo_content: "20% OFF on all Harry Potter books!"}) ))
val response = Await.result( client.saveRule( indexName = "INDEX_NAME", objectID = "harry-potter-rule", rule = Rule( objectID = "harry-potter-rule", conditions = Some( Seq( Condition( pattern = Some("harry potter"), anchoring = Some(Anchoring.withName("contains")) ) ) ), consequence = Consequence( userData = Some(JObject(List(JField("promo_content", JString("20% OFF on all Harry Potter books!"))))) ) ) ), Duration(100, "sec"))
let response = try await client.saveRule( indexName: "INDEX_NAME", objectID: "harry-potter-rule", rule: Rule( objectID: "harry-potter-rule", conditions: [SearchCondition(pattern: "harry potter", anchoring: SearchAnchoring.contains)], consequence: SearchConsequence(userData: ["promo_content": "20% OFF on all Harry Potter books!"]) ))
The search response includes your banner data in the userData property.
This data isn’t displayed automatically:
your search UI must read userData and render the banner when it’s present.
For example, with InstantSearch you can use the queryRuleCustomData widget:
You may have several semi-permanent promotional banners for
specific product categories,
as well as some time-limited, temporary banners for certain products.For instance, an online IT hardware store has banners for the following categories:
Phones
Tablet computers
Laptop computers
Desktop computers
They also have temporary offers and associated banners for the phrases and products:
Infinix Note 40 Pro
Xiaomi Redmi Note 14 Pro+
Samsung Galaxy S25 Ultra
Samsung Galaxy Tab S10 Ultra
Samsung Galaxy Book3 360
To decide which banner to show, Algolia uses a tie-breaking algorithm when multiple rules match.Using the preceding list of products as an example:
User starts on the Phones category page and sees the Phones banner.
They search for note.
At this point, three rules can match: the Phones category banner and the two product banners for Infinix Note 40 Pro and Xiaomi Redmi Note 14 Pro+.
The two product banners are more specific than the category banner, so they take precedence over it.
When multiple rules match, Algolia compares their objectID values and shows the banner whose objectID comes first alphabetically.
In this context, objectID refers to the rule’s ID, not to any product or record objectID in your index.
Rule objectIDs are unique identifiers for rules.
When using the API, you can set them manually.
In the dashboard, they’re generated automatically.To control this tie-breaker, set or change the rule’s objectID with the saveRule method.