Solving Duplicate URL Slugs for Repeated Talks: A Future-Proof Approach

Created: 2025-10-15
3 min read
Loading...
Next.js
SEO
Slug
Web Development
Conference Talks

I rarely repeat talks, but while talking to other speakers I realized I might be the only one doing that, though my sample size is small. While reviewing my site I noticed something strange: one of my very first talks that I gave at Agile Testing Days 2020 opened a different event page. It turned out my slug logic used only the title, so repeating a talk created duplicate URLs. I have three repeated talks over the last five years, enough to show this is not just an edge case but something that needed a scalable fix for SEO and usability.

Here is how I fixed multiple talks with the exact same title produced identical slugs and thus conflicting URLs in a future-proof way that is also SEO-friendly.

The Problem

I rarely give the same talk with the same title. Since my slug logic generated URLs based on the title, this happened:

  • Speeding up your test execution in a fast-paced world (2021-02-23, Online) > /talks/speeding-up-your-test-execution-in-a-fast-paced-world
  • Same talk, different event/date (2020-11-10, Agile Testing Days) > same slug!

This caused:

  • Clashing pages
  • SEO confusion
  • Confused user

Classic approaches, like appending the year or city, fail if you repeat talks more than once in a year or at the same place. Adding the conference or event name would solve this on a first thought but it is still possible that the event is the same (e.g. "Online", "Webinar"). Another reason against this is that the URLs would get even longer which I want to avoid.

The Requirements

  • No breakage of existing or "canonical" links (SEO + old bookmarks).
  • For every future duplicate: URLs must always be unique and stable.
  • Zero manual maintenance. No hand-editing slugs or special cases.

The Solution: Unique Slugs via ID Suffix

Rather than rely on talk metadata that might itself collide, I leveraged a data property I know is always unique: the database (array) id field.

  • First occurrence: Keeps the original pretty slug (great for established links and nice URLs).
  • Subsequent duplicates: Get the slug plus ID: e.g., /talks/speeding-up-your-test-execution-in-a-fast-paced-world-10

With this approach, even if I give a talk with the same title 30 times, each will have a unique, never-colliding, discoverable URL.

Code (simplified):

ts
1function getUniqueTalkSlug(talk, allTalks) { 2 const baseSlug = slugify(talk.title); 3 let seen = 0; 4 for (const t of allTalks) { 5 if (slugify(t.title) === baseSlug) { 6 seen++; 7 if (t.id === talk.id) { 8 return seen === 1 ? baseSlug : `${baseSlug}-${talk.id}`; 9 } 10 } 11 } 12}

How This Changed My Workflow (and Could Change Yours)

  • I never have to manually check for collisions.
    When I add another instance of the same talk, its slug is always unique by design.

  • Legacy links stay valid.
    Only the “first” talk with any title gets the plain slug.

  • SEO is happy, and so are people!
    Every talk page is independently addressable, discoverable, and readable.

Lessons Learned

  • Automate uniqueness early: It’s worth a tiny bit of index logic.

  • Plan for duplicates: Never assume titles or metadata are unique.

  • Preserve legacy links: SEO and users depend on it.

Real-World Impact

After deploying this update my talks page:

  • No longer has conflicting URLs.
  • Is fully future-proof, with zero extra maintenance for the next talks.
  • Is better indexed and more reliable for humans and robots alike.

If you run any site where titles could repeat: conference talks, events, blog posts, whatever, consider this approach!