Tags — Reference
The Tags surface is the content-classification plane for every SGEN site. It owns the catalogue of tags a site uses to label content, the attachment records that bind tags to individual posts, products, events, and other taggable content types, and the read paths that drive the filter widgets, related-content rails, and tag-archive pages on the front end.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a content-classification integration. Customer-facing setup walkthroughs live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Tags live under the Content → Tags module in SG-Admin. The module renders three primary views — the tag list, the tag create / edit form, and the per-content-type attachment editor — and exposes write operations for tag create, tag edit, attachment add, attachment remove, tag merge, and tag delete.
The module is paired by convention with every content-bearing surface — Posts, Products, Events, Pages where tagging is enabled, and the Forms surface for submission classification. Engineers reading the SG-Admin source will see the read half (tag enumeration, attachment lookup, filtered listing) split from the write half (tag CRUD, attachment writes, merge logic); the reference below describes the combined surface as it appears to a calling integration.
A second surface — tag groups — lives adjacent under the same module. Groups let an operator gather related tags under a single classification axis — for example, a "Difficulty" group containing "Beginner", "Intermediate", "Advanced". Front-end filter widgets render groups as separate filter blocks.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Content → Tags
- URL prefix:
/sg-admin/tags/ - View templates:
application/views/Admin/Tags/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Content → Tags [+ Add tag] │├──────────────────────────────────────────────────────────────────────┤│ Tag name Group Attached to Status ││ ───────────────── ──────────── ───────────── ──────────── ││ beginner Difficulty 42 posts Active ││ advanced Difficulty 18 posts Active ││ on-sale Promotion 7 products Active ││ webinar Event type 11 events Active ││ case-study Content type 9 posts Active ││ ││ [⋯ Edit] [⋯ Merge] [⋯ Delete] │└──────────────────────────────────────────────────────────────────────┘Actions
The Tags surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List tags
Returns the tags configured for the current site, in display order. Each row carries the tag name, its group (if grouped), the count of attached records broken down by content type, and an active flag. Supports column sort, free-text filter on tag name, and a group filter.
Create tag
Opens an empty tag form. Required fields: display name. Optional fields cover slug (auto-generated from the name if omitted), description, group binding, colour swatch (for filter widgets that render coloured chips), and a list of content types the tag is allowed to attach to. On submit, the surface validates uniqueness of the slug within the site and persists the new tag.
Edit tag
Loads an existing tag into the same form shape used for create, pre-populated. Submit replaces the stored tag definition. Editing the slug triggers a redirect on the public archive URL — the old slug returns a permanent redirect to the new slug for one full retention period (default ninety days).
Add attachment
Binds a tag to a target record. The attachment write accepts a tag ID and a target — a tuple of content_type and record_id. The surface validates that the tag's allow-list permits attachment to the target's content type and persists the attachment. Duplicate attachments are no-ops.
Remove attachment
Reverses an attachment. The tag remains in the catalogue; only the binding to the named record is removed.
Merge tag
Folds one tag into another. Accepts a source tag and a destination tag. The surface walks the source tag's attachments, rebinds each to the destination tag (skipping records already bound to the destination), removes the source tag's attachments, and marks the source tag inactive. The source tag's slug returns a redirect to the destination tag's archive URL for one retention period.
Create tag group
Opens an empty group form. Required fields: group name, display order. Optional: filter-widget label (the heading shown above the filter block on the front end). On submit, the surface persists the group; subsequent tag edits can bind tags to it.
Edit tag group
Loads an existing group. Submit replaces the group definition. Detaching a tag from its group leaves the tag in the catalogue but ungrouped.
Delete tag
Removes a tag. The surface prompts for confirmation, lists the records currently bound to the tag (for audit), and on confirm removes the tag and all its attachments. The tag's slug returns a redirect to the parent group's archive URL (or to the site root, for ungrouped tags) for one retention period.
Auto-suggest
A read path consumed by the in-line tag picker on content edit forms. Accepts a query string and a target content type, returns the top-ranked matching tags by attachment count within that content type. Suggestions favour tags already in heavy use over rarely-used tags.
Data model
A tag record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
name | string | Display name. Not necessarily unique across groups. |
slug | string | URL-safe identifier. Unique within the site. |
description | text | Optional. Shown on the tag-archive page header. |
group_id | integer | Optional. Foreign key to the parent group. |
colour | string | Optional. Hex value for filter-widget swatches. |
allowed_content_types | array | Content type slugs the tag may attach to. Empty means "all enabled types". |
attachment_count | integer | Maintained by the attachment writer. Cached for list views. |
status | enum | active or inactive. Inactive tags are hidden from the picker. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit. |
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. |
tag_id | integer | Foreign key to the tag. |
content_type | string | The target's content type slug. |
record_id | integer | The target record's primary key. |
attached_at | timestamp | Set on create, immutable. |
attached_by | integer | Operator ID. |
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. |
name | string | Operator-facing label. |
filter_label | string | Optional. Heading shown above the filter block on the front end. |
display_order | integer | Order in which filter blocks render. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit. |
TAG GROUP TAG├── id integer ├── id integer├── name string ├── name string├── filter_label string ├── slug string (unique)└── display_order integer ├── group_id integer (optional)├── colour string (optional)↑ belongs to ├── allowed_content_types array└── status enum↓ has manyATTACHMENT├── tag_id integer├── content_type string (posts | products | events | …)├── record_id integer└── attached_at timestamp↓ points toTARGET RECORD(post, product, event, page, form submission, …)Slug uniqueness. Tag slugs are unique within the site. The merge path collapses the source slug into a redirect; the delete path keeps the slug reserved until the retention period elapses, after which the slug becomes available for reuse.
Attachment-count cache. The attachment_count field on a tag record is maintained by the attachment writer — incremented on add, decremented on remove, recomputed on merge. List views read the cached count; the per-content-type breakdown shown in the list view is computed on demand from the attachment table.
Permissions
Access to the Tags surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Tags surface.
Layer 2 — per-action capability. Within SG-Admin, each Tags action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List tags | ✔ | ✔ | ✔ |
| Create tag | ✔ | ✔ | — |
| Edit tag | ✔ | ✔ | — |
| Add attachment | ✔ | ✔ | — |
| Remove attachment | ✔ | ✔ | — |
| Merge tag | ✔ | — | — |
| Create / edit group | ✔ | — | — |
| Delete tag | ✔ | — | — |
| Auto-suggest (read) | ✔ | ✔ | ✔ |
Attachment scope check. When a content surface (for example, Products) attaches a tag to one of its records, the attachment writer also checks the operator's edit capability for the target content type. An operator who can edit tags but not products cannot attach a tag to a product through the cross-surface attachment editor.
Audit. Every write — tag create, tag edit, attachment add, attachment remove, merge, group create, group edit, delete — emits an Activity Log entry. The log records the acting operator, the target tag (and target record for attachments), and the change shape. Merge events log both source and destination tag IDs. Activity Log retention is governed by the site's general settings.
REQUEST│▼┌───────────────────────────┐│ Admin gate │ unauth → reject│ (every /sg-admin/* call) │└─────────────┬─────────────┘│ authed▼┌───────────────────────────┐│ Tag capability check │ role lacks cap → reject└─────────────┬─────────────┘│ allowed▼┌───────────────────────────┐│ Attachment writes only — │ operator lacks edit on target│ target-content cap check │ content type → reject└─────────────┬─────────────┘│ passes▼┌───────────────────────────┐│ Allow-list check │ target content type not in│ (tag.allowed_content_types)│ allow-list → reject└─────────────┬─────────────┘│ passes▼action executes│▼Activity Log entryRelated references
- Posts — Reference. Tag attachments to post records drive blog filter widgets, related-post rails, and tag-archive pages.
- Products — Reference. Tag attachments to product records drive shop filter facets and product cross-sell rails.
- Events — Reference. Tag attachments to event records drive event-archive filtering.
- Categories — Reference. Hierarchical classification with parent-child semantics. Tags are the flat counterpart; the two surfaces coexist.
- Forms — Reference. Form submissions may carry tag attachments for routing and reporting.
- Search — Reference. The on-site search surface indexes tag names as a separate facet from content body, increasing the weight of tag matches in result ranking.
- Settings — Reference. Owns the role capability map that gates this surface and the redirect retention window applied on slug changes, merges, and deletes.
/docs/tags.