Skip to main content
Categories provide the organizational structure for your Help Center. Learn how to create categories, build hierarchies, and link related content.

What are Categories?

Categories group related articles together, making it easier for customers to find information. Each category can contain:
  • Articles - Individual documentation pages
  • Subcategories - Nested child categories
  • Related categories - Cross-references to similar topics
  • Folders - Additional organizational structure

Creating Categories

Required Fields

name
string
required
Display name for the category
slug
string
required
URL-friendly identifier (must be unique per portal + locale)
portal_id
integer
required
Parent Help Center portal
account_id
integer
required
Account ID (automatically set from portal)

Optional Fields

description
text
Brief explanation of the category’s content
icon
string
Icon identifier for visual representation (default: empty string)
locale
string
Language code (default: ‘en’)
position
integer
Sort order for category display
parent_category_id
bigint
Parent category for creating subcategories
associated_category_id
bigint
Root category for translations
1

Plan Structure

Outline your content hierarchy before creating categories
2

Create Parent Categories

Start with top-level categories for main topics
3

Add Subcategories

Create child categories for more specific topics
4

Assign Articles

Move or create articles within each category
5

Link Related Content

Connect related categories for cross-navigation

Category Schema

class Category < ApplicationRecord
  belongs_to :account
  belongs_to :portal
  belongs_to :parent_category, optional: true
  belongs_to :root_category,
             foreign_key: :associated_category_id,
             optional: true
  
  has_many :articles
  has_many :folders
  has_many :sub_categories,
           foreign_key: :parent_category_id
  has_many :associated_categories,
           foreign_key: :associated_category_id
  has_many :related_categories,
           through: :category_related_categories
end

Category Hierarchy

Parent-Child Structure

Create nested categories for detailed organization:
Getting Started                 # Parent category
├── Installation               # Subcategory
├── Configuration              # Subcategory
└── First Steps                # Subcategory

Advanced Features              # Parent category
├── Automation                 # Subcategory
├── Integrations               # Subcategory
└── Custom Workflows           # Subcategory
# Define parent relationship
subcategory = Category.create!(
  name: 'Installation',
  slug: 'installation',
  parent_category_id: getting_started.id,
  portal_id: portal.id
)
Link categories that cover similar topics:
# Schema
has_many :category_related_categories,
         class_name: :RelatedCategory,
         dependent: :destroy_async
has_many :related_categories,
         through: :category_related_categories

# Usage
category.related_categories << other_category
Related categories appear as suggestions, helping customers discover relevant content.

Multi-language Categories

Locale Support

Categories are language-specific:
# Validation
validate :allowed_locales

def allowed_locales
  allowed_locales = portal.config['allowed_locales']
  return true if allowed_locales.include?(locale)
  
  errors.add(:locale, "#{locale} is not part of portal's allowed_locales")
end

Associated Categories

Link translations of the same category:
# English version (root)
category_en = Category.create!(
  name: 'Getting Started',
  slug: 'getting-started',
  locale: 'en',
  portal_id: portal.id
)

# Spanish translation
category_es = Category.create!(
  name: 'Comenzando',
  slug: 'getting-started',
  locale: 'es',
  associated_category_id: category_en.id,
  portal_id: portal.id
)
The same slug can be used across locales. The uniqueness constraint is per (slug, locale, portal_id) combination.

Category Positioning

Control the display order of categories:
# Default ordering
scope :search, ->(params) {
  search_by_locale(params[:locale])
    .page(current_page(params))
    .order(position: :asc)
}
1

Set Initial Position

Assign position values when creating categories (e.g., 10, 20, 30)
2

Update as Needed

Modify positions to reorder categories
3

Maintain Gaps

Use increments of 10 to allow easy insertion of new categories

Pagination

Categories are paginated for performance:
paginates_per Limits::CATEGORIES_PER_PAGE

# Usage
Category.search(locale: 'en', page: 2)

Organizing Articles

Article Assignment

Articles belong to one category:
has_many :articles, dependent: :nullify
When a category is deleted, articles are not deleted. Instead, their category_id is set to null.

Locale Inheritance

Articles automatically inherit category locale:
# From article.rb
def ensure_locale_in_article
  self.locale = if category.present?
                  category.locale
                else
                  locale.presence || portal.default_locale
                end
end
Articles must have the same locale as their category. Assigning an article to a category with a different locale will update the article’s locale.

Folders

Categories can contain folders for additional organization:
has_many :folders, dependent: :destroy_async
Folders provide an extra level of hierarchy beyond categories and subcategories. They’re useful for large categories with many articles.

Searching Categories

By Locale

Filter categories by language:
scope :search_by_locale, ->(locale) {
  where(locale: locale) if locale.present?
}

# Usage
Category.search_by_locale('en')

Search Method

Combine locale filtering with pagination:
Category.search(
  locale: 'en',
  page: 1
)

Category URLs

Category pages follow this structure:
https://your-domain.com/hc/{portal-slug}/{locale}/categories/{category-slug}
Example:
https://app.chatwoot.com/hc/my-portal/en/categories/getting-started

Best Practices

  • Use clear, descriptive category names
  • Keep names concise (2-4 words)
  • Use title case for consistency
  • Avoid technical jargon in top-level categories
  • Use specific terms for subcategories
  • Limit hierarchy depth to 2-3 levels
  • Group 5-10 articles per category
  • Create subcategories when a category exceeds 15 articles
  • Balance category sizes for easy navigation
  • Use folders for very large categories
  • Create categories for all supported locales
  • Link translations with associated_category_id
  • Use consistent slug structure across locales
  • Maintain same hierarchy in all languages
  • Translate category descriptions and icons

Common Patterns

Feature-based Organization

Messaging
├── Live Chat
├── Email Integration
└── WhatsApp

Automation
├── Canned Responses
├── Chatbots
└── Workflows

User Journey Organization

Getting Started
├── Installation
├── Setup
└── First Steps

Daily Use
├── Managing Conversations
├── Team Collaboration
└── Reporting

Advanced
├── Custom Development
├── API Integration
└── Performance Tuning

Role-based Organization

For Agents
├── Handling Conversations
├── Using Tools
└── Best Practices

For Administrators
├── Account Settings
├── Team Management
└── Security

Validation Rules

name
required
Must be present
slug
required
Must be present and unique per (slug, locale, portal_id)
locale
required
Must be in portal’s allowed_locales list
account_id
required
Automatically set from portal

API Operations

Create Category

category = portal.categories.create!(
  name: 'Getting Started',
  slug: 'getting-started',
  description: 'Learn the basics of Chatwoot',
  locale: 'en',
  position: 10
)

Update Category

category.update!(
  name: 'Updated Name',
  description: 'New description',
  position: 20
)

Delete Category

category.destroy
# Articles in this category will have category_id set to null
# Subcategories will have parent_category_id set to null

Troubleshooting

Category not appearing - Check that the locale matches the portal’s allowed locales and that the category is not a draft (if draft mode exists).
Slug conflict - Ensure the slug is unique for the combination of slug, locale, and portal_id.
Articles changing locale - When assigning an article to a category, the article’s locale will update to match the category’s locale.

Build docs developers (and LLMs) love