Skip to main content

Content Pages

Overview

This domain has 5 tables: content_page is the main table holding page data (slug, status, access control, statistics), while the other 4 are extensions keyed on content_page_id: content_page_translation (per-language content and SEO), content_page_utm (UTM parameters, 1:1), content_page_analytics (tracking scripts, 1:1) and content_page_view (per-visit view log)

Table content_page

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
uuidUUIDNOgen_random_uuid()External reference id for the page (unique)
line_oa_idINTEGERNO-LINE OA the page belongs to (FK to line_oa.id)
user_idINTEGERNO-User who owns the page
organization_idINTEGERNO-Organization that owns the page
slugVARCHAR(255)NO-Page slug used in the URL
statusContentPageStatus (ENUM)NOdraftPage status: draft, published, archived
versionINTEGERNO1Page version number
public_tokenVARCHAR(255)YES-Token for opening the page publicly (unique)
require_authBOOLEANNOfalseWhether login is required to view the page
password_protectedBOOLEANNOfalseWhether the page is password protected
password_hashVARCHAR(255)YES-Hash of the password protecting the page
published_atTIMESTAMPTZ(3)YES-Publication timestamp
published_byINTEGERYES-Publisher (user id)
archived_atTIMESTAMPTZ(3)YES-Archive timestamp
archived_byINTEGERYES-User who archived the page (user id)
view_countBIGINTNO0Total number of views
unique_view_countBIGINTNO0Number of unique viewers
category_idINTEGERYES-Page category (FK to content_category.id)
subcategory_idINTEGERYES-Page subcategory (FK to content_subcategory.id)
audience_idsJSONBYES'[]'Audiences allowed to see this page
friend_track_campaign_idINTEGERYES-Friend Track campaign linked to this page (FK to friend_track_campaign.id)
friend_track_button_textVARCHAR(255)YES-Label shown on the Friend Track button in the page
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO-Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO-Last updater (user id)
deleted_dateTIMESTAMPTZ(3)YES-Deletion timestamp (soft delete)
deleted_byINTEGERYES-User who deleted the page (user id)

Table content_page_translation

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
content_page_idINTEGERNO-Content page this translation belongs to (FK to content_page.id)
languageVARCHAR(10)NO-Translation language code, e.g. th, en
titleVARCHAR(500)NO-Page title in this language
contentTEXTYES-Page content in this language
excerptTEXTYES-Page excerpt / teaser text
meta_titleVARCHAR(160)YES-SEO meta title
meta_descriptionVARCHAR(320)YES-SEO meta description
meta_keywordsTEXTYES-SEO meta keywords
og_titleVARCHAR(160)YES-Open Graph title used when sharing
og_descriptionVARCHAR(320)YES-Open Graph description used when sharing
og_image_urlTEXTYES-Open Graph image URL
twitter_cardVARCHAR(50)YES-Twitter card type
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO-Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO-Last updater (user id)

Table content_page_utm

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
content_page_idINTEGERNO-Content page this row belongs to (unique — 1:1 relation)
utm_sourceVARCHAR(255)YES-Default UTM source for the page
utm_mediumVARCHAR(255)YES-Default UTM medium for the page
utm_campaignVARCHAR(255)YES-Default UTM campaign for the page
utm_termVARCHAR(255)YES-Default UTM term for the page
utm_contentVARCHAR(255)YES-Default UTM content for the page
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO-Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO-Last updater (user id)

Table content_page_analytics

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
content_page_idINTEGERNO-Content page this row belongs to (unique — 1:1 relation)
ga_eventsJSONBYES-Google Analytics event configuration
fb_pixel_eventsTEXTYES-Facebook Pixel event configuration
line_tag_eventsTEXTYES-LINE Tag event configuration
custom_head_scriptsTEXTYES-Extra scripts injected into the page head
custom_body_scriptsTEXTYES-Extra scripts injected into the page body
enable_gaBOOLEANNOtrueWhether Google Analytics is enabled
enable_fb_pixelBOOLEANNOfalseWhether Facebook Pixel is enabled
enable_line_tagBOOLEANNOfalseWhether LINE Tag is enabled
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO-Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO-Last updater (user id)

Table content_page_view

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
content_page_idINTEGERNO-Content page that was viewed (FK to content_page.id)
viewer_ipVARCHAR(45)YES-Viewer IP address (IPv6 capable)
viewer_user_agentTEXTYES-Viewer user agent
viewer_referrerTEXTYES-Referrer URL the viewer arrived from
viewer_line_uidVARCHAR(255)YES-Viewer LINE user id (when identifiable)
utm_sourceVARCHAR(255)YES-UTM source carried by the visit
utm_mediumVARCHAR(255)YES-UTM medium carried by the visit
utm_campaignVARCHAR(255)YES-UTM campaign carried by the visit
utm_termVARCHAR(255)YES-UTM term carried by the visit
utm_contentVARCHAR(255)YES-UTM content carried by the visit
session_idVARCHAR(255)YES-Viewer session id (used to count unique views)
languageVARCHAR(10)YES-Language the viewer opened the page in
device_typeVARCHAR(50)YES-Viewer device type
viewed_atTIMESTAMPTZ(3)NOnow()Visit timestamp

Notes

  • content_page has a unique constraint on (line_oa_id, slug) — a slug must be unique within one OA, but different OAs may reuse the same slug
  • Both content_page.public_token and content_page.uuid have unique constraints
  • All 4 child tables have a FK to content_page.id with ON DELETE CASCADE — deleting a page removes its translations, UTM row, analytics row and view logs
  • content_page_utm.content_page_id and content_page_analytics.content_page_id are unique, making them 1:1 relations with content_page
  • content_page_translation has a unique constraint on (content_page_id, language) — one translation per language per page
  • content_page.friend_track_campaign_id is a FK to friend_track_campaign.id with ON DELETE SET NULL — deleting the campaign keeps the page and nulls the reference
  • content_page.category_id / subcategory_id are FKs to content_category.id and content_subcategory.id (see Content Categories and Link Collections)
  • content_page.view_count and unique_view_count are counters aggregated from content_page_view, which stores per-visit logs and is indexed on content_page_id, session_id and viewed_at