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:
| Table | Purpose |
|---|---|
tracking_log | The append-only event record |
tracking_token | The registry of short links and their destinations |
tracking_line_users | Per-user deduplication of clicks |
Core Data Structure
tracking_log (model TrackingLog, UUID primary key)
An append-only event table, classified through several enums:
service(enumTrackingService) —webhookorredirect, indicating how the event arrivedaction_type(enumActionType) —read/click/sendtype(enumTrackingType) —message/uri/asset/postbackcontent_type(enumContentType) —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_labelcontent_type+content_id+action_index— identifying which button in which piece of content the token belongs toline_oa_hash(used to build the public URL),metadataJSONB,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), nameduk_tracking_key_line_user_id tracking_keyfollows the patterncampaignId: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.
Related Files
prisma/schema.prisma:610— modelTrackingLogprisma/schema.prisma:857— modelTrackingTokenprisma/schema.prisma:888— modelTrackingLineUsersmanual-sql/4.sql— thenotify_campaign_clicktriggermanual-sql/5.sql— the revision that also writes toevent_outboxseed-data/15.tracking_line_users.sqlschema-dumps/2026-07-24/schema.sql:2980,:3012,:2963
Connections to Other Services
- client-api-go — the redirect endpoint (
/r/...) readstracking_token, writes atracking_logrow, then returns a 302 todestination_url - webhook-go — writes event-side logs for reads and postbacks
- worker-go — aggregates totals back into the
campaign.total_*columns and listens on thecampaign_clickchannel - cms-api-go — the reporting screens in the
tracking-logmodule
Related domains: Broadcast Campaigns, Rich Menu, Auto-response, LINE Friends