How to Enable Proximity Search in Adobe Search and Promote | Location-aware search with Adobe Search and Promote
This tutorial explains the details on enabling Proximity Search in Adobe Search and Promote.
Proximity Search
Proximity Search lets you associate a unique location with any page on your website, and then search and sort results by proximity (distance) from a given location.
For example, suppose you have populated pages on your website with United States postal ZIP code metadata such as the following:
<meta name="zipcode" content="84057">
After indexing your site, you perform the following search:
...&sp_q_location_1=84057&sp_x_1=zip&sp_q_max_1=100&sp_s=zip_proximity
The result set contains any documents located within 100 miles of ZIP code 84057, sorted in ascending order of distance from this ZIP code.
The telephone area codes also can be used for United States locations. Or, you can use latitude/longitude pairs to specify locations in your site metadata and in your search criteria. The location type is automatically determined from the form of the data that is provided.
Three-digit location values (“DDD”, where each “D” represents a decimal digit from 0–9) are treated as a United States telephone area code.
Five or five-dash-four digit location values (“DDDDD” or “DDDDD-DDDD”) are treated as a United States postal ZIP code.
Location values in the exact form of “±DD.DDDD±DDD.DDDD” are treated as a latitude/longitude pair. The first signed numeric value specifies latitude and the second signed numeric value represents longitude.
If you specify a positive latitude value, or positive longitude value, or both, the “+” character in the URL must be encoded as %2b. Otherwise, the “+” is interpreted as space, and the value is not recognized as a valid location.
When you search by proximity there is a special “proximity output field” created for that search. The field is populated with the relative distance between the location that is specified in the search criteria, and the location that is associated with each search result. This special field is named for the location-type field that is used in the search criteria with “_proximity” added to the end.
In the example search above, the results are sorted in ascending order of “zip_proximity.” That is the distance between the specified ZIP code (84057) and each result’s “zip” field location. You can also use this special “proximity output field” to display the relative distance for each search result, in either kilo meters or miles, using the Search template tag.
Configure Proximity Search
Let us now enable the proximity search in Adobe Search and Promote, I am going to use the IndexConnector to index the documents. Refer to the below URL for details on enabling IndexConnector and custom presentation and transport templates.
Proximity Search with zip code
Let us now enable the proximity search with zip proximity, I am going to index the below sample feed data through Index Connector
<feed xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<channel>
<title>Product Feed</title>
<Item>
<link>https://qa.example.com/product-title/p/prod1</link>
<title>
<![CDATA[Java Title1]]>
</title>
<description>
<![CDATA[<p>Prod1 description</p>]]>
</description>
<productType>Java</productType>
<ProductId>prod1</ProductId>
<zipcode>55123</zipcode>
<imageUrl>/content/dam/Images/product/prod1.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod2</link>
<title>
<![CDATA[Java Title2]]>
</title>
<description>
<![CDATA[<p>Prod2 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod2</ProductId>
<zipcode>92307</zipcode>
<imageUrl>/content/dam/Images/product/prod2.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod3</link>
<title>
<![CDATA[Java Title3]]>
</title>
<description>
<![CDATA[<p>Prod3 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod3</ProductId>
<zipcode>55103</zipcode>
<imageUrl>/content/dam/Images/product/prod3.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod5</link>
<title>
<![CDATA[Lava Title]]>
</title>
<description>
<![CDATA[<p>Lava description</p>]]>
</description>
<productType>Lava</productType>
<zipcode>55109</zipcode>
<ProductId>prod5</ProductId>
<imageUrl>/content/dam/Images/product/prod5.jpg</imageUrl>
</Item>
</channel>
</feed>
Enable the metadata configuration for new zipcode field — Settings →Metadata →Definitions
Configure the new field in IndexConnector — Settings →Crawling —>Index Connector
Modify the presentation and Transports templates to include the “proximity output field" and if required metadata field zip code to the response, sample custom presentation & transports templates below (modify the corresponding templates used)
custom_backend_json.tpl (Transport)
<search-content-type-header charset="UTF-8">
{
"general": {
"query" : "<search-query />",
"total" : "<search-total />",
"lower" : "<search-lower />",
"upper" : "<search-upper />"
},
"facets" : [
{
"name" : "n1",
"values" : [<search-field-value-list name="n1" quotes="yes" data="values" sortby="values" encoding="json" />],
"counts" : [<search-field-value-list name="n1" quotes="no" data="results" sortby="values" />]
}
],
"results" : [
<search-results>
{
"fields" :
[
{
"name" : "mdi",
"value" : "<search-display-field name="mdi" length="500" encoding="json" />"
},
{
"name" : "title",
"value" : "<search-display-field name="title" encoding="json" />"
},
{
"name" : "productType",
"value" : "<search-display-field name="productType" encoding="json" />"
},
{
"name" : "zip",
"value" : "<search-display-field name="zip" encoding="json" />"
},
{
"name" : "relative_distance",
"value" : "<search-display-field name="zip_proximity" encoding="json" />"
}
]
}
<search-if-not-last>,</search-if-not-last>
</search-results>
]
}
custom_presentation_json.tmpl (Presentation)
<guided-content-type-header content="application/json" />
<guided-if-query-param-defined gsname="callback" /><guided-query-param gsname="callback" />(</guided-if-query-param-defined>
{
"general" :
{
"query" : "<guided-query-param gsname='q' />",
"total" : "<guided-results-total />",
"page_lower" : "<guided-results-lower>",
"page_upper" : "<guided-results-upper>",
"page_total": "<guided-page-total/>"
},"facets" :
[
],
"results" :
[
<guided-results gsname="default">
{
"index" : "<guided-result-index />",
"title" : "<guided-result-field gsname="title" escape="ijson" />",
"productType" : "<guided-result-field gsname="productType" escape="ijson" />",
"zip" : "<guided-result-field gsname="zip" escape="ijson" />",
"relative_distance" : "<guided-result-field gsname="relative_distance" escape="ijson" />"
}<guided-if-not-last>,</guided-if-not-last>
</guided-results>
]
}
<guided-if-query-param-defined gsname="callback">)</guided-if-query-param-defined>
Run the Full Index now and execute the query by specifying the distance
The result contains any documents located within 10 miles of ZIP code 55123, sorted in ascending order of distance from this ZIP code.
{
"general": {
"query": "",
"total": "1",
"page_lower": "1",
"page_upper": "1",
"page_total": "1"
},
"facets": [],
"results": [
{
"index": "",
"title": "Java Title1",
"productType": "Java",
"zip": "55123",
"relative_distance": "0.00"
}
]
}
The result contains any documents located within 20 miles of ZIP code 55123, sorted in ascending order of distance from this ZIP code.
{
"general": {
"query": "",
"total": "3",
"page_lower": "1",
"page_upper": "3",
"page_total": "1"
},
"facets": [],
"results": [
{
"index": "",
"title": "Java Title1",
"productType": "Java",
"zip": "55123",
"relative_distance": "0.00"
},
{
"index": "",
"title": "Java Title3",
"productType": "java",
"zip": "55103",
"relative_distance": "10.98"
},
{
"index": "",
"title": "Lava Title",
"productType": "Lava",
"zip": "55109",
"relative_distance": "15.51"
}
]
}
The result contains any documents located within 1500 miles of ZIP code 55123, sorted in ascending order of distance from this ZIP code.
{
"general": {
"query": "",
"total": "4",
"page_lower": "1",
"page_upper": "4",
"page_total": "1"
},
"facets": [],
"results": [
{
"index": "",
"title": "Java Title1",
"productType": "Java",
"zip": "55123",
"relative_distance": "0.00"
},
{
"index": "",
"title": "Java Title3",
"productType": "java",
"zip": "55103",
"relative_distance": "10.98"
},
{
"index": "",
"title": "Lava Title",
"productType": "Lava",
"zip": "55109",
"relative_distance": "15.51"
},
{
"index": "",
"title": "Java Title2",
"productType": "java",
"zip": "92307",
"relative_distance": "1448.84"
}
]
}
Proximity Search with telephone area code
The proximity search can also be enabled through 3 digit telephone area code.
Sample Feed data
<feed xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<channel>
<title>Product Feed</title>
<Item>
<link>https://qa.example.com/product-title/p/prod1</link>
<title>
<![CDATA[Java Title1]]>
</title>
<description>
<![CDATA[<p>Prod1 description</p>]]>
</description>
<productType>Java</productType>
<ProductId>prod1</ProductId>
<zipcode>55123</zipcode>
<areacode>218</areacode>
<imageUrl>/content/dam/Images/product/prod1.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod2</link>
<title>
<![CDATA[Java Title2]]>
</title>
<description>
<![CDATA[<p>Prod2 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod2</ProductId>
<zipcode>92307</zipcode>
<areacode>320</areacode>
<imageUrl>/content/dam/Images/product/prod2.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod3</link>
<title>
<![CDATA[Java Title3]]>
</title>
<description>
<![CDATA[<p>Prod3 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod3</ProductId>
<zipcode>55103</zipcode>
<areacode>507</areacode>
<imageUrl>/content/dam/Images/product/prod3.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod5</link>
<title>
<![CDATA[Lava Title]]>
</title>
<description>
<![CDATA[<p>Lava description</p>]]>
</description>
<productType>Lava</productType>
<zipcode>55109</zipcode>
<areacode>612 </areacode>
<ProductId>prod5</ProductId>
<imageUrl>/content/dam/Images/product/prod5.jpg</imageUrl>
</Item>
</channel>
</feed>
Enable the metadata configuration for new areacode field — Settings →Metadata →Definitions
Configure the new field in IndexConnector — Settings →Crawling →Index Connector
Modify the presentation and Transports templates to include the “proximity output field” and if required metadata field area code to the response, sample custom presentation & transports templates below (modify the corresponding templates used)
custom_backend_json.tpl (Transport)
<search-content-type-header charset="UTF-8">
{
"general": {
"query" : "<search-query />",
"total" : "<search-total />",
"lower" : "<search-lower />",
"upper" : "<search-upper />"
},
"facets" : [
{
"name" : "n1",
"values" : [<search-field-value-list name="n1" quotes="yes" data="values" sortby="values" encoding="json" />],
"counts" : [<search-field-value-list name="n1" quotes="no" data="results" sortby="values" />]
}
],
"results" : [
<search-results>
{
"fields" :
[
{
"name" : "mdi",
"value" : "<search-display-field name="mdi" length="500" encoding="json" />"
},
{
"name" : "title",
"value" : "<search-display-field name="title" encoding="json" />"
},
{
"name" : "productType",
"value" : "<search-display-field name="productType" encoding="json" />"
},
{
"name" : "zip",
"value" : "<search-display-field name="zip" encoding="json" />"
},
{
"name" : "relative_distance",
"value" : "<search-display-field name="zip_proximity" encoding="json" />"
},
{
"name" : "areacode",
"value" : "<search-display-field name="areacode" encoding="json" />"
},
{
"name" : "relative_distance_areacode",
"value" : "<search-display-field name="areacode_proximity" encoding="json" />"
}
]
}
<search-if-not-last>,</search-if-not-last>
</search-results>
]
}
custom_presentation_json.tmpl (Presentation)
<guided-content-type-header content="application/json" />
<guided-if-query-param-defined gsname="callback" /><guided-query-param gsname="callback" />(</guided-if-query-param-defined>
{
"general" :
{
"query" : "<guided-query-param gsname='q' />",
"total" : "<guided-results-total />",
"page_lower" : "<guided-results-lower>",
"page_upper" : "<guided-results-upper>",
"page_total": "<guided-page-total/>"
},"facets" :
[
],
"results" :
[
<guided-results gsname="default">
{
"index" : "<guided-result-index />",
"title" : "<guided-result-field gsname="title" escape="ijson" />",
"productType" : "<guided-result-field gsname="productType" escape="ijson" />",
"zip" : "<guided-result-field gsname="zip" escape="ijson" />",
"relative_distance" : "<guided-result-field gsname="relative_distance" escape="ijson" />",
"areacode" : "<guided-result-field gsname="areacode" escape="ijson" />",
"relative_distance_areacode" : "<guided-result-field gsname="relative_distance_areacode" escape="ijson" />"}<guided-if-not-last>,</guided-if-not-last>
</guided-results>
]
}
<guided-if-query-param-defined gsname="callback">)</guided-if-query-param-defined>
Run the Full Index now and execute the query by specifying the distance
The result contains any documents located within 200 miles of area code 218, sorted in ascending order of distance from this area code.
{
"general": {
"query": "",
"total": "3",
"page_lower": "1",
"page_upper": "3",
"page_total": "1"
},
"facets": [],
"results": [
{
"index": "",
"title": "Java Title1",
"productType": "Java",
"zip": "55123",
"relative_distance": "",
"areacode": "218",
"relative_distance_areacode": "0.00"
},
{
"index": "",
"title": "Java Title2",
"productType": "java",
"zip": "92307",
"relative_distance": "",
"areacode": "320",
"relative_distance_areacode": "125.02"
},
{
"index": "",
"title": "Lava Title",
"productType": "Lava",
"zip": "55109",
"relative_distance": "",
"areacode": "612",
"relative_distance_areacode": "171.86"
}
]
}
The search can also be enabled based on the latitude/longitude by enabling metadata with latitude/longitude value in “±DD.DDDD±DDD.DDDD” format and searching with the same value(e.g. +44.8041, -93.1668).
The proximity search will associate the location data to the search records and allows us to search the records based on the relative location of the records.