Quickstart

In this guide, we will speed-run through getting a development environment set up and have you create an ad and run an auction. It is intended for developers who want to experiment with and get to know, Kleio.

Start Kleio

Create a folder on your computer (you can call it kleio if you want). In it, copy and paste the following content into a file you call compose.yaml:

kleio/compose.yaml
services:
  kleio:
    image: getkleio/kleio:latest
    ports:
      - 8000:8000
    environment:
      SECRET_KEY_BASE: rlZ6+ueWM4n/cqbOHDjFTrCuL1dkzxpX1clY0ncyN2AW4bsTObj7tQv1O/Nx2n3J
      DATABASE_URL: ecto://kleio:password@postgres/kleio
      HOST: localhost
      PORT: 8000
      MEILISEARCH_ENDPOINT: http://meilisearch:7700
      MEILISEARCH_NUM_ADS: 2
      MEILISEARCH_LIMIT_INCREASE: 50
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8000/up || exit 1"]
      start_period: 10s
      interval: 1s
      timeout: 1s
      retries: 10

  postgres:
    image: postgres:16
    ports:
      - 5432:5432
    volumes:
      - kleio-postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: kleio
      POSTGRES_DB: kleio
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
      start_period: 10s
      interval: 1s
      timeout: 1s
      retries: 5

volumes:
  kleio-postgres-data:

Adding an ad

We'll jump straight into adding an ad to our system. Ads are associated with products, but Kleio takes care of managing the products for us.

POST
/api/v1/ads
curl -H "Content-Type: application/json" \
  --data '{"product_id": "racing-bike-1", "max_bid": 100}' \
  http://localhost:8000/api/v1/ads

Running an auction

Let's go straight ahead and run an auction! No one is claiming it will be an interesting auction (there's only one candidate ad after all...), but an auction is an auction after all!

POST
/api/v1/auction
curl -H "Content-Type: application/json" \
  --data '{}' \
  http://localhost:8000/api/v1/auction

What you get returned from the auction is the set of ads that won the auction. In this instance, the payload looks something like this:

Response

{
  "data": [
    {
      "product_id": "racing-bike-1",
      "ad_id": "a631ae3c-936f-472a-ad13-960ecc9a0b03",
      "bid": 1,
      "tracking_code": "9yj_krpBkNalEdOUjxvQRXKsW_wnzEdtwfiDbIim7o8ApjGuPJNvRyqtE5YOzJoLA99pUMGmOEb0ngXHcm5GzjMAAAAAAAAAAQAAAABlTNNm"
    }
  ]
}

We notice a couple of things straight away:

  • the bid is incredibly low
  • the payload includes a tracking_code

The bid value contains the winning bid of the auction. I.e. if the ad converts (the product is clicked on, or sold – you define what it means to convert in your context) the advertiser will be charged a monetary value of 1. The reason the value is so low is two-fold: there was no competition, and we didn't specify a floor price. You can read more about both of these points in the full documentation for the auction endpoint.

The tracking_code is what we'll need in the next step. Please note that yours will be different from the one in the example above. The tracking code is unique to an auction and to the ad that won the auction.

Tracking impressions and conversions

Let's track that we showed the ad, i.e an impressions:

POST
/api/v1/track/impression/<tracking_code>
curl -X POST \
  http://localhost:8000/api/v1/track/impression/9yj_krpBkNalEdOUjxvQRXKsW_wnzEdtwfiDbIim7o8ApjGuPJNvRyqtE5YOzJoLA99pUMGmOEb0ngXHcm5GzjMAAAAAAAAAAQAAAABlTNNm

and then that a conversion took place:

POST
/api/v1/track/conversion/<tracking_code>
curl -X POST \
  http://localhost:8000/api/v1/track/conversion/9yj_krpBkNalEdOUjxvQRXKsW_wnzEdtwfiDbIim7o8ApjGuPJNvRyqtE5YOzJoLA99pUMGmOEb0ngXHcm5GzjMAAAAAAAAAAQAAAABlTNNm

In neither case, you'll receive anything but an empty response with an HTTP status code of 200.

Getting the tracking right is important. Without tracking impressions and conversions, Kleio will not know which ads perform well and which perform poorly. As a consequence, it will also not know how to run future auctions optimally.

Cleaning up

Let's clean up after ourselves before we end this quickstart. We could delete the ad we created directly, but in this case, let's try a different API endpoint instead, deleting all ads associated with the racing-bike-1 product:

DELETE
/api/v1/product/<product_id>
curl -X DELETE \
  http://localhost:8000/api/v1/products/racing-bike-1

If you were to re-run the auction at this point, you'd notice that there are no longer any winners.

What's next?

Great! You have now created an ad, run an auction, performed tracking, and deleted your ads again. Next, you might want to:

  • Dig deeper into the ads API resource and see what other properties you might associate with an ad
  • Look at the auction API endpoint to get a sense of how you can target your auctions, limit the ads that are part of the auction, and set a floor price.