> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glood.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Image Search

> Search by an uploaded photo or image URL using the Glood Hydrogen Search SDK

Image (visual) search takes one image source and returns matching products. In the browser use
the `SearchApp`'s [`imageSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#methods)
method; for SSR use the standalone
[`fetchImageSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#fetchimagesearch).

<Note>
  Prerequisite: the search app is registered (`.use(search())`), your app is wrapped in
  `<GloodProvider>`, and `https://search.glood.ai` is in your CSP `connectSrc`. See
  [Installation](/for-developers/glood-hydrogen-sdk/installation).
</Note>

## 1. Get the image as a `data:` URL

Pass **exactly one** source: `image` (base64 or a `data:` URL) **or** `imageUrl` (an http(s)
URL, fetched server-side). From a file input, convert to a `data:` URL:

```tsx theme={null}
const toDataUrl = (file: File) =>
  new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
```

## 2. Run the search

Retrieve the `SearchApp` via `useGloodAnalytics().getApp('search')` and call
[`imageSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#methods):

```tsx theme={null}
import { useState } from 'react';
import { useGloodAnalytics, type SearchItem } from '@glood/hydrogen';

export function ImageSearch() {
  const app = useGloodAnalytics()?.getApp('search');
  const [products, setProducts] = useState<SearchItem[]>([]);

  async function onFile(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file || !app) return;
    const res = await app.imageSearch({ image: await toDataUrl(file), pagination: { limit: 24 } });
    setProducts(res.products);
  }

  return (
    <div>
      <input type="file" accept="image/jpeg,image/png,image/webp" onChange={onFile} />
      <div className="grid">
        {products.map((p) => (
          <a key={p.product_id} href={`/products/${p.handle}`}>
            <img src={p.image?.url} alt={p.title} loading="lazy" />
            <span>{p.title}</span>
          </a>
        ))}
      </div>
    </div>
  );
}
```

Params are an [`ImageSearchParams`](/for-developers/glood-hydrogen-sdk/api-reference/types#imagesearchparams--imagesearchresponse);
`res` is an [`ImageSearchResponse`](/for-developers/glood-hydrogen-sdk/api-reference/types#imagesearchparams--imagesearchresponse)
and each product is a [`SearchProduct`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchproduct).

<Note>
  `imageSearch` always runs against the app's **`controlEndpoint`** (non-edge) — the vision
  pipeline isn't available on regional edges. This routing is automatic; see
  [Configuration → Edge vs. non-edge routing](/for-developers/glood-hydrogen-sdk/configuration#edge-vs-non-edge-routing-controlendpoint).
</Note>

## 3. Image constraints

Images are validated server-side; anything outside these returns `400`:

| Rule       | Value                      |
| ---------- | -------------------------- |
| Format     | `jpeg`, `png`, `webp` only |
| Size       | 1 KB – 5 MB                |
| Dimensions | 100×100 to 4096×4096 px    |

## 4. From a URL, or on the server

Pass `imageUrl` instead of `image` to search by a hosted image, and use
[`fetchImageSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#fetchimagesearch)
when you don't have a React component (loaders, mobile backends):

```tsx theme={null}
import { fetchImageSearch } from '@glood/hydrogen';

const res = await fetchImageSearch(
  { apiKey: context.env.GLOOD_API_KEY, myShopifyDomain: 'your-store.myshopify.com' },
  { imageUrl: 'https://example.com/photo.jpg', pagination: { limit: 24 } },
);
```

## 5. Attribution

Attribute clicks with `search_type: 'image'` via the `SearchApp` track helpers
([`trackResultClick`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#event-helpers)),
each taking a [`SearchTrack`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchtrack):

```tsx theme={null}
app.trackResultClick({
  search_type: 'image',
  source: 'image_search',
  products: [{ product_id: p.product_id }],
});
```

## See also

* [`fetchImageSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#fetchimagesearch) — standalone signature
* [Search & Discovery → Image search](/for-developers/glood-hydrogen-sdk/search#image-visual-search)
* [Search API Reference](/for-developers/glood-hydrogen-sdk/api-reference/search-api)
