Skip to main content

Overview

The tag system provides a flexible way to categorize and organize links across clients and campaigns. Tags work independently of the client-campaign hierarchy, allowing you to create cross-cutting categories for filtering and analysis.

Many-to-Many

Links can have multiple tags, tags can be on multiple links

Auto-Creation

Tags are created automatically when first used

Flexible Categories

Create any categorization scheme that fits your workflow

Cross-Client

Tags work across all clients and campaigns

How Tags Work

Many-to-Many Relationships

Tags and links have a many-to-many relationship:
Link 1 ────┬──── Tag: "social"

Link 2 ────┤

Link 3 ────┼──── Tag: "paid"

Link 4 ────┴──── Tag: "instagram"
This means:
  • A single link can have multiple tags
  • A single tag can be applied to multiple links
  • Tags are reusable across all links

Database Structure

Tags are implemented using a junction table for optimal performance:
Tags Table
  - id (uuid)
  - name (unique)
  - createdAt
  - updatedAt

LinkTags Table (Junction)
  - linkId (foreign key)
  - tagId (foreign key)
  - assignedAt
  - PRIMARY KEY (linkId, tagId)
The junction table pattern ensures efficient querying in both directions:
  • Find all tags for a link
  • Find all links with a specific tag

Auto-Creation of Tags

One of the most powerful features of the tag system is automatic creation. You don’t need to pre-define tags.

How Auto-Creation Works

1

Tag name provided

When creating or updating a link, include tag names in the request
2

System checks existence

The system looks up each tag name in the database
3

Create if needed

If a tag doesn’t exist, it’s automatically created
4

Associate with link

The tag is linked to your link via the junction table
POST /links
Content-Type: application/json

{
  "originalUrl": "https://example.com/product",
  "clientId": "client-uuid",
  "tags": ["social", "instagram", "new-product"]  // None exist yet
}
Result:
  1. Three new tags are created: “social”, “instagram”, “new-product”
  2. All three tags are associated with the new link
  3. These tags are now available for other links
Tag names are case-sensitive. “Social” and “social” are treated as different tags.
Include tags when creating a link:
{
  "originalUrl": "https://example.com/page",
  "clientId": "client-uuid",
  "campaignId": "campaign-uuid",
  "tags": ["email", "newsletter", "promo"]
}
Replace all tags on a link:
PUT /links/:id
Content-Type: application/json

{
  "tags": ["updated", "tags", "list"]
}
Tag updates are destructive replacements. The new tag list completely replaces the existing tags. If you want to add a tag, you must include all existing tags plus the new one.

Removing All Tags

Set tags to an empty array:
{
  "tags": []
}
When retrieving link information, tags are included:
{
  "id": "link-uuid",
  "shortCode": "abc123",
  "originalUrl": "https://example.com",
  "tags": [
    { "id": "tag-uuid-1", "name": "social" },
    { "id": "tag-uuid-2", "name": "paid" },
    { "id": "tag-uuid-3", "name": "instagram" }
  ]
}

Tag Naming Best Practices

Lowercase

Use lowercase for consistency: instagram not Instagram

Hyphen Separators

Use hyphens for multi-word tags: new-product not new_product

Descriptive

Make tags self-explanatory: q1-2024 not q1

Consistent Categories

Define category prefixes: channel-email, channel-social

Tag Naming Examples

- social
- instagram
- paid-ad
- organic
- q1-2024
- product-launch
- high-priority
- a-b-test

Tag Organization Strategies

By Channel

Tag links by marketing channel:
- channel-instagram
- channel-facebook
- channel-email
- channel-sms
- channel-print

By Content Type

Categorize by the type of content:
- blog-post
- product-page
- landing-page
- video
- infographic

By Audience

Segment by target audience:
- audience-b2b
- audience-b2c
- audience-enterprise
- audience-sme

By Status or Priority

Track the state or importance:
- active
- archived
- testing
- high-priority
- low-priority

By Traffic Source

Identify where links are shared:
- organic
- paid
- influencer
- partner
- internal

By Time Period

Group by temporal categories:
- q1-2024
- q2-2024
- spring-campaign
- holiday-2024
Combine multiple tagging strategies for powerful filtering. For example: ["channel-instagram", "paid", "q1-2024", "product-launch"]

Tag Lifecycle

Creation

Tags are created in two ways:
  1. Automatically when first used with a link
  2. Reused if they already exist

Persistence

Tags persist even after all links using them are deleted. This means:
  • Tag history is preserved
  • Reusing old tag names is seamless
  • No need to recreate common tags

Deletion Behavior

Tag-link associations are automatically cleaned up:

Querying by Tags

While not explicitly shown in the routes, tags can be used in search queries:
GET /links?search=instagram
This will find links where:
  • The URL contains “instagram”
  • A tag name contains “instagram”
  • Other metadata matches “instagram”

Multiple Tag Filtering

For advanced filtering, you can retrieve all links and filter client-side, or implement custom API filters:
// Client-side filtering example
const links = await fetchAllLinks();
const filteredLinks = links.filter(link => 
  link.tags.some(tag => tag.name === 'instagram') &&
  link.tags.some(tag => tag.name === 'paid')
);

Advanced Tag Patterns

Hierarchical Tags

Use prefixes to create pseudo-hierarchies:
marketing:social:instagram
marketing:social:facebook
marketing:email:newsletter
marketing:email:promo
Or with hyphens:
marketing-social-instagram
marketing-social-facebook
marketing-email-newsletter
marketing-email-promo

Composite Tags

Combine multiple concepts:
- paid-instagram-feed
- organic-facebook-story
- email-newsletter-weekly
- sms-promotional-flash

Boolean Tag Patterns

Use tags as flags:
- is-featured
- needs-review
- high-converter
- bot-traffic
- requires-auth

Tag Analytics

Tags enable powerful analytics queries: Find which tags are used most frequently:
SELECT tag_id, COUNT(*) as usage_count
FROM link_tags
GROUP BY tag_id
ORDER BY usage_count DESC
LIMIT 10;

Performance by Tag

Compare click performance across tags:
SELECT t.name, COUNT(c.id) as clicks
FROM tags t
JOIN link_tags lt ON t.id = lt.tag_id
JOIN links l ON lt.link_id = l.id
JOIN clicks c ON l.id = c.link_id
GROUP BY t.name
ORDER BY clicks DESC;

Tag Combinations

Discover common tag pairings:
SELECT t1.name, t2.name, COUNT(*) as frequency
FROM link_tags lt1
JOIN link_tags lt2 ON lt1.link_id = lt2.link_id
JOIN tags t1 ON lt1.tag_id = t1.id
JOIN tags t2 ON lt2.tag_id = t2.id
WHERE lt1.tag_id < lt2.tag_id
GROUP BY t1.name, t2.name
ORDER BY frequency DESC;

Tag Management UI Patterns

Tag Input Methods

Text Input

Comma-separated tag names: social, instagram, paid

Autocomplete

Suggest existing tags as user types

Tag Pills

Visual chips with remove buttons

Tag Browser

Browse and select from all existing tags

Visual Representations

  • Tag Clouds: Show popular tags with size representing usage
  • Color Coding: Assign colors to tag categories
  • Tag Groups: Organize tags into collapsible categories
  • Tag Counters: Display link count for each tag

Common Use Cases

Marketing Campaign Tracking

{
  "tags": [
    "campaign-spring-2024",
    "channel-instagram",
    "paid",
    "target-millennials"
  ]
}

A/B Testing

{
  "tags": [
    "ab-test",
    "variant-a",
    "landing-page",
    "checkout-flow"
  ]
}

Content Organization

{
  "tags": [
    "content-blog",
    "topic-seo",
    "author-john",
    "published-2024-03"
  ]
}

Partner Tracking

{
  "tags": [
    "partner-affiliate",
    "partner-id-12345",
    "commission-10pct"
  ]
}

Best Practices Summary

Start Simple

Begin with basic tags and expand as needs grow

Document Conventions

Maintain a tag naming guide for your team

Regular Review

Periodically audit tags to identify unused or redundant ones

Train Team

Ensure all users understand the tagging system
Consider creating a “tag dictionary” document that lists standard tags and their intended uses. This helps maintain consistency across the team.

Build docs developers (and LLMs) love