Skip to main content
March 23, 2026Noble Desktop Publishing Team/8 min read

Product Images, SEO-Friendly Slugs, & Markdown

Build SEO-Friendly Rails Apps with Professional URLs

Core Technologies We'll Implement

FriendlyId Gem

Transform numeric URLs into SEO-friendly slugs that improve search rankings and user experience.

Database Migrations

Add unique slug fields with proper indexing for optimal performance and data integrity.

Active Storage

Integrate image attachments programmatically through seeds file for streamlined content management.

Topics Covered in This Ruby on Rails Tutorial:

Installing the FriendlyId Gem, Creating SEO-Optimized URLs with Slugs, and Rebuilding Your Product Database

Exercise Overview

In this comprehensive exercise, you'll transform your Rails application into a production-ready e-commerce platform. We'll implement proper image handling for all products, create search engine-optimized URLs that boost your site's SEO performance, and leverage Markdown for streamlined content management. These improvements will significantly enhance both user experience and search engine visibility.

  1. If you've completed the previous exercises (8A–8B), you can skip the following sidebar and continue to the Setup section. However, if you haven't finished those foundational exercises, follow the steps below to get your development environment properly configured.

    What You'll Accomplish

    1

    Install FriendlyId Gem

    Add and configure the FriendlyId gem to enable SEO-friendly URL generation

    2

    Implement Slug System

    Create unique slug fields and modify models to use human-readable URLs

    3

    Display Product Images

    Configure Active Storage to show unique images for all products

    4

    Rebuild Database

    Recreate the database with proper seeds file for images and slugs

Prerequisite Setup: If You Haven't Completed Exercises 8A–8B

  1. Close any open files in your code editor to start with a clean workspace.
  2. Open the Finder and navigate to Class Files > yourname-Rails Class
  3. Open Terminal to access the command line interface.
  4. Type cd followed by a single space (do NOT press Return yet).
  5. Drag the yourname-Rails Class folder from the Finder window directly into the Terminal window, then press ENTER to navigate to that directory.
  6. Run rm -rf nutty to completely remove your existing copy of the nutty site.
  7. Run git clone https://bitbucket.org/Noble Desktop/nutty.git to download the latest version of the That Nutty Guy repository.
  8. Type cd nutty to enter the newly cloned directory.
  9. Type git checkout 8B to switch to the branch containing all completed work from the previous exercise.
  10. Run bundle install to install all required Ruby gems and dependencies.
  11. Run yarn install --check-files to install all JavaScript dependencies and verify file integrity.

URL Structure: Before vs After

FeatureCurrent URLsSEO-Friendly URLs
Product Pageslocalhost:3000/products/1localhost:3000/products/buddha-board
SEO ValueNo keyword relevanceProduct name in URL
User ExperienceGeneric numeric IDDescriptive and memorable
Recommended: SEO-friendly URLs significantly improve search rankings by including relevant keywords
SEO Impact of URLs

Google considers URL contents as one of the most important factors for determining page keywords and search relevance. Including product names in URLs directly improves SEO performance.

Setup and Initial Configuration

Before we dive into implementing SEO-friendly URLs, let's examine the current state of your application and understand why these improvements matter for modern web development.

  1. Open your web browser and navigate to: localhost:3000

  2. Click on any product to view its detail page.

  3. Examine the URL structure—you'll notice it follows the pattern: localhost:3000/products/1

    While these numeric URLs are functional, they're problematic for modern SEO best practices. Search engines like Google heavily weight URL content when determining page relevance and ranking. A URL like /products/1 tells search engines nothing about your product, whereas /products/organic-dark-chocolate-truffles immediately signals the page content and improves keyword association.

    The FriendlyId gem solves this problem elegantly by replacing numeric IDs with human-readable slugs derived from your content.

  4. In your browser, navigate to: github.com/norman/friendly_id

  5. Scroll down to the Rails Quickstart section and copy the current gem declaration (the version may be newer than shown here, which is perfectly fine—always use the latest stable version):

    gem 'friendly_id', '~> 5.4.0'

    This declaration will be added to your application's Gemfile to manage the dependency.

  6. Continue working with the nutty folder located in Desktop > Class Files > yourname-Rails Class > nutty

    For optimal workflow, open the entire nutty folder in your code editor (VS Code, Sublime Text, or similar) to enable project-wide navigation and search capabilities.

  7. In your code editor, open nutty > Gemfile

  8. Scroll to the bottom of the file and add the following lines:

    # Use FriendlyId for SEO-friendly URLs
    gem 'friendly_id', '~> 5.4.0'
  9. Save the file using Cmd+S (Mac) or Ctrl+S (Windows).

    Remember: whenever you add new gems to your Rails application, you must restart the development server to load the new dependencies properly.

  10. Switch to the ruby tab in your Terminal window (the one currently running the Rails server).

  11. Press Ctrl+C to gracefully stop the server.

  12. Install the new gem by running:

    bundle install
  13. Restart your Rails development server:

    rails server
  14. Switch to your second Terminal tab to continue with configuration commands.

  15. Complete the FriendlyId setup by running these configuration commands:

    rails generate friendly_id
    rails db:migrate

    These commands create the necessary database tables and configuration files for FriendlyId to function properly.

URL Structure: Before vs After

FeatureCurrent URLsSEO-Friendly URLs
Product Pageslocalhost:3000/products/1localhost:3000/products/buddha-board
SEO ValueNo keyword relevanceProduct name in URL
User ExperienceGeneric numeric IDDescriptive and memorable
Recommended: SEO-friendly URLs significantly improve search rankings by including relevant keywords
SEO Impact of URLs

Google considers URL contents as one of the most important factors for determining page keywords and search relevance. Including product names in URLs directly improves SEO performance.

Implementing Slugs for SEO-Optimized URLs

FriendlyId operates using slugs—URL-friendly versions of your content titles. Think of slugs as the bridge between human-readable content and web-safe URLs. Instead of /products/1, you'll have URLs like /products/buddha-board that both users and search engines can immediately understand.

  1. First, we'll add a database field to store these slug values. In Terminal, run:

    rails generate migration add_slug_to_products slug:uniq

    The uniq type is Rails shorthand for a unique string field. Since each slug represents a unique URL, ensuring uniqueness at the database level prevents conflicts and maintains data integrity.

  2. In your code editor, locate and open nutty > db > migrate > [timestamp]_add_slug_to_products.rb

    Note: The timestamp portion of the filename will be unique to when you generated this migration.

    Examine the generated migration code:

    add_column :products, :slug, :string
    add_index :products, :slug, unique: true

    This migration does two critical things: it adds the slug column and creates a unique index. The index is crucial for performance—without it, your application would slow significantly as your product catalog grows. Database lookups on indexed fields are orders of magnitude faster than unindexed searches.

  3. Close the migration file after reviewing it.

  4. Apply the migration to your database:

    rails db:migrate
  5. Now we'll configure the Product model to use FriendlyId. Open nutty > app > models > product.rb

  6. Add the FriendlyId configuration after the existing has_one_attached :image line:

    has_one_attached :image
    
    extend FriendlyId
    friendly_id :title, use: [:slugged, :finders]
    end

    This configuration tells FriendlyId to generate slugs from the product title and to override Rails' default finder methods to work with slugs instead of numeric IDs.

  7. Save the file.

  8. We also need to configure Active Admin to work with FriendlyId. Open app > admin > products.rb and add this controller configuration at the bottom:

    f.actions
    end
    
    controller do
      def find_resource
        scoped_collection.friendly.find(params[:id])
      end
    end
    end
  9. Now let's test the implementation. In your browser, navigate to: localhost:3000/admin

  10. Sign in with your admin credentials if prompted.

  11. Click on Products in the navigation.

  12. To generate a slug, we need to trigger an update on any product. Find the Buddha Board product (typically the first in the list).

  13. Click on the product ID number (8) to view the product details.

  14. Click Edit Product in the top right corner.

  15. Without changing any information, click the Update Product button.

    This triggers FriendlyId to generate a slug based on the product title.

  16. Check the URL bar—you should now see: localhost:3000/admin/products/buddha-board

  17. Test the public-facing URL by visiting: localhost:3000/products/buddha-board

    Congratulations! You now have SEO-optimized URLs that clearly communicate page content to both users and search engines.

Database Reconstruction and Bulk Image Processing

Now that we've implemented both Active Storage and FriendlyId, let's take a professional approach to data management. Rather than manually updating each product through the admin interface—a time-consuming and error-prone process—we'll rebuild our database programmatically. This approach ensures consistency and demonstrates real-world deployment practices.

The key challenge is programmatically attaching image files to model objects. Fortunately, Rails Active Storage makes this surprisingly straightforward, whether your images are stored locally, on a CDN, or accessible via URL.

  1. Open nutty > db > seeds.rb in your code editor.

  2. Review the pre-configured seeds file structure. Note these key elements:

    • Each product entry includes an :image key with a corresponding filename (visible around lines 16, 29, 40, etc.)
    • The file uses an array-based structure containing product attributes and image references
    • An each loop processes each product, creates a new Product object, and handles success/error reporting

    We need to enhance this loop to handle image attachment before saving each product record.

  3. Locate the product creation loop around line 114 and enhance it with image processing logic:

    p = Product.new(product[:attributes])
    fn = "public/img/product_images/#{product[:image]}"
    if File.exist?(fn)
      p.image.attach(io: File.open(fn), filename: product[:image])
    else
      puts "Warning: Image file not found for #{product[:attributes][:title]}: #{fn}"
    end
    
    if p.save
      puts "Created #{p.title}"
    else
      puts "Failed to create #{product[:attributes][:title]}: #{p.errors.full_messages.join(', ')}"
    end

    This enhanced code includes proper error handling and detailed logging—essential for production-quality applications.

  4. Save the file.

  5. Now we'll reset our database with the improved seed data. Open the Rails console:

    rails console
  6. Remove all existing products:

    Product.destroy_all

    This ensures a clean slate for our enhanced data structure.

  7. Exit the console and return to the command prompt:

    exit
  8. Populate your database with the new seed data:

    rails db:seed

    Watch the output to confirm successful product creation and image attachment.

  9. Test the results by navigating to localhost:3000 in your browser (refresh if already open).

    All product images should now display correctly on both the catalog and individual product pages.

  10. Click through several products to verify that each one displays its unique image and uses its SEO-friendly URL structure.

    You've successfully implemented a professional-grade e-commerce catalog with optimized URLs and proper image management—key components of any serious web application.

Key Takeaways

1FriendlyId gem transforms numeric product URLs into SEO-friendly slugs using product titles for better search engine optimization
2Database indexing on slug columns is essential for maintaining fast lookup performance as your product catalog grows
3Unique string fields for slugs prevent URL conflicts and ensure each product has a distinct, memorable web address
4Active Storage enables programmatic image attachment through seeds files, eliminating manual upload requirements
5Updating existing products through the admin interface automatically generates new slug-based URLs
6Wiping and reseeding databases is more efficient than manual editing when implementing new features across all products
7URL structure directly impacts SEO rankings, with keyword-rich URLs providing significant search engine benefits
8Rails migration shortcuts like 'uniq' type automatically create unique string fields with proper database constraints

RELATED ARTICLES