Redirects in Angular InstantSearch
On this page
Introduction
When you create specific landing pages to display search results, it’s handy to be able to redirect users to those dedicated pages, in the situation where the search query matches one of them.
In this tutorial, we’ll see two methods for setting up redirects in an Algolia index: using Rules and using dedicated indices.
Using Rules
The best way to set up redirects is through Rules. You can add redirect information as custom data to any Rule. The Rule returns this data when a search activates it. You also need to add a custom ais-query-rule-custom-data
widget that handles the Rule and redirects your user.
Configuring the Rule
Using the API
To add a Rule, you need to use the saveRule
method. When setting a Rule, you need to define a condition and a consequence.
In the example below, we want to redirect whenever the query matches “star wars” exactly. If the query is “star wars lightsaber” or “books star wars”, we don’t want to redirect.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$rule = array(
'objectID' => 'a-rule-id',
'conditions' => array(array(
'pattern' => 'star wars',
'anchoring' => 'is'
)),
'consequence' => array(
'userData' => array(
'redirect' => 'https://www.google.com/#q=star+wars'
)
)
);
$index->saveRule($rule);
Using the dashboard
You can also add your Rules in your Algolia dashboard.
- Select the Search product icon on your dashboard and then select your index.
- Click the Rules tab.
- Select Create your first rule or New rule. In the dropdown, click on the Manual Editor option.
- In the Condition(s) section, keep Query toggled on, select Is in the dropdown and enter “star wars” in the input field.
- In the Consequence(s) section:
- Click the Add consequence button and select Return Custom Data.
- In the input field that appears, add the data to return when the user query matches the Rule:
{ "redirect": "https://www.google.com/#q=star+wars" }
- Don’t forget to save your changes.
Configuring the queryRuleCustomData widget
Now that everything is set up, you can use the ais-query-rule-custom-data
widget to update the page location anytime userData
contains a redirect.
1
2
<ais-query-rule-custom-data [transformItems]="transformItems">
</ais-query-rule-custom-data>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
})
export class AppComponent {
// ...
transformItems(items) {
const match = items.find(data => Boolean(data.redirect));
if (match && match.redirect) {
window.location.href = match.redirect;
}
return [];
},
}
Using a dedicated index
An alternative way to set up redirects is to create a dedicated index with the list of redirects and the query terms that trigger them. This index is separate from your regular index, where your searchable records are. Whenever a user performs a search, you have to look in two indices: the regular one to search for items, and the redirect one that determines whether the user should be redirected.
This technique can be useful if you cannot use Rules or if you want access to typo tolerance, synonyms or filters.
Dataset
1
2
3
4
5
6
7
8
9
10
[
{
"url": "https://www.google.com/#q=star+wars",
"query_terms": ["star wars"]
},
{
"url": "https://www.google.com/#q=star+wars+actors",
"query_terms": ["george lucas", "luke skywalker"]
}
]
In this dataset, we give a list of URLs we want to redirect to. For each of them, we define a list of queries that we want to redirect from.
For example, the query “star wars” should redirect to https://www.google.com/#q=star+wars
.
You can download the dataset on our GitHub. Have look at how to import it in Algolia here
Configuring the index
We want to redirect only if the query exactly matches one of the query_terms
. We’re adding query_terms
to our list of attributesForFaceting
, so we can filter on it.
1
2
3
4
5
$index->setSettings([
'attributesForFaceting' => [
'query_terms'
]
]);
Creating a custom search client
Now that everything is set up, you’ll create a custom search client that will simultaneously send requests to the regular and redirect indices.
The request to the redirect index is sent with:
- an empty query, so we don’t filter with it
- a filter on
query_terms
with the content of the current query, to match only on records that contains the current query exactly hitsPerPage=1
, as we only need the first record
Whenever we find hits in this index, we redirect:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import algoliasearch from 'algoliasearch/lite';
const algoliaClient = algoliasearch(
'YourApplicationID',
'YourSearchOnlyAPIKey'
);
const customSearchClient = {
...algoliaClient,
async search(requests) {
if (requests[0].params.query) {
const { results } = await algoliaClient.search([
...requests,
{
indexName: 'your_redirect_index_name',
params: {
hitsPerPage: 1,
facetFilters: [`query_terms:${requests[0].params.query}`],
},
},
]);
const redirect = results.pop();
if (redirect.hits.length) {
window.location.href = redirect.hits[0].url;
}
return { results };
} else {
return algoliaClient.search(requests);
}
},
};
@Component({
template: `
<ais-instantsearch [config]="config">
<!-- Widgets -->
</ais-instantsearch>
`,
})
export class AppComponent {
config = {
indexName: 'instant_search',
searchClient: customSearchClient,
}
}