← API reference

Address autocomplete widget

One script tag wires Canadian address search into an existing form. It finds the address field, fills the address on selection, and emits the riding. The widget calls /api/search, which must be enabled on this deployment.

Widget v1.3.0

Quick start

<script src="https://cancoder.chesterhillsolutions.ca/embed.js" data-province="ON" defer></script>

That is the whole integration. On load the widget finds the address field in each <form>, attaches, and handles the rest.

Script tag attributes

AttributeEffect
data-autoSet to false to disable auto-attach and wire forms yourself with the JavaScript API.
data-keyPublic browser key (pk_…). Required when browser keys are enabled; pairs with an origin allowlist and a daily cap.
data-provinceRestrict suggestions to a province/territory code (for example ON).
data-limitMaximum suggestions to request per keystroke. Defaults to the API default.
data-include-provinceSet to true to resolve the riding as well as the address (uses /api/combined).
data-demoSet to true to resolve via the keyless /api/demo/* tier — intended for marketing try-its, not production.
data-endpointOverride the API origin the widget calls. Defaults to the script’s own origin.
data-themeForce light or dark. Omit to follow the operating-system preference.

Field detection

The standard autocomplete attribute wins, since it is an explicit statement of intent; otherwise name/id/placeholder/aria-label/<label> are matched against per-field patterns. Detection is deliberately conservative: it skips address-line2, unit/apt, country, and email fields, and matches on word boundaries so prov matches but improve does not.

Filling works on React/Vue controlled inputs: values are written through the prototype setter and followed by real input/change events, so framework state actually updates instead of silently reverting. A province <select> is matched on either the code (ON) or the full name (Ontario).

JavaScript API

For forms detection cannot read, attach explicitly:

const widget = RidingLookup.attach({
  form: '#checkout',
  input: '#addr1',                 // optional; auto-detected within `form`
  fields: {                        // any of these override detection
    city: '#city', province: '#prov', postal: '#pc',
    riding: '#riding_hidden'       // not auto-detected: bind it to have the riding written in
  },
  province: 'ON',
  includeProvince: false,          // true -> resolve via /api/combined
  demo: false,                     // true -> resolve via /api/demo/* (keyless; marketing)
  fill: true,                      // false -> emit events only, touch nothing
  locationBias: { lat: 43.65, lon: -79.38 },
  onSelect(s) {}, onRiding(r) {}, onError(e) {}
});
widget.destroy();                  // restores the field exactly as found

Events

Events bubble from the input, so one delegated listener covers every form on the page.

Eventdetail
ridinglookup:selectThe chosen suggestion, fired for containers and addresses alike.
ridinglookup:riding{ riding, properties, provinceData, point, suggestion }
ridinglookup:error{ error }
document.addEventListener('ridinglookup:riding', (e) => {
  console.log(e.detail.riding); // "Toronto Centre"
});

Behaviour worth knowing

Authentication

The widget runs in a browser, so it cannot hold a secret. Use a public browser key (pk_…), which pairs with a server-enforced origin allowlist and a daily cap:

<script src="https://cancoder.chesterhillsolutions.ca/embed.js" data-key="pk_live_…" defer></script>

Your backend should keep calling the API with BASIC_AUTH (or a server key): that credential is not origin-restricted and not daily-capped, and never belongs in a browser.

See also