Skip to main content

Broadcast Campaigns

Overview

A campaign is the unit of sending a message out to LINE friends, either immediately or on a schedule. Three delivery modes are supported through the CastType enum:

ModeMeaning
broadcastSent to every friend of the LINE OA
multicastSent to a specific audience segment
narrowcastSent using LINE's own targeting conditions

The campaign table plays two roles at once: it is both the send instruction and the delivery report. It stores a snapshot of the content that actually went out, alongside result counters (reach and clicks) written back from the tracking log.

Core Data Structure

campaign (model Campaign)

Send configuration lives in name, broadcast_now, start_date, cast_type, and status (enum CampaignStatus).

Key relations:

  • rich_message_idrich_message.id — the content to send
  • audience_idaudience.id (nullable) — the target segment for multicast
  • line_oa_idline_oa.id and organization_idorganization.id

Send-time snapshot, kept so that historical reports remain interpretable even after the source content has been edited:

  • rich_message_content JSONB — the resolved message content
  • line_message_object JSONB — the exact payload handed to the LINE API
  • template_tracking JSONB — mapping between buttons and tracking keys
  • end_tracking_date — when statistics collection stops

Merge tagshas_merge_tags and skip_merge_tag_missing decide what happens when a recipient has no value for a variable referenced in the message: skip that recipient, or send with the placeholder left empty.

Result counterstotal_activity, total_recipient, total_reach, total_unique_click, total_first_click, plus reason for recording why a campaign was cancelled or failed.

Atomic claim mechanism — the claimed_at column (added via manual SQL) together with the sending status appended through ALTER TYPE "CampaignStatus" ADD VALUE prevents multiple workers from picking up the same campaign twice. Rows stuck in sending beyond the lease window are reverted to scheduled by a reaper process.

campaign_delivery_batch

This table exists only in manual SQL and is not part of the Prisma schema. It tracks delivery split into smaller chunks.

  • unique (campaign_id, batch_no) with user_count and status (pending / sending / done / failed)
  • per-batch counters sent_count, error_count, skipped_count
  • a partial index on (campaign_id, status) for checking which batches are still open

The flow is: the worker's planner inserts batch rows, delivery workers claim and update them, and the last batch to finish closes out the campaign's aggregate totals.

  • prisma/schema.prisma:380 — model Campaign
  • manual-sql/8.campaign_claim.sql — the sending status and claimed_at column
  • manual-sql/8.campaign_delivery_batch.sql — the batch table (per the worker-go spec)
  • manual-sql/4.sql — the notify_campaign_click trigger on tracking_log
  • seed-data/12.campaign.sql — sample campaigns for all three modes
  • schema-dumps/2026-07-24/schema.sql:1154, :1190

Connections to Other Services

  • cms-api-go — creating, editing, and cancelling campaigns, plus the reporting screens
  • worker-go — the actual sender: claims campaigns, splits batches, calls the LINE API, updates counters, and listens on the campaign_click channel
  • client-api-go — the redirect endpoint that records a tracking_log entry when a user taps a link, before forwarding to the real destination

Related domains: Message Library (content), Audience (targeting), Click Tracking (results), Event Outbox (click-driven triggers)