nyris API Documentation

Welcome to nyris' API Documentation. nyris is a high performance visual product search, object detection and visual recommendations engine for retail and industry. This documentation covers our visual product search engine and the visual recommendations engine.


The implementation in your website or app comprises of three steps.

1. Submit your product & image data
In order to recognize your products, we need to know your products. The product feed section covers all details how to submit your product data to us and the specifications for your product or object images.

2. Implement nyris API in your app, website or messenger bot
The nyris engine can be integrated in your app, website, messenger bots, BI solutions - wherever you want to make your customers happy or optimize your data management process. We provide you with code examples on how to query our Find API and Regions API and have ready to go SDKs for iOS and Android.

3. Implement automated feedback in your app, website or messenger bot
By tying user interactions to automated feedback in our Feedback API, you allow for automatic statistic generation and continous improvement of the search results.

To get started, email us at mailto:support@nyris.io. Our team will provision API keys to access our API. Always feel free to contact us should you have questions or suggestions for our service or this documentation. In addition, you can always find our open source code github.com/nyris.

Try it with Postman — You can explore and test the nyris API directly using our public Postman workspace. It includes ready-to-use collections for Find, Recommend, Regions, and Images APIs.

Thank You & happy coding!
Markus (CTO / Founder)

Authentication

All nyris API requests require an API key passed in the X-Api-Key header.

How do I get an API key?

To get started, email us at support@nyris.io. Our team will provision an API key for you.

What if I don't want to share the API key with front-end users?

If you want to control each request, you can create your own proxy that forwards the requests to the nyris API. That way you can have your own authentication method and control over each request.

Find API

Send an image to the Find API and receive a JSON object with metadata for the identified items. You can optionally pass a session ID to correlate multiple requests.

POST https://api.nyris.io/find/v1.1

To search with filters, send the image and filter fields as multipart/form-data. Filtered responses include only items matching the given filter types and values. You can also append a session ID as a query parameter: POST https://api.nyris.io/find/v1.1?session=xxxxxx.

Request Headers

Key | Value ---|--- X-Api-Key | The API key provided by us. Content-Type | image/jpeg, image/png, multipart/form-data (filters), or application/json (base64). Content-Length | The size of image in bytes. Accept | (Optional) application/items.complete+json for the full response format. Default is minimal. X-Session | (Optional) A valid session identifier to correlate multiple requests. X-Options | (Optional) Search parameters, e.g. limit=10 threshold=0.5. See below.

If no value is provided for X-Session (or the session query argument), a new session is started and its ID is returned with the response. Front-ends are encouraged to pass the session ID returned by the previous request to the next request, thereby linking requests together.

Request Body

  • Image only (binary): send the raw image bytes as the request body with Content-Type: image/jpeg or image/png.
  • Image with filters (multipart): use multipart/form-data and include the image plus the filter fields described below.
  • JSON body (base64): send Content-Type: application/json with a JSON object containing the image as a base64-encoded string. This is convenient for clients that work with JSON APIs end-to-end and avoids managing binary or multipart boundaries.

JSON Body Schema

Field | Type | Required | Description ---|---|---|--- image | String | Yes | Base64-encoded image (plain or data URI, e.g. data:image/jpeg;base64,...). text | String | No | Optional text query (max 512 characters). filters | Array | No | Same filter format as multipart: [{"key": "MachineSerial", "values": ["SN-40821"]}].

Note: base64 encoding increases payload size by ~33%. Stay within the usual image size limits.

Filter Schema (multipart)

When sending filters via multipart/form-data, include one or more filter type/value pairs. The AND operator is used between filter types; OR is used between values of the same type.

Name | Type | Explanation ---|---|--- filterType | String | The filter type, example: color filterValues | String [] | The filter values, example: [red, blue]

Search Parameters (X-Options)

Control result count and score thresholds via the X-Options header. Parameters are key=value pairs separated by a space, e.g. X-Options: limit=10 threshold=0.5.

Parameter | Example Value | Explanation ---|---|--- limit | limit=20 (default), integers between 1 and 100 | The upper limit for the number of results to be returned. threshold | threshold=0.8 | The final threshold to apply to the scores. Only results above or equal to that score will be returned.

Response Headers

Requests are automatically tagged with a Request ID and a Session ID:

Key | Value ---|--- X-Matching-Request | The identifier of the request; used for tracing and with the Feedback API. X-Session | A session identifier covering multiple requests; used for tracing and with the Feedback API.

Response Format

By default, a minimal response is returned. Use the Accept header to request the full format:

Accept value | Description ---|--- application/minimal+json | Return minimal response (the default). application/items.complete+json | Return all available fields.

We guarantee that existing fields will not be removed or have their type changed. Additional fields can be added at any point; application code should gracefully ignore unknown fields.

Image Requirements

  • Preferred image dimension: 1 Mpx (e.g. 1000 x 1000 px), regardless of aspect ratio.
  • Minimum size: 100 px on the shortest edge. Smaller images are rejected with a 460 status code.
  • Maximum file size: approximately 2 MB. Larger images are rejected with a 413 status code. A good target is around 100 kB.
  • Accepted formats: JPEG/JFIF or PNG only. JPEG is preferred for smaller file sizes.
  • Resize and crop on the client device before sending. Apply cropping to the original image first, then resize.

Example Request

POST
https://api.nyris.io/find/v1.1
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://api.nyris.io/find/v1.1")
  .post(null)
  .addHeader("x-api-key", "KEY")
  .addHeader("x-session", "...")
  .addHeader("content-type", "image/jpeg")
  .addHeader("content-length", "image-file-size-in-bytes")
  .addHeader("cache-control", "no-cache")
  .build();

Response response = client.newCall(request).execute();

Example with Filters

POST
https://api.nyris.io/find/v1.1
OkHttpClient client = new OkHttpClient();
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
    .addFormDataPart("filters[0].filterType","color")
    .addFormDataPart("filters[0].filterValues[0]","Red")
    .addFormDataPart("image","image.jpg",
        RequestBody.create(MediaType.parse("application/octet-stream"),
            new File("image.jpg")))
    .build();

Request request = new Request.Builder()
    .url("https://api.nyris.io/find/v1.1")
    .method("POST", body)
    .addHeader("x-api-key", "<SET_YOUR_KEY_HERE>")
    .addHeader("cache-control", "no-cache")
    .build();

Response response = client.newCall(request).execute();

Example with JSON Body (Base64)

POST
https://api.nyris.io/find/v1.1
{
    "image": "/9j/4AAQSkZJRg...",
    "text": "hydraulics",
    "filters": [
        {
            "key": "MachineSerial",
            "values": ["SN-40821"]
        },
        {
            "key": "Assembly",
            "values": ["Hydraulics", "Pneumatics"]
        }
    ]
}
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

OkHttpClient client = new OkHttpClient();

byte[] imageBytes = Files.readAllBytes(Path.of("image.jpg"));
String imageB64 = Base64.getEncoder().encodeToString(imageBytes);

String json = "{"
    + "\"image\":\"" + imageB64 + "\","
    + "\"text\":\"hydraulics\","
    + "\"filters\":["
    + "{\"key\":\"MachineSerial\",\"values\":[\"SN-40821\"]},"
    + "{\"key\":\"Assembly\",\"values\":[\"Hydraulics\",\"Pneumatics\"]}"
    + "]}";

RequestBody body = RequestBody.create(
    MediaType.parse("application/json"), json);

Request request = new Request.Builder()
    .url("https://api.nyris.io/find/v1.1")
    .post(body)
    .addHeader("x-api-key", "KEY")
    .build();

Response response = client.newCall(request).execute();

Example Minimal Response

{
    "id": "c7ac45c0165a54feb005aa2049f19235",
    "session": "c7ac45c0165a54feb005aa2049f19235",
    "results": [
        {
            "sku": "123454643",
            "score": 0.96
        },
        {
            "sku": "123454644",
            "score": 0.92
        },
        {
            "sku": "123454645",
            "score": 0.88
        },
        {
            "sku": "123454646",
            "score": 0.83
        }
    ]
}

Example Full Response

{
    "id": "c7ac45c0165a54feb005aa2049f19235",
    "session": "c7ac45c0165a54feb005aa2049f19235",
    "results": [{
        "title": "test product",
        "descriptionShort": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
        "descriptionLong": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
        "language": "de-DE",
        "brand": "test brand",
        "catalogNumbers": ["test_catalog_number_0", "test_catalog_number_1"],
        "customIds": {
            "DEMO_CUSTOM_ID": "DEMO_ID_123"
        },
        "keywords": ["demo", "demonstration", "test"],
        "categories": ["Demo", "Test"],
        "availability": "in stock",
        "feedId": "1",
        "groupId": "1",
        "price": "10.00 EUR",
        "salePrice": "1.00 EUR",
        "links": {
            "main": "https://example.com/product/123",
            "mobile": "https://example.com/product/123/thumbnail.jpg"
        },
        "images": ["https://img.nyris.io/example1.jpg", "https://img.nyris.io/example2.jpg"],
        "metadata": "This product is for demonstrations only",
        "sku": "123456",
        "score": 1,
        "filters": {
            "color": ["Red"],
            "product": ["Shoes"]
        }
    }]
}

Geolocation

If products have geolocation data, you can narrow results by distance. Coordinates must be in WGS84 format.

When using multipart/form-data (for filters), pass geolocation as form fields. Otherwise, use query parameters: POST https://api.nyris.io/find/v1.1?lat=LAT&lon=LON&dist=DIST.

Name | Example | Explanation --|--|-- lat | 52.5200 | The latitude of the user. lon | 13.4050 | The longitude of the user. dist | 10000 | The maximum distance from the center in meters.

Regions API

The Find API matches on the entire image. For images containing multiple objects, you may want to detect and crop to specific areas first. The Regions API identifies parts of the image likely to contain relevant objects, allowing your UI to propose sections of the image for the user to search with.

POST https://api.nyris.io/find/v2/regions

Request Headers

Key | Value ---|--- X-Api-Key | The API key provided by us. Content-Type | image/jpeg, image/png, multipart/form-data, or application/json (base64). Content-Length | The size of image in bytes (for binary uploads).

Request Body

  • Binary: send the raw image bytes as the request body with Content-Type: image/jpeg or image/png.
  • Multipart: use multipart/form-data and include the image as a file field named image.
  • JSON body (base64): send Content-Type: application/json with a JSON object containing the image as a base64-encoded string.

JSON Body Schema

Field | Type | Required | Description ---|---|---|--- image | String | Yes | Base64-encoded image (plain or data URI).

Response Format

The response contains a regions array. Each region has a confidence score (0–1) and a bounding box with pixel coordinates relative to the submitted image.

Property | Description ---|--- confidence | Confidence value (0..1) that an object was detected at this location. region.top | Top-most coordinate in pixels (floating point). region.left | Left-most coordinate in pixels (floating point). region.bottom | Bottom-most coordinate in pixels (floating point). region.right | Right-most coordinate in pixels (floating point).

Example Request

POST
https://api.nyris.io/find/v2/regions
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://api.nyris.io/find/v2/regions")
  .post(null)
  .addHeader("x-api-key", "KEY")
  .addHeader("content-type", "image/jpeg")
  .addHeader("content-length", "image-file-size-in-bytes")
  .addHeader("cache-control", "no-cache")
  .build();

Response response = client.newCall(request).execute();

Example with JSON Body (Base64)

POST
https://api.nyris.io/find/v2/regions
{
    "image": "/9j/4AAQSkZJRg..."
}
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

OkHttpClient client = new OkHttpClient();

byte[] imageBytes = Files.readAllBytes(Path.of("image.jpg"));
String imageB64 = Base64.getEncoder().encodeToString(imageBytes);
String json = "{\"image\":\"" + imageB64 + "\"}";

RequestBody body = RequestBody.create(
    MediaType.parse("application/json"), json);

Request request = new Request.Builder()
    .url("https://api.nyris.io/find/v2/regions")
    .post(body)
    .addHeader("x-api-key", "KEY")
    .build();

Response response = client.newCall(request).execute();

Example Response

{
    "regions": [
        {
            "confidence": 0.8876233,
            "region": {
                "top": 43.0,
                "left": 153.0,
                "bottom": 577.0,
                "right": 427.0
            }
        }
    ]
}

Recommend API

Get visually similar items for a product in your catalogue by submitting its SKU. Since we already have your product data (from the feed import), we perform a visual similarity search based on the main image of the given product. The submitted SKU itself is excluded from results.

GET https://api.nyris.io/recommend/v1/{sku}

Request Headers

Key | Value ---|--- X-Api-Key | The API key provided by us. Accept | (Optional) application/items.complete+json for full response. Accept-Language | (Optional) Filter results by language, e.g. de,*;q=0.5.

Path Parameters

Name | Example | Explanation ---|---|--- sku | 03764560 | The SKU of the product to find recommendations for.

Example Response

GET
https://api.nyris.io/recommend/v1/{sku}
{
    "id": "575e838883cf5e60859889c112b1463e",
    "session": "575e838883cf5e60859889c112b1463e",
    "results": [
        {
            "sku": "123454643",
            "image": "https://img.nyris.io/example.jpg",
            "score": 0.96
        },
        {
            "sku": "123454644",
            "image": "https://img.nyris.io/example2.jpg",
            "score": 0.92
        }
    ]
}

Images API

Retrieve the public images associated with a product by its SKU.

GET https://api.nyris.io/find/v1.1/images/{sku}

Request Headers

Key | Value ---|--- X-Api-Key | The API key provided by us. Accept | application/items.complete+json

Path Parameters

Name | Example | Explanation ---|---|--- sku | D005 | The SKU of the product to retrieve images for.

Example Response

GET
https://api.nyris.io/find/v1.1/images/{sku}
{
    "images": [
        "https://img.nyris.io/7bb/7bb5d2940a23084f307ed9a4bf8d74c6e03cf38cd10ca1e909eb6205774629ff.jpg"
    ]
}

Filter API

Retrieve the available filter attributes that can be used with the Find API.

GET https://api.nyris.io/find/v1.1/filters

Request Headers

Key | Value ---|--- X-Api-Key | The API key provided by us. Accept | application/items.complete+json

Example Response

GET
https://api.nyris.io/find/v1.1/filters
{
    "filters": [
        {
            "filterType": "color",
            "filterValues": ["Red", "Blue", "Green", "Black", "White"]
        },
        {
            "filterType": "category",
            "filterValues": ["Shoes", "Bags", "Accessories"]
        }
    ]
}

Widget (JS)

The fastest and easiest way to integrate visual search to your website is using our Javascript Widget. All you have to do is to add some lines of code to a runtime file of your website and you are ready to start using visual search.

What I need to start using this code?

You need to follow these steps:

  1. Copy the script into a text editor and configure the settings parameters.
  1. After making the necessary updates, copy all the lines and add to the runtime file (ex. index.html) to embed the visual search widget into your platform.

Done. You are ready to use visual search on your website!

Sample

See the nyris demo widget in action: https://widget.nyris.app/

Where is the source code? Can I change it

The code is on github. Follow the readme file to build the project. You can change or adjust the JS / CSS files according to your needs and host them on your server as well.

Android SDK

You can find the latest Android SDK including the implementation documentation on github:

https://github.com/nyris/SDK.Android

iOS SDK

You can find the latest iOS SDK including the implementation documentation on github:

https://github.com/nyris/Nyris.IMX.iOS

Should you have any questions, please send and e-mail to support@nyris.io

Submit your product data

There are several ways to submit your product and image data to us. You can provide any kind of structured file that we can pull (xml, csv, txt, json, etc.), or use the Data Management API to programmatically manage your items and images. If you are already providing your data to an affiliate network like Affilinet, Awin or Google Shopping, you are probably all set for the start. In this case we just need access to your feed URL. Please be aware that those feeds usually only include the link to the main product image. As image recognition works best the more images of a specific product we have, you might need to adjust those feeds to include all your product images. Please find more details below.

Feed Format & Updates

  • The feed can be submitted as csv, xml, txt or json file
  • Preferred encoding for the files is UTF-8
  • For csv, please use if possible "," as delimiter and " " for enclosing text
  • Please provide us with a link to your feed. If the access to the feed is secured with username/password, please also provide us those credentials
  • Please revise your server seetings in order to ensure that the IP address we use to access your server remains unblocked at all times in spite of frequent accessing
  • You feed will be imported daily. Should you need shorter import cycles, please contact support@nyris.io

If you don't have a product feed, we can also directly access your product data trough an API for the following systems:

Shop Systems.

  • BigCommerce
  • Magento 1.x SOAP
  • PrestaShop
  • Shopify
  • WooCommerce

PIM

  • Akeneo
  • hybris

You can also create a data feed using Google Sheets. Details on how to use Goole Sheets and an example file can be found in a section below.

Data Management API

The Data Management API lets you programmatically manage items and images in your nyris index. Use it to create, update, list, and delete product data and associated images.

The Data Management API requires a separate API key. For security, the keys used for the Find API and Recommend API do not work with the Data Management API, and vice versa. Contact mailto:support@nyris.io to obtain your Data API key.

The full OpenAPI reference is available at api.nyris.io/manage/swagger.

Authentication

All Data Management API requests require an API key passed via the X-Api-Key header. This key is different from the one used for the Find and Recommend APIs.

Key | Value ---|--- X-Api-Key | Your Data Management API key (not the same as the Find API key).

Create an Item

Creates a new item in your index. The key field is required and must be unique within your index.

POST
https://api.nyris.io/manage/v1/items

Example Request

{
    "key": "product-001",
    "text": {
        "name": "Red Running Shoe",
        "description": "Lightweight running shoe in red",
        "brand": "ExampleBrand",
        "language": "en-US"
    },
    "category": ["Shoes", "Running"],
    "links": {
        "main": "https://example.com/products/product-001"
    },
    "price": {
        "value": 89.99,
        "currency": "EUR"
    }
}

Example Response

{
    "id": "18b7f87a-1577-4486-a680-a460d970b584",
    "indexId": "adc23661-bc7f-4514-875e-c60d1ac61b93",
    "key": "product-001",
    "text": {
        "name": "Red Running Shoe",
        "description": "Lightweight running shoe in red",
        "brand": "ExampleBrand",
        "language": "en-US"
    },
    "category": ["Shoes", "Running"],
    "links": {
        "main": "https://example.com/products/product-001"
    },
    "price": {
        "value": 89.99,
        "currency": "EUR"
    },
    "images": [],
    "created": "2026-03-19T12:00:00Z",
    "modified": "2026-03-19T12:00:00Z"
}

Upsert an Item

Creates an item if the key does not exist yet, or updates the existing item. This is the recommended way to keep your index in sync with your product catalog.

The request body is the same as for creating an item. Returns 201 if a new item was created, 200 if an existing item was updated.

PUT
https://api.nyris.io/manage/v1/items

List Items

Returns a paginated list of items in your index.

Name | Type | Description ---|---|--- size | integer | Number of items per page (optional). pageToken | uuid | Token for the next page (from a previous response). sort | string | Sort by UpdateDate, CreationDate, or UniqueKey. order | string | Ascending or Descending.

GET
https://api.nyris.io/manage/v1/items

Example Response

{
    "items": [
        {
            "id": "18b7f87a-1577-4486-a680-a460d970b584",
            "key": "product-001",
            "text": { "name": "Red Running Shoe" },
            "images": [],
            "created": "2026-03-19T12:00:00Z",
            "modified": "2026-03-19T12:00:00Z"
        }
    ],
    "pageToken": "18b7f87a-1577-4486-a680-a460d970b584",
    "nextPageToken": "29c5bf8b-2688-5597-b791-991443195695"
}

Get Item by Key

Retrieves a single item using your unique key.

GET
https://api.nyris.io/manage/v1/items/by-key?key={key}

Delete an Item

Deletes an item by its unique key. All associated images are also removed.

DELETE
https://api.nyris.io/manage/v1/items?key={key}

Add an Image to an Item

Adds an image to an existing item, identified by its key. You can provide the image as a URL (JSON body) or upload it directly (multipart/form-data or raw image bytes).

POST
https://api.nyris.io/manage/v1/items/by-key/images?key={key}

JSON body (image from URL)

{
    "url": "https://example.com/images/product-001.jpg",
    "visible": true,
    "main": true
}

Example Response

{
    "id": "63a4ac04-d267-442c-9be4-880332084127",
    "indexId": "adc23661-bc7f-4514-875e-c60d1ac61b93",
    "itemId": "18b7f87a-1577-4486-a680-a460d970b584",
    "url": "https://example.com/images/product-001.jpg",
    "visible": true,
    "main": true,
    "created": "2026-03-19T12:01:00Z"
}

Get Images for an Item

Returns all images belonging to an item.

GET
https://api.nyris.io/manage/v1/items/by-key/images?key={key}

Delete an Image

Removes a specific image by its ID.

DELETE
https://api.nyris.io/manage/v1/images/{id}

Full API Reference

The complete OpenAPI specification, including all endpoints, schemas, and error codes, is available in the interactive Swagger documentation:

api.nyris.io/manage/swagger

You can also import the OpenAPI spec directly into Postman or other API tools using the JSON URL:

https://api.nyris.io/manage/swagger/v1/swagger.json

Available Feed Attributes

The bare minimum is a unique ID (sku) and the main_image_link. To get a full list of possible attributes please download the following sheet or use a copy of it as base for your item or product feed. When gathering your data, please keep always in mind that all submitted information will be used for improving your search results. Completeness and quality of data often makes the difference:

Download Feed Example and full attribute description (google sheets)

Required Fields

| Attribute | Example | Comment | |---|---|---| | sku | sku1 | unique item or product identifier (e.g. EAN code) | | main_image_link | https://storage.googleapis.com/nyris/share/image_a1.png | main image link. should be publicly available. ideally, product in question should be at the center of the image |

Optional Fields

Image Links

To improve the search, additional images can be provided. All referenced images (main, additional and recognition types) are used for search. main and additional images are treated identically, with the main image being the designated reference to be shown e.g. in the Portal. If requested, these image links can be returned as part of the response. recognition image links, on the other hand, are purely used for recognition and are never returned as part of any response.

Attribute | Example | Comment ---|---|--- additional_image_link_0 | https://storage.googleapis.com/nyris/share/image_a1.png | additional images additional_image_link_1 | | additional images additional_image_link_N | | Nth additional image recognition_image_link_0 | | additional recognition images (images that will never show up on frontend) ideally taken from different angles and w/o packaging recognition_image_link_1 | https://storage.googleapis.com/nyris/share/image_r1.png | additional recognition images (images that will never show up on frontend** ideally taken from different angles and w/o packaging recognition_image_link_N | | Nth additional recognition image

Textual description

Providing these values will enable both OCR (text matching) functionality, finer grained recognition of results and item class distribution results. While optional, providing these values is thus strongly recommended.

Attribute | Example | Comment ---|---|--- title | title 1 | Product or item title (supports OCR recognition step) brand | brand 1 | Brand (supports brand recogntion step) description_short | description short 1 | Short description (supports OCR recognition step) description_long | description long 1 | Long description (supports OCR recognition step) custom_category | cat1 > cat2 | your product or item category. Please separate with > (e.g. building materials, wood, windows & doors > windows > window ledges). Providing this field will be used to improve recommendations. language | de-DE | Language Culture Name (https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/db9b9b72-b10b-4e7e-844c-09f88c972219)

Key-value pairs

By providing custom key-value pairs, we are able to improve detection in combination with text matching functionality, and/or will be able to return named IDs as part of the response. If your system requires multiple IDs or custom data pairs, use these fields.

Attribute | Example | Comment ---|---|--- custom_id_key_0 | pzn | custom ID key (e.g. for Barcode recognition) and custom_id_value_0 | 123456 | custom ID value (e.g. for Barcode recognition), custom_id_key_N | pzn | Nth custom ID key and custom_id_value_N | 123456 | Nth custom ID value

Catalog numbers

These values are mainly used for identifying products within catalogs, and catalogs by IDs.

Attribute | Example | Comment ---|---|--- catalog_number_0 | 3306 | catalog numbers from your printed advertisment. Used by PDF importer catalog_number_1 | cat1 | catalog numbers from your printed advertisment. Used by PDF importer catalog_number_N | ... | Nth catalog number

Keywords

These values are used for exactly matching keywords, such as item materials, colors, etc., with text found during OCR; thus, providing these values improves text matching. Keywords are treated as a set, so values specified multiple times would be considered identical.

To simplify specification of keywords, you can specify keywords in a delimiter-separated list via the configurable keywords column. By default, keywords are split at the , (comma) delimiter:

Attribute | Example | Comment ---|---|--- keywords | keyword, keyword, keyword 2 | Registers the two keywords keyword and keyword 2 keyword(",") | keyword 1, keyword 2 | Registers the two keywords keyword 1 and keyword 2 keyword("AND") | keyword 1 AND keyword 2 | Registers the two keywords keyword 1 and keyword 2

To provide single keywords or individual keywords per column, use the keyword / keyword_N variant instead. Here, values are not split:

Attribute | Example | Comment ---|---|--- keyword | a nice, individual keyword | Registers the keyword a nice, individual keyword keyword_0 | keyword 0 | The first keyword in a set keyword_1 | keyword 1 | The second keyword in a set keyword_N | ... | The Nth keyword in a set

Geolocation Fields

If provided, the coordinates can be used to narrow down the search by the location of the product. The provided coordinates have to be in the WGS84 format with signed decimal numbers as the notation.

Attribute | Example | Comment ---|---|--- latitude | 52.5200 | Latitude of the product. Use together with longitude to associate the product with a location. longitude | 13.4050 | Longitude of the product. Use together with latitude to associate the product with a location.

Item relations

Some items are related to other entries, and some IDs may have different meaning across logical separations of feeds (e.g. when there is a feed per country).

Attribute | Example | Comment ---|---|--- feed_id | 1 | Feed ID, required only if you have multiple feeds as one merchant. The value has to be an integer. group_id | 23 | for variation products (size, colour etc. variations)

Item URLs

Attribute | Example | Comment ---|---|--- main_offer_link | https://www.nyris.io/products/visual-search-api | product or landing page link mobile_offer_link | https://vimeo.com/788577734 | secondary product or landing page link (mobile, video etc.)

PreFilter Attributes

Attribute | Example | Comment ---|---|--- filter_key_0 | color | filter key used by faceted search and filter_value_0 | Red,Blue | comma separated filter values for the key for the item, filter_key_N | shape | Nth filter key (Max N = 10)and filter_value_N | candle,capsule | Nth filter values for the item

Other Optional Fields

Attribute | Example | Comment ---|---|--- meta_data | some additional text data | any data you would like to store additionally (text field); the content is not interpreted availability | in stock | valid values: in stock, out of stock, preorder, back in stock soon, removed price | 17.30 EUR | . as decimal, 3-digit ISO Code for currency sale_price | 15.00 EUR | . as decimal, 3-digit ISO Code for currency image_version | 1234 | image version; if changed, images will be re-imported

Visual search analytics show how customers interact with search results and help improve search performance over time.

Nyris provides two levels of analytics:

| Type | Merchant implementation | What you get | |---|---|---| | General usage & index analytics | None required | Search volume, product count, image count in your index | | Click & conversion analytics | Required (see below) | Which results were clicked, which led to conversions, tied to each search request_id |

This document covers click & conversion analytics — how to send customer events to the Nyris Feedback API.


What the script does

Once embedded, the script:

  • intercepts Nyris Find API responses and captures the request_id of each search,
  • detects clicks on search-result cards and CTA buttons,
  • detects add-to-cart actions by configurable button labels,
  • forwards conversions declared via HTML attributes, JavaScript, or your GA4 dataLayer,
  • and posts events to the Feedback API, keyed to the originating search.

It requires no changes to your store's source code in the typical case and is built so it cannot break the host page (all logic is error-isolated).

Quick start

Place the tag in the <head>. async is recommended.

Minimal — only the API key is required:

Typical commerce setup — configure result cards, product ids, and add-to-cart labels:

With this markup, a click on the card (or its link) is reported as a click, and a click on the add-to-cart button is reported as a conversion — both carrying the product id:

<script
  async
  src="https://assets.nyris.io/nyris-tracking/v1/nyris-tracker.min.js"
  data-api-key="YOUR_NYRIS_API_KEY">
</script>
<script
  async
  src="https://assets.nyris.io/nyris-tracking/v1/nyris-tracker.min.js"
  data-api-key="YOUR_NYRIS_API_KEY"
  data-results-selector=".product-card"
  data-product-id-attr="data-product-id"
  data-cart-button-labels="Add to cart,In den Warenkorb">
</script>
<div class="product-card" data-product-id="SKU-9987">
  <a href="/products/sku-9987">Trail Runner Jacket</a>
  <button type="button">Add to cart</button>
</div>

Prerequisites

The script works when the browser calls the Nyris Find API directly (https://api.nyris.io/find/...). It intercepts those responses to obtain the request_id.

If your store proxies search through your own backend and never calls the Find API from the browser, inject the request id into the results container instead:

Without a request_id (from interception or data-nyris-request-id), click and conversion events are not sent.

<div id="search-results" data-nyris-request-id="REQUEST_ID_FROM_SERVER">
  <!-- result cards -->
</div>

Product id resolution

The tracker resolves the product id for each result card in this order:

  1. Attribute — value of data-product-id-attr on (or inside) the card (default: data-product-id).
  2. Text — trimmed text of data-product-text-selector, if configured.
  3. Position — SKU at the same zero-based position in the Find API response (no DOM markup required).

For most stores the position fallback works out of the box when result order matches the API response.

Declaring purchases

Add-to-cart is detected automatically from button labels. Purchases happen on the order-confirmation page and must be declared once the order is known.

HTML attributes:

JavaScript API:

Custom DOM event (useful with tag managers):

If you already send GA4 e-commerce events to window.dataLayer, enable the GA4 bridge (default) to mirror add_to_cart and purchase events automatically.

<button
  data-nyris-conversion="purchase"
  data-nyris-product-ids="SKU-9987,SKU-1234"
  data-nyris-order-id="ORD-123"
  data-nyris-revenue-amount="49.99"
  data-nyris-revenue-currency="EUR">
  Complete purchase
</button>

Configuration reference

Set options as data-* attributes on the script tag, or as window.nyrisTrackerConfig before the script loads.

| data-* attribute | nyrisTrackerConfig key | Default | Description | |---|---|---|---| | data-api-key | apiKey | — (required) | Nyris API key. Sent as X-Api-Key. | | data-results-selector | resultsSelector | .product-card | CSS selector for a single search-result card. | | data-results-container | resultsContainer | document.body | Scope where results live. | | data-product-id-attr | productIdAttr | data-product-id | Attribute holding the product id/SKU. | | data-product-text-selector | productTextSelector | none | CSS selector whose text is the product id. | | data-cart-button-labels | cartButtonLabels | Add to cart,Add to basket,In den Warenkorb | Comma-separated, case-insensitive add-to-cart labels. Replaces defaults when set. | | data-mode | mode | cookiefree | cookiefree or full. See GDPR modes. | | data-attribution-window-minutes | attributionWindowMinutes | 30 | How long a search stays eligible for attributed conversions. | | data-ga4-bridge | ga4Bridge | true | Bidirectional GA4 dataLayer integration. | | data-feedback-url | feedbackUrl | https://api.nyris.io/feedback/v1 | Override endpoint (restricted to api.nyris.io/feedback/). | | data-debug | debug | false | Log [NyrisTracker] messages to the console. |

window.nyrisTrackerConfig example:

<script>
  window.nyrisTrackerConfig = {
    apiKey: 'YOUR_NYRIS_API_KEY',
    resultsSelector: '.search-result',
    cartButtonLabels: ['Add to cart', 'Buy now'],
  };
</script>
<script async src="https://assets.nyris.io/nyris-tracking/v1/nyris-tracker.min.js"></script>

JavaScript API

| Method | Description | |---|---| | NyrisTracker.conversion(subtype, options) | Report a conversion. options: product_ids, positions, quantity, revenue. | | NyrisTracker.grantConsent() | Switch to full mode after cookie consent. | | NyrisTracker.getRequestId() | Current Nyris request_id, or null. |

GDPR modes

| Mode | Storage | Consent | Notes | |---|---|---|---| | cookiefree (default) | sessionStorage, else in-memory | Not required | No cookies, no persistent visitor id. | | full | localStorage | Required | Call NyrisTracker.grantConsent() after opt-in. |

The default cookiefree mode uses no cookies and no cross-session identifier. Confirm with your DPO whether a consent banner is required for your jurisdiction.

Debugging

Enable debug output while integrating:

Then open the browser console and look for [NyrisTracker] initialized, search captured, click, and add_to_cart / conversion messages.

data-debug="true"

When the script is not enough

Use the raw Feedback API implementation below if you:

  • cannot call the Find API from the browser,
  • need full control over event timing and payloads,
  • integrate from a mobile app or server-side system, or
  • already have your own analytics pipeline and only need to forward events.

2. Alternative: Raw Feedback API implementation

Implement click and conversion analytics yourself by POSTing JSON events to the Feedback API. Use this path when you cannot embed the tracking script or need a custom integration.

Overview

Every Find API response includes a unique request id and optionally a session id:

| Source | Header | JSON body fallback | |---|---|---| | Request id | X-Matching-Request | id | | Session id | X-Session | session |

Store the request id when you receive search results. Attach it to every subsequent click or conversion event for that search.

Perform a Find API search first (see Find API documentation), then POST events to the Feedback API using the same API key.

Endpoint

POST https://api.nyris.io/feedback/v1

Request headers

| Header | Value | |---|---| | X-Api-Key | Your Nyris API key | | Content-Type | application/json, application/event+json, or text/json |

Request body

Every event is a JSON object with these fields:

| Property | Required | Description | |---|---|---| | request_id | Yes | Request id from the Find API response | | session_id | No | Session id from the Find API response. Groups multiple searches from the same user. | | timestamp | Yes | Event time in ISO 8601 UTC, e.g. 2020-11-06T17:53:25.511Z | | event | Yes | Event type: click, conversion, feedback, or region | | data | Depends on event | Event-specific payload (see below) |

A successful POST returns HTTP 2xx. Invalid JSON or missing required fields may return an error.

Event types

| event value | Purpose | |---|---| | click | User clicked or selected a result (position and/or product id) | | conversion | A result led to business value (e.g. add to cart, purchase) | | feedback | End-user feedback on the result set ("Did we find what you were looking for?") |


Click events

Tracks which result the user interacted with.

data properties:

| Property | Type | Description | |---|---|---| | product_ids | string[] | Product ids as in your product data / Find API SKUs | | positions | number[] | Zero-based index in the Find API result list |

Provide product ids where possible — they remain accurate even if the frontend reorders or filters results.

Example:


{
  "request_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "session_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "timestamp": "2020-11-06T17:53:25.511Z",
  "event": "click",
  "data": {
    "positions": [0],
    "product_ids": ["1234"]
  }
}

Conversion events

Tracks that a search result led to a conversion (add to cart, purchase, product view, etc.).

data properties:

| Property | Type | Description | |---|---|---| | product_ids | string[] | Product ids involved in the conversion | | positions | number[] | Zero-based positions in the original result list | | quantity | number | Optional item quantity |

The data field is optional. A conversion with no data still marks the request as successful if a prior click event was sent for the same request_id.

Example (with product data):

Example (minimal — relies on prior click):

The tracking script may send a subtype field inside data (e.g. add_to_cart, purchase) to distinguish conversion types. The Feedback API currently ignores subtype — it does not return an error, but the value is not stored or surfaced in analytics yet. Support for subtypes is planned.

Until then, treat all conversion events equally and include product_ids and positions in data where available. Do not rely on subtype for reporting.


{
  "request_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "session_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "timestamp": "2020-11-06T17:53:25.511Z",
  "event": "conversion",
  "data": {
    "positions": [0],
    "product_ids": ["1234"],
    "quantity": 1
  }
}
{
  "request_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "session_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "timestamp": "2020-11-06T17:53:25.511Z",
  "event": "conversion"
}

Feedback events

End-user feedback on the overall result set, e.g. from a "Did we find what you were looking for?" prompt.

data properties:

| Property | Type | Description | |---|---|---| | success | boolean | Whether the search was successful from the user's perspective | | comment | string | Optional free-text comment |

Where possible, also send click and conversion events — they provide automatic, behaviour-based feedback.

Example:


{
  "request_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "session_id": "e8848827-27af-41d7-a98f-1a2f94b0f19a",
  "timestamp": "2020-11-06T17:53:25.511Z",
  "event": "feedback",
  "data": {
    "success": true,
    "comment": "Thank you!"
  }
}

Implementation checklist (raw)

  1. Capture ids — On every Find API response, read X-Matching-Request / X-Session (or id / session from the JSON body if headers are not exposed).
  2. Store ids — Keep the request id available for the user's session (in memory, session storage, or your backend).
  3. Send click — When the user clicks a result, POST a click event with product_ids and positions.
  4. Send conversion — When the user converts (cart, purchase, etc.), POST a conversion event with the same request_id and relevant product_ids.
  5. Send feedback — If your UI collects explicit feedback, POST a feedback event as applicable.

Product ids must match the SKUs in your product data and Find API results, or Nyris cannot correlate events with your catalogue.


Example: end-to-end with curl

All event types should return HTTP 2xx when the payload is valid.

Show examples in:
nyris
nyris API Docs