Saltar al contenido principal
Después de ejecutar una subasta de listings, a menudo querrá combinar los ganadores con resultados orgánicos. Por ejemplo, suponga que está construyendo una sección de categoría de una tienda web que también mostrará una serie de productos patrocinados. Necesitará una forma de “inyectar” sus ganadores de subasta en los resultados de categoría regulares. Esta página muestra los pasos involucrados en la construcción de tal sección de categoría, pero consideraciones similares se aplican a otras páginas o widgets.

Escenario

La sección de categoría necesita admitir paginación y mostrar 3 productos por página. Si es posible, el primer producto en cada página será un producto patrocinado. Los productos en esta página de categoría tienen la siguiente estructura:
{
  "id": "sku-367",
  "categoryId": "Shoes",
  "name": "Running shoes",
  "image": "photo_123.jpg",
  "description": "Beautiful and fast running shoes",
  "resolvedBidId": null
}
El resolvedBidId es null cuando el producto no está promovido y contiene un ID de cadena cuando lo está. Nuestro objetivo es tener el código pseudo en su lugar para un endpoint que pueda crear listas de tales productos.

1. Consultar sus resultados orgánicos

El primer paso será consultar sus resultados orgánicos. Los productos que deben mostrarse para una página y categoría específicas. El código para hacer esto podría verse así:
const pageSize = 3;
let products = queryProductsInCategory(pageSize, cursor, categoryId);

console.log(products);
Digamos que ejecutáramos este código para la primera página de la categoría Shoes, y hay 3 o más productos disponibles en esta categoría. Este código entonces generaría algo similar a esto:
[
  {
    "id": "sku-367",
    "categoryId": "Shoes",
    "name": "Running shoes",
    "image": "photo_123.jpg",
    "description": "Beautiful and fast running shoes"
  },
  {
    "id": "sku-897",
    "categoryId": "Shoes",
    "name": "Slippers",
    "image": "slippers.jpg",
    "description": "A pair of comfortable slippers"
  },
  {
    "id": "sku-343",
    "categoryId": "Shoes",
    "name": "Dress shoes",
    "image": "dress_shoe_original.jpg",
    "description": "Elegant dress shoes for formal events"
  }
]
Tenga en cuenta que estos productos aún no tienen el campo resolvedBidId, vamos a agregarlo.
const pageSize = 3;
let products = queryProductsInCategory(pageSize, cursor, categoryId);
products.forEach((prod) => {
  prod.resolvedBidId = null;
});
Ahora, sí necesitamos considerar qué sucede si no hay resultados orgánicos para esta página y categoría. Probablemente queramos devolver un error 404 y no ejecutar ninguna subasta. Esto nos da el siguiente código:
const pageSize = 3;
let products = queryProductsInCategory(pageSize, cursor, categoryId);
if (products.length === 0) {
  throw new NotFoundError("no products found");
}

products.forEach((prod) => {
  prod.resolvedBidId = null;
});
Con este manejo de errores en su lugar, estamos listos para ejecutar una subasta.

2. Ejecutar una subasta

En nuestro escenario queremos ejecutar una subasta para un solo slot:
// skip earlier code...

const slots = 1;
const winners = runAuctionForCategory(slots, categoryId);

console.log(winners);
¿No está seguro de cómo ejecutar una subasta para una categoría? Consulte estos ejemplos.
Si hay ganadores, la salida del código anterior se vería algo así:
[
  {
    "rank": 1,
    "type": "product",
    "id": "sku-444",
    "resolvedBidId": "WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0="
  }
]
Si observa los ganadores, verá que no contienen datos de productos, solo un montón de IDs. Necesitaremos consultar los datos del producto para estos ganadores. Además, es posible que no haya ganadores. Simplemente podría ser que no haya campañas activas adecuadas para esta subasta, pero hay muchas otras razones potenciales. Independientemente, necesitamos tener en cuenta este caso y simplemente devolveremos los resultados orgánicos disponibles en products.
// skip earlier code...

const slots = 1;
const winners = runAuctionForCategory(slots, categoryId);
if (winners.length === 0) {
  return products;
}

3. Consultar datos de productos para ganadores

Ahora, cuando hay ganadores. Necesitamos consultar los datos del producto para ellos.
// skip earlier code...

const ids = winners.map((x) => x.id);
const promoProducts = queryProductsByIds(ids);

console.log(promoProducts);
Siguiendo con nuestros ejemplos anteriores, esto podría registrar algo como:
[
  {
    "id": "sku-444",
    "categoryId": "Shoes",
    "name": "Wooden clogs",
    "image": "clogs.jpg",
    "description": "Original wooden clogs."
  }
]
Nuevamente, necesitamos agregar el resolvedBidId para completar estos datos. Pero, esta vez no debemos establecerlo en null, porque ahora estamos tratando con productos promovidos. Si asumimos que queryProductsByIds devolverá productos en el mismo orden que los ids proporcionados, podemos agregar los IDs de oferta de la siguiente manera:
// skip earlier code...

const ids = winners.map((x) => x.id);
const promoProducts = queryProductsByIds(ids);
promoProducts.forEach((prod, i) => {
  prod.resolvedBidId = winners[i].resolvedBidId;
});
¿Por qué es necesario este ID de oferta? El ID de oferta es vital para permitir que Topsort atribuya eventos a ofertas y campañas.
Ahora todo lo que queda es fusionar nuestros productos promovidos con los resultados orgánicos.

4. Fusionar

Queremos mostrar los productos promovidos al principio de la lista. Para lograrlo, necesitaremos anteponer los promoProducts a los products. Sin embargo, esto puede hacer que products tenga más elementos que nuestro tamaño de página previsto de 3. Por lo tanto, necesitamos dividirlo para permanecer en este tamaño de página.
// skip earlier code...

products.unshift(...promoProducts);
return products.slice(0, pageSize);
Ahora nuestro código devuelve un máximo de 3 productos, de los cuales el primer producto puede ser un producto patrocinado.

Código completo

// query for organic products.
const pageSize = 3;
let products = queryProductsInCategory(pageSize, cursor, categoryId);
if (products.length === 0) {
  throw new NotFoundError("no products found");
}

products.forEach((prod) => {
  prod.resolvedBidId = null;
});

// run an auction.
const slots = 1;
const winners = runAuctionForCategory(slots, categoryId);
if (winners.length === 0) {
  return products;
}

// query product data for winners.
const ids = winners.map((x) => x.id);
const promoProducts = queryProductsByIds(ids);
promoProducts.forEach((prod, i) => {
  prod.resolvedBidId = winners[i].resolvedBidId;
});

// merge results.
products.unshift(...promoProducts);
return products.slice(0, pageSize);