Skip to main content

Items Engagement API Reference

Overview

The Items Engagement endpoints provide access to engagement metrics and popularity scores for directory items. These include view counts, votes, ratings, favorites, and comments. The popularity scores endpoint additionally computes a weighted ranking that factors in engagement metrics, featured status, and content recency.

Endpoints

GET /api/items/engagement

Fetches engagement metrics for multiple items by their slugs in a single batch request.

Request

ParameterTypeInDescription
slugsstringqueryComma-separated list of item slugs (required, max 200)

Response

{
metrics: Record<string, {
views: number;
votes: number;
avgRating: number;
favorites: number;
comments: number;
}>;
}

Example

const response = await fetch('/api/items/engagement?slugs=item-one,item-two,item-three');
const { metrics } = await response.json();

// metrics["item-one"] = { views: 1500, votes: 42, avgRating: 4.2, favorites: 18, comments: 7 }

GET /api/items/popularity-scores

Debug endpoint that returns items sorted by computed popularity score with a detailed breakdown of scoring factors. Useful for understanding how the sorting algorithm ranks items.

Request

ParameterTypeInDescription
limitnumberqueryNumber of items to return (default: 20, max: 100)
localestringqueryLanguage code for items (default: "en")

Response

{
totalItems: number;
showing: number;
items: Array<{
rank: number;
name: string;
slug: string;
featured: boolean;
score: number; // Total computed score (rounded)
scoreBreakdown: {
featured: number; // 10000 if featured, 0 otherwise
views: number; // log10(views + 1) * 1000
votes: number; // log10(votes + 1) * 1200
rating: number; // avgRating * 500
favorites: number; // log10(favorites + 1) * 1100
comments: number; // log10(comments + 1) * 1000
recency: number; // Decays over 180 days
};
engagement: {
views: number;
votes: number;
avgRating: number;
favorites: number;
comments: number;
} | null;
ageInDays: number;
}>;
}

Example

const response = await fetch('/api/items/popularity-scores?limit=10&locale=en');
const { items, totalItems } = await response.json();

// items[0] = { rank: 1, name: "Top Item", score: 15234, scoreBreakdown: { ... }, ... }

Authentication

Both endpoints are public -- no authentication is required. They are marked as force-dynamic to ensure fresh data on every request.

Error Responses

StatusDescription
400Missing required slugs parameter or more than 200 slugs provided (engagement endpoint)
500Internal server error -- database query failure

Rate Limiting

No explicit rate limiting. The engagement endpoint caps batch size at 200 slugs per request to prevent abuse. Both endpoints bypass Next.js caching via export const dynamic = 'force-dynamic'.