DEV Community

Sebastian Casvean
Sebastian Casvean

Posted on • Originally published at zenndra.com

Build Read-Next Rails with Medium Related and Recommended Articles

Build Read-Next Rails with Medium Related and Recommended Articles

One article view is a bounce waiting to happen. Related and recommended endpoints let you show a second and third story without sending traffic back to medium.com.

Tool outcome: <ReadNext articleId="…" /> with 24h cache and editorial overrides.


Placement ideas


Fetch recommendations

const API = 'https://api.zenndra.com';
const headers = { Authorization: `Bearer ${process.env.ZENNDRA_API_KEY}` };

async function getReadNext(articleId) {
  const cacheKey = `readnext:${articleId}`;
  const hit = await cache.get(cacheKey);
  if (hit) return JSON.parse(hit);

  const [related, recommended] = await Promise.all([
    fetch(`${API}/article/${articleId}/related`, { headers }).then((r) => r.json()),
    fetch(`${API}/article/${articleId}/recommended`, { headers }).then((r) => r.json()),
  ]);

  const merged = dedupeById([
    ...(related.articles ?? []),
    ...(recommended.articles ?? []),
  ]).slice(0, 6);

  await cache.set(cacheKey, JSON.stringify(merged), { ex: 86400 });
  return merged;
}

function dedupeById(items) {
  const seen = new Set();
  return items.filter((a) => (seen.has(a.id) ? false : (seen.add(a.id), true)));
}
Enter fullscreen mode Exit fullscreen mode

Mix your own rules

API suggestions + product logic wins:

function rankReadNext(candidates, { sameTag, excludeIds }) {
  return candidates
    .filter((a) => !excludeIds.has(a.id))
    .sort((a, b) => (sameTag(a) === sameTag(b) ? 0 : sameTag(a) ? -1 : 1));
}
Enter fullscreen mode Exit fullscreen mode

Exclude articles the reader already opened (localStorage or your analytics).


UX metrics

Track second-page views and scroll depth on rail—not just clicks. Session depth is the attribution game when Medium was the original source.


Keywords

medium related articles api, read next widget, medium recommendations, increase time on site, medium embed engagement.


Further reading

Top comments (0)