Skip to main content

Click Tracking

Overview

This domain is the platform's central measurement system. It records who read or tapped what, when, and which piece of content it came from. Every link sent out through LINE is first rewritten into a short link routed through the tracking system, which then redirects onward to the real destination.

Three tables make up the domain:

TablePurpose
tracking_logThe append-only event record
tracking_tokenThe registry of short links and their destinations
tracking_line_usersPer-user deduplication of clicks

Core Data Structure

tracking_log (model TrackingLog, UUID primary key)

An append-only event table, classified through several enums:

  • service (enum TrackingService) — webhook or redirect, indicating how the event arrived
  • action_type (enum ActionType) — read / click / send
  • type (enum TrackingType) — message / uri / asset / postback
  • content_type (enum ContentType) — rich_menu / campaign / auto_response / trigger_rule / lead_generation

The originating content is referenced through campaign_id, rich_menu_id, rich_menu_action_index, rich_message_id, rich_message_index, auto_response_id, trigger_rule_id, and rich_menu_archive_id.

Identity is captured by line_uid plus the composite foreign key (line_uid, line_oa_id, organization_id)line_user.

Link details cover redirect_id, token, short_url, original_url, tracking_label, title, raw_data JSONB, and created_date.

The table carries six composite indexes covering every reporting angle: per user, per campaign, per rich menu, per service/type, and unique-click counting.

tracking_token (model TrackingToken, UUID primary key)

The short-link registry:

  • token (unique), destination_url, tracking_label
  • content_type + content_id + action_index — identifying which button in which piece of content the token belongs to
  • line_oa_hash (used to build the public URL), metadata JSONB, expires_at
  • indexes on (token, status), (line_oa_id, content_type, content_id), and (expires_at, status)

tracking_line_users (model TrackingLineUsers, UUID primary key)

Records that a given user has already clicked a given key, which is what makes unique-click and first-click figures possible for campaigns.

  • unique (tracking_key, line_user_id), named uk_tracking_key_line_user_id
  • tracking_key follows the pattern campaignId:richMessageId:bubbleIndex:index (documented in the seed file)

Trigger

tracking_log_campaign_click_notify (AFTER INSERT) calls notify_campaign_click(), which emits pg_notify('campaign_click', ...) whenever the event is a campaign click with an identifiable user. The worker picks this signal up to update totals and fire trigger rules.

  • prisma/schema.prisma:610 — model TrackingLog
  • prisma/schema.prisma:857 — model TrackingToken
  • prisma/schema.prisma:888 — model TrackingLineUsers
  • manual-sql/4.sql — the notify_campaign_click trigger
  • manual-sql/5.sql — the revision that also writes to event_outbox
  • seed-data/15.tracking_line_users.sql
  • schema-dumps/2026-07-24/schema.sql:2980, :3012, :2963

Connections to Other Services

  • client-api-go — the redirect endpoint (/r/...) reads tracking_token, writes a tracking_log row, then returns a 302 to destination_url
  • webhook-go — writes event-side logs for reads and postbacks
  • worker-go — aggregates totals back into the campaign.total_* columns and listens on the campaign_click channel
  • cms-api-go — the reporting screens in the tracking-log module

Related domains: Broadcast Campaigns, Rich Menu, Auto-response, LINE Friends