Seekmodo developer docs

Reference for the REST shim, MCP JSON-RPC surface, and storefront connectors. Authenticate with HMAC; replay window is 5 minutes.

Multi-region storefronts

Run one Seekmodo tenant across multiple markets — different prices, stock, merchandising, and self-tuning relevance per region — without standing up a tenant per country. Region scoping is forward-looking: every storefront ships with it off, and Seekmodo behaves byte-for-byte the same as before until you turn it on.

1. Turn it on

Open Admin → Regions, flip Enable multi-region on this storefront, and add one row per market. Each region carries:

  • region_id — your slug (e.g. us, ca, uk). Locked once created.
  • currency — ISO 4217 (USD, CAD, GBP, EUR, …). Drives the price formatter in the SDK.
  • locale — BCP-47 (en-US, fr-CA, de-DE, …). Used by Intl.NumberFormat for thousands separators and decimal symbols.
  • url_path_prefix — optional. When set, shoppers landing on a URL under this prefix (e.g. /ca/products/...) get the region without a cookie / IP lookup.
  • Default region — the fallback when nothing else identifies the shopper. Required.

2. The 5-step region resolver

Every /v1/search, /v1/recommend, and /v1/chat request runs through the gateway's RegionResolver. First non-empty match wins; if every step misses, the shopper lands on the tenant default, so prices and stock always render.

  1. Explicit picker. Body argregion_id or the Seekmodo-Region HTTP header. The SDK reads theseekmodo_region cookie and forwards it as the header — see step 4.
  2. Connector envelope. shopper_context.region_id. Connectors that know the shopper's region (e.g. logged-in Zen Cart customers via customers_zone_id) attest it here.
  3. URL path. The longest matching url_path_prefix on the request's Referer. /uk/... beats /u/... when both exist.
  4. IP geolocation. Optional, off by default. When the operator installs MaxMind GeoLite2 on the gateway and toggles IP geolocation on, the resolver maps the shopper's ISO country code to a region. Failures fall through silently — never an error, never a delay.
  5. Tenant default. The region you flagged as default in step 1.

3. Wire the connector (optional)

Skip this step if your storefront only uses the URL prefix / IP / cookie rungs. For the Zen Cart connector v1.0.13+, define one of the following storefront constants in your config.numinix_seekmodo.php:

define('NUMINIX_SEEKMODO_REGIONS_ENABLED', true);

// Option A — JSON map of zone / country id to region slug.
// Looks at customer_zone_id first, falls back to
// customer_country_id under a "country:<id>" key.
define('NUMINIX_SEEKMODO_ZONE_REGION_MAP', json_encode([
    '1'           => 'us',  // Zen Cart zone_id 1 (US)
    '2'           => 'ca',  // zone_id 2 (Canada)
    'country:223' => 'us',  // guests in the US
    'country:38'  => 'ca',  // guests in Canada
]));

// Option B — static slug, useful before you have logged-in shoppers.
define('NUMINIX_SEEKMODO_DEFAULT_REGION_ID', 'us');

When neither option is set, the connector forwards no envelope field and the resolver moves to the URL / IP / default rungs.

4. Render the SDK

The gateway projects the resolved region onto every search response under meta.region:

{
  "hits": [...],
  "meta": {
    "region": {
      "id":              "ca",
      "currency":        "CAD",
      "locale":          "fr-CA",
      "src":             "envelope",
      "regions_enabled": true
    }
  }
}

The web components read this automatically. <seekmodo-results> and <seekmodo-recommendations> format prices with the region's currency + locale, falling back to the existing currency attribute (or USD) when the field is absent. Add the picker if you want shoppers to override:

<seekmodo-region-switcher
  regions='[
    {"id":"us","display_name":"United States","currency":"USD"},
    {"id":"ca","display_name":"Canada","currency":"CAD"},
    {"id":"uk","display_name":"United Kingdom","currency":"GBP"}
  ]'>
</seekmodo-region-switcher>

On change the picker writes the slug to a first-partyseekmodo_region cookie and dispatches a seekmodo:region-change event on document. Every other Seekmodo component on the page refetches automatically. Storefronts using the SDK directly can wire setSeekmodoRegion(slug) from @seekmodo/web-components from any framework component (a checkout flow, a country picker, a saved preference page).

What stays scoped per region

  • Pricing & stock. The indexer-side fields price_by_region / in_stock_by_region are projected onto the top-level price / in_stock for the resolved shopper, so existing storefront templates render the right number with no template change.
  • Visibility. Items with visible_by_region set are filtered out of regions not in the list. Empty list = visible everywhere.
  • Merchandising. Pins, banners, deboosts, and segments take an optional region_id; NULL means “applies to every region”.
  • Self-tuning relevance. Per-region LTR models train automatically when a region accumulates ≥ LTR_REGION_MIN_EVENTS click events (default 5,000). Until then, the region inherits the tenant-wide model — check the LTR diagnostics tile to see which model fired for the last query.

Cost & metering

Multi-region does not change pricing. Each search counts once against your searches bucket regardless of how many regions the tenant has, and you only pay for hits on regions where you have inventory. Per-region LTR training runs offline against your existing click stream — no new meter, no new spend.

See Web Components for the full attribute reference, and Connectors for the envelope contract.