Locator Upgrade - General API Steps
Table of Contents
Store finder render service API
The render service turns a store finder page into HTML on the server. A web server, a CDN or a plugin asks for that HTML and puts it into its own page, so the stores are in the page before any JavaScript runs.
This document is the contract for anyone who calls the service. For a step by step setup on a web server, see the guides in integration/.
At a glance
| Endpoint | Returns |
GET /page |
Body and head from one render, as JSON. Use this one from your own code |
GET /body |
The store finder markup, as HTML |
GET /head |
The tags for the page's <head>, as HTML |
Base URL:
https://uberall.com/api/locator-fragments
A trailing slash on the endpoint path is accepted: /body/ works the same as /body. Any other path answers 404 not found.
Which endpoint to use
- From your own code (PHP, Node.js, a CMS plugin, a serverless function): call
GET /page. One call returns the body and the head from the same render, as JSON. Putbodyinto the store finder's div andheadinto the page's<head>. - From a web server that inserts the answer as it is, such as Apache or nginx includes, Varnish ESI or LiteSpeed: call
GET /bodyandGET /head. They return plain HTML, which the server puts in place without reading it.
Authentication
Every call sends the render token in a header:
x-uberall-render-token: YOUR_RENDER_TOKEN
Uberall gives you the token. The locator key is not a secret, since it is in the store finder snippet on every page, so the token is what lets a caller in.
Without the token, or with one the service does not know, the answer is still a 200 with an empty fragment and the reason unauthorised. See Empty answers.
Query parameters
All three endpoints take the same parameters.
| Parameter | Required | Meaning |
key |
Yes | The locator key, the data-key of the store finder snippet |
lang |
No | Language of the page, such as de. Defaults to the locator's language |
countries |
No | Only when the snippet has data-countries, with exactly the same value, such as US,DE. To limit a single locator's countries, set them in the builder instead and leave both out. Most callers don't need it |
widgetOriginUrl |
No | The store finder's address, such as https://www.example.com/store-locator. Defaults to the address configured on the locator |
withoutMap |
No |
true for a page that loads storeFinderWidget-v2-withoutMap.js or starts the store finder with withoutMap: true. Anything else renders it with the map |
debug |
No |
1 shows why a fragment is empty. See Debugging
|
path |
Yes | The path the visitor asked for, such as /store-locator/berlin. Defaults to /. Must be the last parameter
|
path comes last
A web server often pastes the visitor's request into path as it is, without encoding it. If the visitor's URL has an &, it would then set one of the parameters above. So the service reads everything after the first path= as the path, and only what comes before it as the other parameters.
/body?key=YOUR_LOCATOR_KEY&lang=de&path=/store-locator/berlin?q=a&b=c
└─────── parameters ───────┘ └───────────── path ─────────────┘
When key, lang, widgetOriginUrl or debug appears after path:
- In the path itself, such as
path=/store-locator&key=…, the answer is empty with the reasonmisplaced-parameter. Move the parameter beforepath. - In the visitor's query, such as
path=/store-locator?lang=fr, it belongs to the site, so the service ignores it.
path may be encoded or not.
Which page is rendered
The path has to be under the store finder's address (widgetOriginUrl). The store finder decides which page it is, the same way it does in the browser: the store finder home, a country, a city, a single store, and so on. A path that is not a page of this store finder gets an empty answer.
The visitor's query (after ?) does not change the HTML. A search or a filter only changes what one visitor sees, and the store finder applies it in the browser, on top of the HTML.
The snippet and the calls must match
The store finder only takes over the server's HTML when it was rendered with the same settings as the snippet on the page. Otherwise it drops the server render and renders in the browser, and search engines and AI assistants may not see your stores.
| Snippet | Call |
|---|---|
data-key |
key |
data-language |
lang |
data-countries |
countries |
data-widgetoriginurl |
widgetOriginUrl |
storeFinderWidget-v2-withoutMap.js, or withoutMap: true
|
withoutMap=true |
Leave data-baseurl out of the snippet. The server always renders with Uberall's own API, so a snippet with its own data-baseurl never matches.
GET /page
Everything one render produces, as JSON. For a caller that builds the page itself, such as a plugin. Calling /body and /head costs two renders; /page costs one.
curl -H 'x-uberall-render-token: YOUR_RENDER_TOKEN' \
'https://uberall.com/api/locator-fragments/page?key=YOUR_LOCATOR_KEY&path=/store-locator/berlin'
HTTP/1.1 200 OK
content-type: application/json
cache-control: public, max-age=300
x-sf-request-id: 0b9a6c4d-3e2f-4a1b-8c7d-5e6f7a8b9c0d
x-sf-widget-version: 3.250.0@abc12345
{
"body": "<div …>…the store finder markup…</div>",
"head": "<title>…</title><link rel=\"canonical\" href=\"…\"><meta name=\"description\" content=\"…\">…",
"page": "locationPage"
}
| Field | Meaning |
body |
The store finder markup, the same as /body answers |
head |
The tags for <head>, the same as /head answers |
page |
Which kind of store finder page the path is: mainPage, sitemapPage or locationPage
|
When there is nothing to render
The status is still 200, with the same headers as an empty /body: x-sf-empty-reason, x-sf-request-id and cache-control: public, max-age=10. The body has the reason:
{ "reason": "unknown-locator" }
With debug=1, a reason that comes from the render (incomplete-render, no-page-content) also carries what the render reported:
{ "reason": "incomplete-render", "errors": ["…"], "warnings": ["no-page-content"] }
| Field | Meaning |
reason |
Why there is nothing to render, the same as x-sf-empty-reason. See Empty answers
|
errors |
The errors the render raised. Only with debug=1
|
warnings |
What the render noticed without failing, such as no-page-content. Same condition |
GET /body
The store finder markup, to put where the store finder snippet is on the page.
curl -H 'x-uberall-render-token: YOUR_RENDER_TOKEN' \
'https://uberall.com/api/locator-fragments/body?key=YOUR_LOCATOR_KEY&path=/store-locator/berlin'
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
cache-control: public, max-age=300
x-sf-request-id: 2f1c5a0e-8a51-4c3e-9d0b-6a2b6a9f1e7d
x-sf-widget-version: 3.250.0@abc12345
<div …>…the store finder markup…</div>
Put the whole answer where the snippet is, as it comes.
GET /head
The tags the page needs in its <head>: title, canonical link, meta tags and the store finder's stylesheet.
curl -H 'x-uberall-render-token: YOUR_RENDER_TOKEN' \
'https://uberall.com/api/locator-fragments/head?key=YOUR_LOCATOR_KEY&path=/store-locator/berlin'
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
cache-control: public, max-age=300
x-sf-request-id: 7d0e3b8c-1f4a-4b6e-a2c9-3e5d8f0a1b2c
x-sf-widget-version: 3.250.0@abc12345
<title>…</title><link rel="canonical" href="…"><meta name="description" content="…">…
Put the whole answer into <head>, as it comes.
Response headers
| Header | When | Meaning |
x-sf-request-id |
Always | ID of this request. Quote it when you report a problem |
x-sf-widget-version |
Rendered answers | The store finder version the HTML was rendered with |
x-sf-empty-reason |
Empty answers | Why there is nothing to render. See the table below |
cache-control |
Always |
public, max-age=300 when rendered, public, max-age=10 when empty |
An empty answer is cached for a much shorter time on purpose. A short failure, cached as long as a page, would remove the page's HTML for five minutes without anyone noticing, because the store finder still shows the page to visitors in the browser.
Empty answers
/body, /head and /page always answer with status 200, also when there is nothing to render.
A server side include cannot change the status of the page it is in, and neither Apache nor Varnish has a way to catch an error from one. With another status, the customer's server could not handle it, and some setups would put the error page into the customer's page. So an empty answer is how the service says "nothing to render", and the store finder renders the page in the browser as it did before.
| x-sf-empty-reason | Meaning |
unauthorised |
The render token is missing or not known |
unknown-locator |
No key, or a key the service does not know |
misplaced-parameter |
One of the parameters came after path, which has to be last |
missing-origin-url |
No store finder address on the locator, and no widgetOriginUrl sent |
unresolvable-path |
The path is not a page of this store finder |
upstream-failure |
The locator API did not answer |
timeout |
The render took longer than its deadline |
incomplete-render |
The render did not produce every part of the page |
no-page-content |
The render raised no error but produced no page content |
render-unavailable |
The service has no store finder to render with |
incomplete-render and no-page-content are answered empty on purpose: a page with a part missing would be cached and look fine from outside, which is worse than no HTML at all.
The body of an empty answer:
-
/bodyand/head: an HTML comment with the reason and the request ID, such as<!-- uberall-render: no fragment · reason=unknown-locator · req=… --> -
/page:{ "reason": "…" }, see When there is nothing to render
Debugging
With debug=1, an empty /body or /head shows a visible box on the page instead of the HTML comment. It names the reason, explains it in one line, and gives the request ID.
/page adds the render's errors and warnings the same way, see When there is nothing to render.