## What is AdQuery?

**AdQuery** is a Decision API feature that filters which ads get selected based on properties of the ads. It provides **fine-grained controls on the ad request side** - think of AdQuery as querying over ads in a database and returning selections that match your query.

Say a marketplace displays sponsored listings in search results. When the marketplace's users select a price range and a category in the search (like a price between 0 and 200 and a category "lawn-care"), the marketplace makes a Decision API request that queries for those prices and category. The response will only contain ads that meet those criteria. The marketplace then integrates those ads into the search as sponsored results.

AdQuery supports a range of filtering strategies — from fine-grained attribute filters (price ranges, categories, sizes) to passing candidate product lists for [Auction-as-a-Service](https://dev.kevel.com/docs/auction-as-a-service). Pair it with [Kevel Catalog](https://dev.kevel.com/docs/catalog) to automatically sync product data into your ads.

## How AdQuery Works

AdQuery uses _creative template field values_ as queryable properties. These values must be **strings** (`"lawn-care"`), **numbers** (`24`, `26.72` etc.), or **arrays** (`["lawn-care", "tools"]`).

In order to be used for AdQuery, a creative template field must have `"AdQuery": true` set while creating or updating the creative template.

A Kevel user sets values for those fields when creating a creative template ad in the API or UI. Using the marketplace example, each seller's product would be given a creative, and queryable details from that product would be set on the creative as values.

Once an ad is live, a Decision API request makes an ad query on a placement to return any eligible ads for that query.

## Setting Up AdQuery Templates and Ads

Create a creative template with AdQuery enabled fields. _OR_ update an existing template with new AdQuery enabled fields.

To make a field enabled for AdQuery, include the parameter `"AdQuery"` set to `true`. The `Variable` of the field will become the key used for the AdQuery.

Here's an example creative template with three enabled fields:

Example Template JSON

```json
{
    "Name": "AdQuery Is Cool",
    "Description": "v1",
    "IsArchived": false,
    "Fields": [
        {
            "Name": "Product Price",
            "Description": "Product Price",
            "Required": true,
            "Variable": "ctPrice",
            "AdQuery": true,
            "Type": "Number"
        },
        {
            "Name": "Product Size",
            "Description": "Product Size",
            "Required": false,
            "Variable": "ctSize",
            "AdQuery": true,
            "Type": "String"
        },
        {
            "Name": "Product Categories",
            "Description": "Product Categories",
            "Required": false,
            "Variable": "ctCategories",
            "AdQuery": true,
            "Type": "Array"
        }
    ],
    "Contents": [
        {
            "Type": "Raw",
            "Body": "."
        }
    ]
}
```

```curl
curl -X POST \
     -H "X-Adzerk-ApiKey: $ADZERK_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{\
        "Name": "AdQuery Is Cool",\
        "Description": "v1",\
        "IsArchived": false,\
        "Fields": [\
          {\
          "Name": "Product Price",\
          "Description": "Product Price",\
          "Required": true,\
          "Variable": "ctPrice",\
          "AdQuery": true,\
          "Type": "Number"\
          },\
          {\
          "Name": "Product Size",\
          "Description": "Product Size",\
          "Required": false,\
          "Variable": "ctSize",\
          "AdQuery": true,\
          "Type": "String"\
          },\
          {\
          "Name": "Product Categories",\
          "Description": "Product Categories",\
          "Required": false,\
          "Variable": "ctCategories",\
          "AdQuery": true,\
          "Type": "Array"\
          }\
        ],\
        "Contents": [\
          {\
          "Type": "Raw",\
          "Body": "."\
          }\
        ]\
     }' \
     "https://api.kevel.co/v2/creative-templates"
```

## Creating Ads for Creatives

1. Create creatives that supply values for the AdQuery enabled fields. This creative should include the `TemplateId`, and the AdQuery values should go in the `TemplateValues`. Refer to the [creative endpoint docs](https://dev.kevel.com/reference/creative) for details.

Example Creative JSON

```json
{
    "AdvertiserId": 12345,
    "AdTypeId": 5,
    "Title": "Price: 100 Dollars!!!",
    "IsActive": true,
    "ScriptBody": "Come buy this cool thing for a Benjamin",
    "IsHTMLJS": true,
    "TemplateId": 12345,
    "TemplateValues": "{\"ctPrice\":100}"
}
```

2. Create ads for those creatives to associate them with flights.

---

## Setting Up AdQuery Decision API Requests

Make your ad queries in the `adQuery` key on the `placements` object. The key for the query is the `Variable` name of the creative template field.

You can request one or more fields to query:

Example Decision Request JSON

```json
{
    "placements": [
        {
            "networkId": 12345,
            "siteId": 12345,
            "adTypes": [
                5
            ],
            "adQuery": {
                "ctPrice": {
                    "min": 50,
                    "max": 250,
                    "nullValuesMatch": false
                },
                "ctSize": {
                    "eq": "large",
                    "nullValuesMatch": false
                },
                "ctCategories": {
                    "eq": 136933,
                    "nullValuesMatch": false
                }
            }
        }
    ]
}
```

---

## Using Arrays

Kevel customers may have Creative Template fields that have multiple sets (or ‘arrays’) of product data (eg SKU, price, brand, category). One product may belong to multiple categories in the customer's catalog and is often represented as an array of category ids.

For example, a Creative's data may be `"ctCategories": ["cat1","cat7","cat8"]`.

In an ad decision request, a Kevel customer will pass the current category of the page which ads are to be shown. AdQuery can also support returning ads for products when the category is not the only category the product belongs to.

### Phrase or `Fuzzy` Matching

AdQuery supports phrase matching on string fields. This is commonly used to match user search terms (that may contain slight misspellings or snippets of longer product names) against product details. Phrase matching is based on a lexical edit distance and phonetic algorithms.

---

## Operators

| Key | Type(s) | Usage | Example Value | Default |
| --- | --- | --- | --- | --- |
| `min` | number | The minimum of a range. | `0` | - |
| `max` | number | The maximum of a range. | `2000` | - |
| `eq` | string, number | An exact or phrase match (for strings when used with `phraseMatch` operator). Wildcard characters aren't supported. | `"Honda"` | - |
| `in` | array of strings or numbers | Match on any of the values in the array. | ` ["Honda", "Toyota", "Subaru"]` | - |
| `not` | object | Do not match on the query provided. Is used with another operator - currently `in` is supported. | `{   "in": [     "Chevrolet"   ] }` | - |
| `nullValuesMatch` | boolean | Whether to include ads where the queried field has no value | `true` | `false` |
| `phraseMatch` | boolean | Whether to include ads that have a fuzzy or inexact match with the `eq` query | `true` | `false` (exact match) |

---

> 🚧
>
> If an ad query isn't present on a Decision API request, and ad query eligible ads are candidates for that decision, **any** of the ad query eligible ads will be returned.

---

### What’s Next

- [Auction-as-a-Service: Using AdQuery to Run Ads Against Your Own Candidate Sets](https://dev.kevel.com/docs/auction-as-a-service)
- [Relevancy Score](https://dev.kevel.com/docs/relevancy-score)
