Seekmodo developer docs

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

<seekmodo-image-search> — search by photo

A drop-in widget that lets shoppers find products by snapping or uploading an image. Powered by CLIP ViT-B/32 running on a dedicated embed sidecar; results come back from the same Typesense index your text search uses, so the SERP renders through the existing <seekmodo-results>widget.

Pricing — 2× on the master bucket

Every shopper image search costs 2 against your searches allowance (one for the text-equivalent lookup, one for the AI visual match) + 1 against the dedicated searches_image display bucket that surfaces on your /analytics dashboard so you can separate visual from keyword fan-out.

Indexer-side, every catalog photo we convert to an AI vector consumes 1 from your image_embeds allowance. That's a one-time cost per product photo — once embedded, the same SKU can be searched against forever without re-embedding.

Plan-tier eligibility

Image search requires the Growth plan or higher. Hobby and Starter tenants get an HTTP 402 with error: feature_not_in_plan; the widget mounts but degrades silently to nothing — upgrade to enable.

Embed

After installing @seekmodo/web-components and wiring the meta tags:

<seekmodo-image-search
  button-label="Search by photo"
  max-edge="1024"
  quality="0.85"
  with-preview
>
  <!-- Optional: override the default upgrade affordance -->
  <a slot="upgrade" href="/account/billing?upgrade=image_search">
    Image search paused — upgrade to keep
  </a>
</seekmodo-image-search>
<seekmodo-results></seekmodo-results>
<script>
  document.addEventListener('seekmodo:image-search', (e) => {
    const results = document.querySelector('seekmodo-results');
    results.setHits(e.detail.results);
  });
</script>

The widget client-side resizes uploads to a 1024-px max edge (configurable via max-edge) before encoding to base64, so a typical phone photo (3-8 MB raw) goes over the wire as ~150-200 KB — well under the gateway's 2 MB cap.

API

If you'd rather call the image search tool directly from the SDK (e.g. for a server-rendered “more like this” rail or a native iOS / Android app):

// Path 1 — shopper-uploaded photo
const res = await client.searchByImage({
  image_b64: base64WithoutDataPrefix,
});

// Path 2 — catalog URL (embed worker fetches it)
const res = await client.searchByImage({
  image_url: "https://cdn.example.com/photos/red-sneaker.jpg",
});

// Path 3 — "more like this" using an indexed doc's vector. No
// embed-worker call — much faster and doesn't count against the
// image_embeds bucket, only the 2× searches charge.
const res = await client.searchByImage({
  doc_id: "sku-12345",
});

if (res.meta?.suppressed) {
  renderUpgradeCta(res.meta.suppression_reason);
} else {
  renderHits(res.hits);
}

Catalog photo cost — worked example

The indexer asks the embed worker for one CLIP vector per product photo it sees on the first full reindex after you enable image search. Subsequent reindexes only re-embed photos that changed, so the steady-state monthly cost is well below this one-time bootstrap.

Catalog sizeImages / SKUTotal imagesimage_embeds consumedFits in
Small (1,000 SKUs)11,0001,000Growth (10,000 cap, 10% used)
Medium (10,000 SKUs)110,00010,000Growth (cap reached on first reindex)
Large (50,000 SKUs, 1 photo each)150,00050,000Scale (100,000 cap, 50% used)
XL (100,000 SKUs, 3 photos each)3300,000300,000Enterprise (unlimited)

Shopper-side cost — worked example

Each shopper image search consumes 2 from the master searches bucket because of the visual match multiplier. The table below sizes the impact across representative monthly traffic levels.

TrafficImage searches / moΣ searches consumedRecommended plan
Low (1K image searches/mo)1,0002,000Growth (50K searches cap, 4% used)
Medium (10K image searches/mo)10,00020,000Growth (40% of cap) or Scale
High (50K image searches/mo)50,000100,000Scale (500K cap, 20% used)
Very high (200K+ image searches/mo)200,000+400,000+Scale or Enterprise (with overage)

How image search meters

  • searches (master bucket) — 2× per shopper image search. Once exhausted, the gateway returns meta.suppressed=true and the widget renders the upgrade affordance.
  • searches_image (display bucket) — 1× per shopper image search. Visible on the /analytics dashboard so you can separate visual fan-out from keyword search loads.
  • image_embeds (master billing bucket) — 1× per catalog photo embedded during indexing. Surfaced on the /image-search admin page with cap + remaining headroom. When exhausted, new catalog photos are stored as text-only and the indexer continues without blocking.

Hybrid mode — text + photo together

Passing both a q string and an image to the regular search tool triggers blended ranking (Typesense's native vector_query weighting). The merchant sets the default blend on the admin /image-search page (0.0 = pure text, 1.0 = pure visual; default 0.5). A per-request image_blend_weight arg overrides the tenant default. Both modes meter identically — the master bucket sees a 2× charge regardless of which side of the blend dominates.

Defence-in-depth limits

  • 2 MB uploads — base64-encoded payload cap. The web component resizes client-side; SDK callers must enforce themselves.
  • Bot-check first — same gating as the text search tool. Bot traffic never reaches the embed worker.
  • Per-tenant toggle — entitled tenants must also flip image_search_enabled on the admin page before the gateway accepts the call.

Links