• Home
BuildWithMatija
Get In Touch
  1. Home
  2. Blog
  3. Payload
  4. Generate Product Slugs Automatically: Complete 2026 Guide

Generate Product Slugs Automatically: Complete 2026 Guide

Backfill missing product slugs across locales (sl, en, ru) using a safe Payload job, API trigger, and migration steps

24th January 2026·Updated on:28th January 2026·MŽMatija Žiberna·
Payload
Generate Product Slugs Automatically: Complete 2026 Guide

📚 Comprehensive Payload CMS Guides

Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.

No spam. Unsubscribe anytime.

This guide explains how to use the automated product slug generation system to populate missing slugs for all products across all locales (Slovenian, English, Russian).

Overview

The slug generation task automatically creates URL-friendly slugs for products based on their titles. It:

  • Generates slugs from titles: Uses the same logic as manual slug creation (src/utilities/formatSlug.ts)
  • Respects existing slugs: Only generates slugs for products/locales that don't have one yet
  • Handles all locales: Generates localized slugs for sl, en, and ru based on their respective titles
  • Safe operation: Never overwrites existing slugs

How It Works

The slug generation process:

  1. Fetches all products from the database with all locales
  2. For each product, checks each locale (sl, en, ru)
  3. If a slug is missing for that locale:
    • Gets the product title for that locale
    • Generates a URL-friendly slug using the same formatting rules as manual entry
    • Updates only that specific locale's slug field
  4. Provides detailed logging and error reporting

Slug Format

Slugs are formatted according to these rules:

  • Spaces replaced with hyphens (-)
  • Non-word characters removed (except hyphens and slashes)
  • Converted to lowercase

Example transformations:

  • "Goveje meso" → "goveje-meso"
  • "Fresh Chicken Breast" → "fresh-chicken-breast"
  • "Свежая курица" → "kurица" (Cyrillic handled appropriately)

Running the Slug Generation Job

Option 1: Via API Endpoint

Queue the job via HTTP:

curl -X POST http://localhost:3000/api/generate-product-slugs \
  -H "Authorization: Bearer YOUR_PAYLOAD_API_KEY" \
  -H "Content-Type: application/json"

This will return a job ID:

{
  "success": true,
  "jobId": "12345",
  "message": "Product slug generation job queued successfully"
}

Option 2: Via Payload Admin UI

  1. Go to the Payload admin panel
  2. Navigate to Jobs in the sidebar
  3. Find the job with task type generateProductSlugs
  4. Click Run to execute it

Checking Job Status

Use the GET endpoint with your job ID:

curl "http://localhost:3000/api/generate-product-slugs?jobId=12345" \
  -H "Authorization: Bearer YOUR_PAYLOAD_API_KEY"

Response includes:

{
  "jobId": "12345",
  "status": "completed",
  "result": {
    "success": true,
    "totalDocuments": 50,
    "totalSlugsGenerated": 87,
    "errors": []
  }
}

Implementation Details

Files Created

  1. Job Handler (src/payload/jobs/tasks/generateProductSlugs.ts)

    • Main logic for slug generation
    • Handles all locales independently
    • Includes error handling and logging
  2. API Endpoint (src/app/api/generate-product-slugs/route.ts)

    • HTTP trigger for the job
    • Status checking endpoint
    • Basic authentication
  3. Config Registration (updated payload.config.ts)

    • Registered as a Payload job task
    • Label: "Generate Product Slugs (from titles)"
    • No input parameters needed

Database Migration Required

After adding the job task to the config, you need to create and run a database migration:

# Create migration
pnpm run payload migrate:create

# Run migration
pnpm run payload migrate

This updates the PostgreSQL enum for job task slugs to include generateProductSlugs.

Examples

Example 1: New Product with Only Slovenian Title

Before:

{
  "title": {
    "sl": "Goveje meso",
    "en": "Beef Meat",
    "ru": "Говядина"
  },
  "slug": "goveje-meso" // Only Slovenian slug exists (string format)
}

After running job:

{
  "title": {
    "sl": "Goveje meso",
    "en": "Beef Meat",
    "ru": "Говядина"
  },
  "slug": {
    "sl": "goveje-meso",
    "en": "beef-meat",
    "ru": "govyadina"
  }
}

Example 2: Product with Some Missing Slugs

Before:

{
  "slug": {
    "sl": "svinje-meso",
    "en": "" // Empty English slug
    // Russian slug missing entirely
  }
}

After running job:

{
  "slug": {
    "sl": "svinje-meso", // Unchanged
    "en": "pork-meat", // Generated from English title
    "ru": "svinina" // Generated from Russian title
  }
}

Logs and Debugging

The job provides detailed logging:

=== PRODUCT SLUG GENERATION JOB STARTED ===
Found 50 product documents

=== Processing Product ID: 123 ===
Product 123 already has slug for locale sl, skipping
Generating slug for product 123 (en): "Beef Meat" -> "beef-meat"
Successfully generated slug for product 123 (en): beef-meat
Generating slug for product 123 (ru): "Говядина" -> "govyadina"
Successfully generated slug for product 123 (ru): govyadina

=== PRODUCT SLUG GENERATION COMPLETED ===
Generated 87 slugs across 50 products

Safety Features

  1. Never overwrites existing slugs: If a slug already exists for a locale, it's skipped
  2. Per-locale isolation: Each locale is processed independently
  3. Error isolation: If one product/locale fails, others continue processing
  4. Detailed error reporting: All errors are logged and returned in the result

When to Use This

Use this task when:

  • You have products with missing slugs in some locales
  • You've imported products without generating slugs
  • You've added new locale support and need to backfill slugs
  • You want to ensure all products have consistent, URL-friendly identifiers

Extending for Other Collections

This pattern can be adapted for other collections (Collections, Recipes, etc.) by:

  1. Copying the job handler and changing the collection name
  2. Adjusting the field names (if not using title and slug)
  3. Registering the new task in payload.config.ts
  4. Creating a corresponding API endpoint

Troubleshooting

Problem: Job queues but never runs

Solution: Make sure you have a job runner process active:

curl -X POST http://localhost:3000/api/payload-jobs/run \
  -H "Authorization: Bearer YOUR_CRON_SECRET"

Problem: Slugs not generating for a specific locale

Solution: Check that the product has a title in that locale. The job logs will show:

Product 123 has no title for locale en, skipping slug generation

Problem: "Duplicate slug" error

Solution: The job doesn't handle slug uniqueness conflicts. Ensure your titles are unique per locale, or manually adjust conflicting slugs before running the job.

Related

  • Automating Payload Translations with OpenAI - Similar pattern for translating content
  • src/utilities/formatSlug.ts - Core slug formatting logic
  • src/fields/slug.ts - Slug field definition and hooks
📄View markdown version
0

Frequently Asked Questions

Comments

Leave a Comment

Your email will not be published

Stay updated! Get our weekly digest with the latest learnings on NextJS, React, AI, and web development tips delivered straight to your inbox.

10-2000 characters

• Comments are automatically approved and will appear immediately

• Your name and email will be saved for future comments

• Be respectful and constructive in your feedback

• No spam, self-promotion, or off-topic content

Matija Žiberna
Matija Žiberna
Full-stack developer, co-founder

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

Table of Contents

  • Overview
  • How It Works
  • Slug Format
  • Running the Slug Generation Job
  • Option 1: Via API Endpoint
  • Option 2: Via Payload Admin UI
  • Checking Job Status
  • Implementation Details
  • Files Created
  • Database Migration Required
  • Examples
  • Example 1: New Product with Only Slovenian Title
  • Example 2: Product with Some Missing Slugs
  • Logs and Debugging
  • Safety Features
  • When to Use This
  • Extending for Other Collections
  • Troubleshooting
  • Related
On this page:
  • Overview
  • How It Works
  • Running the Slug Generation Job
  • Implementation Details
  • Examples
Build With Matija Logo

Build with Matija

Matija Žiberna

Full Stack Developer specializing in Next.js and TypeScript. Co-founder of We Hate Copy Pasting, building solutions for D2C brands.

Quick Links

About
  • Projects
  • Commands
  • Blog
  • Contact
  • Get in Touch

    Have a project in mind? Let's discuss how we can help your business grow.

    Contact me →
    © 2026BuildWithMatija•Crafting digital experiences with code•All rights reserved