生产级谷歌广告分析系统架构设计方案

生产级谷歌广告分析系统架构设计方案

下面给你一套 生产级(企业用) 的数据表设计方案,用于整合:

  • Google Ads API
    • gclid
    • 搜索字词 (search term)
    • 匹配关键词 (matched keyword)
    • campaign/ad group/ad
    • impressions/clicks/ctr/cpc/cost
    • landing page
    • conversion / conversion value
  • GA4 API / BigQuery Export
    • session_id
    • user_pseudo_id
    • 页面浏览历史 (pageview list)
    • 停留时长
    • 用户访问次数 (session_count)
    • 来源/媒介/source_medium/utm
    • 转化事件
  • 询盘 (Lead)
    • 表单提交数据
    • 来源归因(Ads or SEO)

并最终实现 广告&SEO全链路分析系统

从广告关键词 → 点击 → 会话 → 浏览行为 → 表单 → 询盘 → 转化价值
形成完整客户路径(Click → Session → Lead → Conversion)。


🚀 一、总体数据库结构(核心理念)

数据库由 6 张核心表 + 2 张辅助维表组成:


✔️ 核心 6 张事实表(Fact Tables)

  1. fact_ads_clicks(广告点击级别)
  2. fact_ga4_sessions(GA4 会话级别)
  3. fact_ga4_events(GA4 事件级别)
  4. fact_leads(询盘级别)
  5. fact_ads_conversions(Ads 转化级别)
  6. fact_lead_attribution(最终归因表,最关键)

✔️ 维表(Dimension Tables)

  1. dim_keywords
  2. dim_campaigns

接下来给你完整字段设计,每张表都可直接用于 MySQL / PostgreSQL / BigQuery


🧱 二、数据表详细设计(完全可落地)


① fact_ads_clicks(广告点击级别表)

来源:Google Ads API → GAQL(search_term_view / click_view)

CREATE TABLE fact_ads_clicks (
  gclid               STRING,
  click_time          DATETIME,
  campaign_id         STRING,
  campaign_name       STRING,
  ad_group_id         STRING,
  ad_group_name       STRING,
  ad_id               STRING,
  keyword_id          STRING,
  keyword_text        STRING,
  match_type          STRING,          -- exact/broad/phrase
  search_term         STRING,
  final_url           STRING,
  device              STRING,

  impressions         INT,
  clicks              INT,
  cost_micros         BIGINT,
  currency_code       STRING,

  created_at          DATETIME
);

用途:

  • 按 gclid → lead → conversion 完整追踪
  • 分析搜索字词 / 关键词 / 平台 / 设备
  • 计算广告 ROI / CPA / ROAS

② fact_ga4_sessions(会话级别表)

来源:GA4 BigQuery Export 或 GA4 API → runReport

CREATE TABLE fact_ga4_sessions (
  session_id            STRING,       -- ga_session_id
  user_pseudo_id        STRING,       -- 匿名用户ID
  gclid                 STRING,       -- GA4 自动提取
  source                STRING,
  medium                STRING,
  campaign              STRING,
  utm_term              STRING,
  landing_page          STRING,
  device_category       STRING,

  session_start         DATETIME,
  session_end           DATETIME,
  engagement_time_ms    INT,
  page_view_count       INT,
  session_number        INT,          -- 访问次数(GA4: ga_session_number)

  created_at            DATETIME
);

用途:

  • 分析 SEO vs 广告流量
  • 落地页效果
  • 用户停留时间、互动度

③ fact_ga4_events(用户行为事件级表)

来自 GA4 BigQuery Export(event table)

CREATE TABLE fact_ga4_events (
  event_id        STRING,
  session_id      STRING,
  user_pseudo_id  STRING,
  event_name      STRING,
  event_time      DATETIME,
  page_location   STRING,
  page_referrer   STRING,
  engagement_time INT,
  gclid           STRING,
  event_params    JSON
);

用途:

  • 构建用户浏览路径(page flow)
  • 分析用户行为:滚动、输出、按钮点击
  • 观察 SEO/Ads 用户质量(互动度)

④ fact_leads(询盘级别表)

来自:WordPress 表单 / CRM

CREATE TABLE fact_leads (
  lead_id           STRING,
  name              STRING,
  email             STRING,
  phone             STRING,
  message           STRING,

  gclid             STRING,
  ga_session_id     STRING,
  user_pseudo_id    STRING,
  landing_page      STRING,
  utm_source        STRING,
  utm_medium        STRING,
  utm_campaign      STRING,
  utm_term          STRING,

  ip_address        STRING,
  user_agent        STRING,

  created_at        DATETIME
);

用途:

  • 询盘来源识别(广告 or SEO)
  • 按 gclid 绑定 Ads
  • 按 session_id 绑定 GA4 会话
  • 全链路漏斗分析

⑤ fact_ads_conversions(广告转化表)

来自:Google Ads API 或 UploadConversion API

CREATE TABLE fact_ads_conversions (
  conversion_id        STRING,
  gclid                STRING,
  conversion_action    STRING,
  conversion_time      DATETIME,
  conversion_value     DECIMAL(10,2),
  conversion_currency  STRING,
  created_at           DATETIME
);

用途:

  • 广告真实转化
  • 用于与 leads 关联后分析 ROI/ROAS

⑥ fact_lead_attribution(最终归因表)

这个表是整个系统最终使用的 分析核心表

CREATE TABLE fact_lead_attribution (
  lead_id             STRING,
  gclid               STRING,
  session_id          STRING,
  user_pseudo_id      STRING,

  -- Ads 信息
  campaign_id         STRING,
  campaign_name       STRING,
  ad_group_id         STRING,
  ad_group_name       STRING,
  keyword_id          STRING,
  keyword_text        STRING,
  match_type          STRING,
  search_term         STRING,
  device              STRING,
  final_url           STRING,
  click_time          DATETIME,
  cost_micros         BIGINT,

  -- GA4 会话行为
  landing_page        STRING,
  pageview_count      INT,
  engagement_time_ms  INT,
  session_number      INT,

  -- 转化
  conversion_value    DECIMAL(10,2),
  conversion_time     DATETIME,
  conversion_action   STRING,

  attribution_model   STRING,    -- last_click / data_driven / position_based
  attribution_weight  DECIMAL(5,4),

  created_at          DATETIME
);

这是投手、老板最需要的表。
每一行 = 一个 Lead 及其完整来源信息。


🧱 三、维表(供 JOIN 和报表使用)


⑦ dim_keywords(关键词维表)

CREATE TABLE dim_keywords (
  keyword_id       STRING,
  keyword_text     STRING,
  match_type       STRING,
  status           STRING,
  created_at       DATETIME
);

⑧ dim_campaigns

CREATE TABLE dim_campaigns (
  campaign_id      STRING,
  campaign_name    STRING,
  budget           DECIMAL(10,2),
  status           STRING,
  created_at       DATETIME
);

🎯 四、关键 Join 逻辑(全链路贯通)

1. Ads → Lead(通过 gclid)

SELECT *
FROM fact_ads_clicks a
JOIN fact_leads l ON a.gclid = l.gclid

2. GA4 Session → Lead(通过 session_id)

SELECT *
FROM fact_ga4_sessions s
JOIN fact_leads l ON s.session_id = l.ga_session_id

3. GA4 Events → Session(session_id)

SELECT *
FROM fact_ga4_events e
JOIN fact_ga4_sessions s ON e.session_id = s.session_id

4. Ads Conversion → Lead

SELECT *
FROM fact_ads_conversions c
JOIN fact_leads l USING (gclid)

5. 最终归因写入 fact_lead_attribution(ETL 逻辑)

  • 使用 Last Click
  • 或使用 GA4 data-driven 模型
  • 或自定义模型

🧠 五、这套表能分析什么?(专业投手级)

你的分析能力将提升到:

✔ 广告效果(投手 KPI)

  • search term 的 真实询盘产生率
  • 每个关键词的 CPA / ROAS / 转化率
  • 每个落地页的 询盘产出能力
  • 设备性能(mobile/desktop)
  • 广告花费 vs Lead 价值曲线

✔ SEO 效果

  • 拿到会话 → 页面浏览 → 表单提交 → lead
  • 每个自然关键词 / 页面转化率
  • 用户停留时长、跳出率、流量质量

✔ 用户行为路径(GA4)

  • 点击广告后访问了哪些页面?
  • 停留多久?
  • 看了几页?
  • 最后在哪个页面提交表单?

✔ 询盘全链路数据(老板级)

“哪个关键词 → 产生了哪些询盘 → 哪些询盘成单 → 赚了多少钱”

=====================最终优化方案如下===============================



生产级广告&SEO全链路分析系统 – 数据库设计与实现方案

📋 目录

  1. 方案概述
  2. 数据库架构设计
  3. 表结构详细设计(优化版)
  4. 数据同步与ETL流程
  5. 关键优化点
  6. 实现方案
  7. 查询与分析场景
  8. 性能优化策略
  9. 实施路线图

一、方案概述

1.1 业务目标

构建一个生产级的广告&SEO全链路分析系统,实现从广告关键词 → 点击 → 会话 → 浏览行为 → 表单 → 询盘 → 转化价值的完整客户路径追踪。

1.2 核心价值

  • 广告效果精准分析:每个关键词的ROI、CPA、ROAS
  • SEO效果评估:自然流量的转化路径和质量
  • 用户行为洞察:完整的用户浏览路径和交互行为
  • 数据驱动决策:支持多维度的数据分析和报表

1.3 技术架构

数据源层
├── Google Ads API (GAQL查询)
├── GA4 BigQuery Export / GA4 API
└── WordPress 表单提交

数据采集层
├── 实时采集(询盘提交时)
├── 异步同步(后台任务)
└── 批量导入(历史数据)

数据存储层
├── 6张事实表(Fact Tables)
├── 2张维表(Dimension Tables)
└── 1张归因表(Attribution Table)

分析应用层
├── ROI/ROAS计算
├── 转化路径分析
├── 用户行为分析
└── 报表可视化

二、数据库架构设计

2.1 表结构总览

核心事实表(6张)
├── fact_ads_clicks       (广告点击级别)
├── fact_ga4_sessions     (GA4会话级别)
├── fact_ga4_events       (GA4事件级别)
├── fact_leads           (询盘级别)
├── fact_ads_conversions (Ads转化级别)
└── fact_lead_attribution (最终归因表)

维表(2张)
├── dim_keywords         (关键词维表)
└── dim_campaigns         (广告系列维表)

辅助表(可选)
├── dim_devices           (设备维表)
├── dim_landing_pages     (着陆页维表)
└── dim_geo_locations     (地理位置维表)

2.2 数据流向图

Google Ads API
  ↓
fact_ads_clicks (gclid)
  ↓
fact_ads_conversions
  ↓
      ┌──────────────┐
      │             │
GA4 API/BigQuery       │
  ↓                 │
fact_ga4_sessions     │
  ↓                 │
fact_ga4_events       │
  ↓                 │
      └──────────────┘
          ↓
fact_leads (关联gclid/session_id)
  ↓
fact_lead_attribution (最终归因)

三、表结构详细设计(优化版)

3.1 fact_ads_clicks(广告点击级别表)

优化点

  • 添加分区字段(按日期分区)
  • 添加时区字段
  • 优化索引策略
  • 添加数据质量字段
CREATE TABLE fact_ads_clicks (
 -- 主键和关联
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
gclid               VARCHAR(255) NOT NULL COMMENT 'Google Click ID',
 
 -- 时间字段
click_date          DATE NOT NULL COMMENT '点击日期(用于分区)',
click_time          DATETIME NOT NULL COMMENT '点击时间',
click_timezone      VARCHAR(50) DEFAULT 'UTC' COMMENT '时区',
 
 -- 广告层级信息
account_id          VARCHAR(50) COMMENT '广告账户ID',
account_name        VARCHAR(255) COMMENT '广告账户名称',
campaign_id         VARCHAR(50) NOT NULL COMMENT '广告系列ID',
campaign_name       VARCHAR(255) COMMENT '广告系列名称',
ad_group_id         VARCHAR(50) COMMENT '广告组ID',
ad_group_name       VARCHAR(255) COMMENT '广告组名称',
ad_id               VARCHAR(50) COMMENT '广告ID',
ad_type             VARCHAR(50) COMMENT '广告类型:search, display, video等',
 
 -- 关键词信息
keyword_id          VARCHAR(50) COMMENT '关键词ID',
keyword_text        VARCHAR(500) COMMENT '关键词文本',
match_type          VARCHAR(20) COMMENT '匹配类型:exact, phrase, broad, bmm',
search_term         VARCHAR(500) COMMENT '搜索字词(用户实际搜索的词)',
 
 -- 网址和位置
final_url           TEXT COMMENT '最终URL',
display_url         VARCHAR(500) COMMENT '显示URL',
landing_page        TEXT COMMENT '着陆页URL',
 
 -- 设备和位置
device              VARCHAR(50) COMMENT '设备类型:mobile, desktop, tablet',
network_type        VARCHAR(50) COMMENT '网络类型:search, display, video, shopping',
country_code        VARCHAR(10) COMMENT '国家代码',
location            VARCHAR(255) COMMENT '地理位置',
 
 -- 广告指标
impressions         INT UNSIGNED DEFAULT 0 COMMENT '展示次数',
clicks              INT UNSIGNED DEFAULT 0 COMMENT '点击次数',
ctr                 DECIMAL(10,4) COMMENT '点击率',
cost_micros         BIGINT UNSIGNED DEFAULT 0 COMMENT '花费(微单位)',
cost                DECIMAL(15,2) COMMENT '花费(实际金额)',
currency_code       VARCHAR(10) DEFAULT 'USD' COMMENT '货币代码',
avg_cpc             DECIMAL(15,2) COMMENT '平均每次点击费用',
 
 -- 质量指标
quality_score       INT COMMENT '质量得分(1-10)',
expected_ctr        DECIMAL(10,4) COMMENT '预期点击率',
ad_relevance        INT COMMENT '广告相关性',
landing_page_exp    INT COMMENT '着陆页体验',
 
 -- 数据质量字段
data_source         VARCHAR(50) DEFAULT 'google_ads_api' COMMENT '数据来源',
sync_status         VARCHAR(20) DEFAULT 'synced' COMMENT '同步状态:pending, synced, failed',
sync_time           DATETIME COMMENT '同步时间',
raw_data           JSON COMMENT '原始API响应数据(JSON格式)',
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 -- 索引
 INDEX idx_gclid (gclid),
 INDEX idx_click_date (click_date),
 INDEX idx_campaign_id (campaign_id),
 INDEX idx_keyword_id (keyword_id),
 INDEX idx_search_term (search_term(100)),
 INDEX idx_device (device),
 INDEX idx_click_time (click_time),
 INDEX idx_sync_status (sync_status),
 
 -- 唯一索引(防止重复)
 UNIQUE KEY uk_gclid_click_time (gclid, click_time)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(click_date)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01')),
 -- 可以继续添加更多分区
);

关键优化

  1. ✅ 按日期分区,提高查询性能
  2. ✅ 添加质量得分等字段
  3. ✅ 添加同步状态,支持增量同步
  4. ✅ 保存原始数据,便于问题排查
  5. ✅ 唯一索引防止重复数据

3.2 fact_ga4_sessions(GA4会话级别表)

优化点

  • 添加会话时长计算字段
  • 添加参与度指标
  • 优化索引策略
CREATE TABLE fact_ga4_sessions (
 -- 主键和关联
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
session_id          VARCHAR(255) NOT NULL COMMENT 'GA4会话ID',
user_pseudo_id      VARCHAR(255) NOT NULL COMMENT 'GA4用户伪ID',
user_id             VARCHAR(255) COMMENT '用户ID(如果已登录)',
 
 -- GCLID关联
gclid               VARCHAR(255) COMMENT 'Google Click ID(如果有)',
 
 -- 会话时间
session_date        DATE NOT NULL COMMENT '会话日期(用于分区)',
session_start       DATETIME NOT NULL COMMENT '会话开始时间',
session_end         DATETIME COMMENT '会话结束时间',
session_duration    INT UNSIGNED COMMENT '会话时长(秒)',
 
 -- 来源信息
 source              VARCHAR(255) COMMENT '来源',
 medium              VARCHAR(255) COMMENT '媒介',
campaign            VARCHAR(255) COMMENT '广告系列',
term                VARCHAR(500) COMMENT '关键词',
content             VARCHAR(500) COMMENT '内容',
 
 -- UTM参数
utm_source          VARCHAR(255) COMMENT 'UTM来源',
utm_medium          VARCHAR(255) COMMENT 'UTM媒介',
utm_campaign        VARCHAR(255) COMMENT 'UTM广告系列',
utm_term            VARCHAR(500) COMMENT 'UTM关键词',
utm_content         VARCHAR(500) COMMENT 'UTM内容',
 
 -- 页面信息
landing_page        TEXT COMMENT '着陆页URL',
landing_page_path   VARCHAR(500) COMMENT '着陆页路径',
exit_page           TEXT COMMENT '退出页URL',
 
 -- 设备和位置
device_category     VARCHAR(50) COMMENT '设备类别',
device_brand        VARCHAR(100) COMMENT '设备品牌',
device_model        VARCHAR(100) COMMENT '设备型号',
operating_system    VARCHAR(100) COMMENT '操作系统',
browser             VARCHAR(100) COMMENT '浏览器',
country             VARCHAR(100) COMMENT '国家',
city                VARCHAR(100) COMMENT '城市',
region              VARCHAR(100) COMMENT '地区',
 
 -- 会话指标
page_view_count     INT UNSIGNED DEFAULT 0 COMMENT '页面浏览量',
session_number      INT UNSIGNED DEFAULT 1 COMMENT '会话序号(第几次访问)',
engagement_time_ms  INT UNSIGNED DEFAULT 0 COMMENT '参与时间(毫秒)',
engagement_rate     DECIMAL(10,4) COMMENT '参与率',
bounce_rate         DECIMAL(10,4) COMMENT '跳出率',
is_bounce           TINYINT(1) DEFAULT 0 COMMENT '是否跳出',
 
 -- 转化指标
conversion_count    INT UNSIGNED DEFAULT 0 COMMENT '转化次数',
conversion_value    DECIMAL(15,2) DEFAULT 0 COMMENT '转化价值',
 
 -- 数据质量字段
data_source         VARCHAR(50) DEFAULT 'ga4_api' COMMENT '数据来源',
property_id         VARCHAR(50) COMMENT 'GA4属性ID',
sync_status         VARCHAR(20) DEFAULT 'synced',
sync_time           DATETIME,
raw_data           JSON COMMENT '原始数据',
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 -- 索引
 INDEX idx_session_id (session_id),
 INDEX idx_user_pseudo_id (user_pseudo_id),
 INDEX idx_gclid (gclid),
 INDEX idx_session_date (session_date),
 INDEX idx_source_medium (source, medium),
 INDEX idx_utm_campaign (utm_campaign),
 INDEX idx_session_start (session_start),
 INDEX idx_sync_status (sync_status),
 
 -- 唯一索引
 UNIQUE KEY uk_session_id (session_id)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(session_date)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01'))
);

3.3 fact_ga4_events(GA4事件级别表)

优化点

  • 使用JSON字段存储事件参数
  • 优化查询性能
  • 支持事件序列分析
CREATE TABLE fact_ga4_events (
 -- 主键
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
 
 -- 关联字段
event_id            VARCHAR(255) NOT NULL COMMENT '事件ID(唯一)',
session_id          VARCHAR(255) NOT NULL COMMENT '会话ID',
user_pseudo_id      VARCHAR(255) NOT NULL COMMENT '用户伪ID',
 
 -- 事件信息
event_date          DATE NOT NULL COMMENT '事件日期(用于分区)',
event_time          DATETIME NOT NULL COMMENT '事件时间',
event_name          VARCHAR(255) NOT NULL COMMENT '事件名称',
 
 -- 页面信息
page_location       TEXT COMMENT '页面URL',
page_path           VARCHAR(500) COMMENT '页面路径',
page_title          VARCHAR(500) COMMENT '页面标题',
page_referrer       TEXT COMMENT '来源页面',
 
 -- 事件参数(JSON格式存储所有参数)
event_params       JSON COMMENT '事件参数(JSON格式)',
 
 -- 常用参数(提取到独立字段便于查询)
engagement_time     INT UNSIGNED COMMENT '参与时间(秒)',
 value               DECIMAL(15,2) COMMENT '事件价值',
currency            VARCHAR(10) COMMENT '货币',
 
 -- 设备和位置
device_category     VARCHAR(50),
country             VARCHAR(100),
city                VARCHAR(100),
 
 -- 数据质量
data_source         VARCHAR(50) DEFAULT 'ga4_bigquery',
property_id         VARCHAR(50),
sync_status         VARCHAR(20) DEFAULT 'synced',
sync_time           DATETIME,
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
 
 -- 索引
 INDEX idx_event_id (event_id),
 INDEX idx_session_id (session_id),
 INDEX idx_user_pseudo_id (user_pseudo_id),
 INDEX idx_event_date (event_date),
 INDEX idx_event_name (event_name),
 INDEX idx_event_time (event_time),
 INDEX idx_session_event (session_id, event_time),
 
 -- 唯一索引
 UNIQUE KEY uk_event_id (event_id)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(event_date)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01'))
);

事件参数JSON结构示例

{
 "page_title": "产品详情页",
 "page_location": "https://example.com/products/123",
 "engagement_time_msec": 5000,
 "link_url": "https://example.com/contact",
 "link_text": "联系我们",
 "method": "click"
}

3.4 fact_leads(询盘级别表)

优化点

  • 关联所有来源标识符
  • 添加质量评分字段
  • 支持多表单类型
CREATE TABLE fact_leads (
 -- 主键
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
lead_id             VARCHAR(100) NOT NULL COMMENT '询盘ID(业务唯一标识)',
 
 -- 关联字段(用于关联Ads和GA4数据)
gclid               VARCHAR(255) COMMENT 'Google Click ID',
session_id          VARCHAR(255) COMMENT 'GA4会话ID',
user_pseudo_id      VARCHAR(255) COMMENT 'GA4用户伪ID',
 
 -- 询盘基本信息
name                VARCHAR(255) COMMENT '姓名',
email               VARCHAR(255) NOT NULL COMMENT '邮箱',
phone               VARCHAR(50) COMMENT '电话',
company             VARCHAR(255) COMMENT '公司',
message             TEXT COMMENT '留言内容',
subject             VARCHAR(500) COMMENT '主题',
 
 -- 表单信息
form_id             VARCHAR(100) COMMENT '表单ID',
form_name           VARCHAR(255) COMMENT '表单名称',
form_type           VARCHAR(50) COMMENT '表单类型:contact, quote, demo等',
 
 -- 来源信息
landing_page        TEXT COMMENT '着陆页URL',
referrer_url        TEXT COMMENT '来源页面URL',
utm_source          VARCHAR(255) COMMENT 'UTM来源',
utm_medium          VARCHAR(255) COMMENT 'UTM媒介',
utm_campaign        VARCHAR(255) COMMENT 'UTM广告系列',
utm_term            VARCHAR(500) COMMENT 'UTM关键词',
utm_content         VARCHAR(500) COMMENT 'UTM内容',
 
 -- 位置信息
ip_address          VARCHAR(45) COMMENT 'IP地址',
country             VARCHAR(100) COMMENT '国家',
region              VARCHAR(100) COMMENT '省份/地区',
city                VARCHAR(100) COMMENT '城市',
 
 -- 设备信息
user_agent          TEXT COMMENT '用户代理',
device_type         VARCHAR(50) COMMENT '设备类型',
browser             VARCHAR(100) COMMENT '浏览器',
os                  VARCHAR(100) COMMENT '操作系统',
 
 -- 时间信息
lead_date           DATE NOT NULL COMMENT '询盘日期(用于分区)',
lead_time           DATETIME NOT NULL COMMENT '询盘提交时间',
first_visit_time    DATETIME COMMENT '首次访问时间',
time_to_lead        INT COMMENT '从首次访问到询盘的时间(秒)',
 
 -- 质量评分
lead_score          INT COMMENT '询盘质量评分(1-100)',
lead_status         VARCHAR(50) DEFAULT 'new' COMMENT '状态:new, contacted, qualified, converted, lost',
is_qualified        TINYINT(1) DEFAULT 0 COMMENT '是否合格',
 
 -- 转化价值
estimated_value     DECIMAL(15,2) COMMENT '预估价值',
actual_value        DECIMAL(15,2) COMMENT '实际价值(成交后更新)',
 
 -- 数据质量
data_source         VARCHAR(50) DEFAULT 'wordpress_form',
sync_status         VARCHAR(20) DEFAULT 'synced',
sync_time           DATETIME,
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 -- 索引
 INDEX idx_lead_id (lead_id),
 INDEX idx_gclid (gclid),
 INDEX idx_session_id (session_id),
 INDEX idx_user_pseudo_id (user_pseudo_id),
 INDEX idx_lead_date (lead_date),
 INDEX idx_email (email),
 INDEX idx_lead_status (lead_status),
 INDEX idx_utm_campaign (utm_campaign),
 INDEX idx_sync_status (sync_status),
 
 -- 唯一索引
 UNIQUE KEY uk_lead_id (lead_id)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(lead_date)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01'))
);

3.5 fact_ads_conversions(广告转化表)

优化点

  • 支持多个转化动作
  • 关联原始点击数据
CREATE TABLE fact_ads_conversions (
 -- 主键
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
conversion_id       VARCHAR(255) NOT NULL COMMENT '转化ID(唯一)',
 
 -- 关联字段
gclid               VARCHAR(255) NOT NULL COMMENT 'GCLID(关联点击)',
 
 -- 转化信息
conversion_date     DATE NOT NULL COMMENT '转化日期(用于分区)',
conversion_time     DATETIME NOT NULL COMMENT '转化时间',
conversion_action   VARCHAR(255) NOT NULL COMMENT '转化动作名称',
conversion_action_id VARCHAR(100) COMMENT '转化动作ID',
 
 -- 转化价值
conversion_value    DECIMAL(15,2) DEFAULT 0 COMMENT '转化价值',
conversion_currency VARCHAR(10) DEFAULT 'USD' COMMENT '货币',
 
 -- 转化类型
conversion_type     VARCHAR(50) COMMENT '转化类型:click, view, call等',
conversion_category VARCHAR(50) COMMENT '转化类别:purchase, lead, signup等',
 
 -- 关联询盘
lead_id             VARCHAR(100) COMMENT '关联的询盘ID',
 
 -- 数据质量
data_source         VARCHAR(50) DEFAULT 'google_ads_api',
sync_status         VARCHAR(20) DEFAULT 'synced',
sync_time           DATETIME,
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
 
 -- 索引
 INDEX idx_conversion_id (conversion_id),
 INDEX idx_gclid (gclid),
 INDEX idx_conversion_date (conversion_date),
 INDEX idx_conversion_action (conversion_action),
 INDEX idx_lead_id (lead_id),
 
 -- 唯一索引
 UNIQUE KEY uk_conversion_id (conversion_id)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(conversion_date)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01'))
);

3.6 fact_lead_attribution(最终归因表)⭐核心表

优化点

  • 支持多种归因模型
  • 完整保存归因逻辑
  • 便于直接查询分析
CREATE TABLE fact_lead_attribution (
 -- 主键
id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
 
 -- 关联字段
lead_id             VARCHAR(100) NOT NULL COMMENT '询盘ID',
gclid               VARCHAR(255) COMMENT 'GCLID',
session_id          VARCHAR(255) COMMENT '会话ID',
user_pseudo_id      VARCHAR(255) COMMENT '用户伪ID',
 
 -- ========== Ads 信息 ==========
account_id          VARCHAR(50) COMMENT '广告账户ID',
account_name        VARCHAR(255) COMMENT '广告账户名称',
campaign_id         VARCHAR(50) COMMENT '广告系列ID',
campaign_name       VARCHAR(255) COMMENT '广告系列名称',
ad_group_id         VARCHAR(50) COMMENT '广告组ID',
ad_group_name       VARCHAR(255) COMMENT '广告组名称',
ad_id               VARCHAR(50) COMMENT '广告ID',
 
 -- 关键词信息
keyword_id          VARCHAR(50) COMMENT '关键词ID',
keyword_text        VARCHAR(500) COMMENT '关键词文本',
match_type          VARCHAR(20) COMMENT '匹配类型',
search_term         VARCHAR(500) COMMENT '搜索字词',
 
 -- Ads时间和成本
click_time          DATETIME COMMENT '点击时间',
click_date          DATE COMMENT '点击日期',
cost_micros         BIGINT UNSIGNED DEFAULT 0 COMMENT '花费(微单位)',
cost                DECIMAL(15,2) COMMENT '花费(实际金额)',
currency_code       VARCHAR(10) DEFAULT 'USD' COMMENT '货币',
 
 -- Ads指标
impressions         INT UNSIGNED DEFAULT 0 COMMENT '展示次数',
clicks              INT UNSIGNED DEFAULT 0 COMMENT '点击次数',
ctr                 DECIMAL(10,4) COMMENT '点击率',
quality_score       INT COMMENT '质量得分',
 
 -- 网址和位置
landing_page        TEXT COMMENT '着陆页URL',
final_url           TEXT COMMENT '最终URL',
device              VARCHAR(50) COMMENT '设备类型',
country_code        VARCHAR(10) COMMENT '国家代码',
 
 -- ========== GA4 会话信息 ==========
 source              VARCHAR(255) COMMENT '来源',
 medium              VARCHAR(255) COMMENT '媒介',
utm_campaign        VARCHAR(255) COMMENT 'UTM广告系列',
utm_term            VARCHAR(500) COMMENT 'UTM关键词',
 
 -- GA4行为指标
pageview_count      INT UNSIGNED DEFAULT 0 COMMENT '页面浏览量',
session_duration    INT UNSIGNED COMMENT '会话时长(秒)',
engagement_time_ms  INT UNSIGNED COMMENT '参与时间(毫秒)',
session_number      INT UNSIGNED COMMENT '会话序号',
bounce_rate         DECIMAL(10,4) COMMENT '跳出率',
 
 -- ========== 时间信息 ==========
first_visit_time    DATETIME COMMENT '首次访问时间',
last_visit_time     DATETIME COMMENT '最后访问时间',
conversion_time     DATETIME NOT NULL COMMENT '转化时间(询盘提交时间)',
days_to_conversion  INT COMMENT '从首次访问到转化的天数',
 
 -- ========== 转化信息 ==========
conversion_action   VARCHAR(255) COMMENT '转化动作',
conversion_value    DECIMAL(15,2) DEFAULT 0 COMMENT '转化价值',
conversion_currency VARCHAR(10) DEFAULT 'USD' COMMENT '转化货币',
 
 -- ========== 归因信息 ==========
attribution_model   VARCHAR(50) DEFAULT 'last_click' COMMENT '归因模型:last_click, first_click, linear, time_decay, position_based, data_driven',
attribution_weight  DECIMAL(5,4) DEFAULT 1.0000 COMMENT '归因权重(0-1)',
is_primary_source   TINYINT(1) DEFAULT 1 COMMENT '是否为主要来源',
source_type         VARCHAR(50) COMMENT '来源类型:ads, seo, direct, referral, email, social',
 
 -- ========== 询盘质量 ==========
lead_score          INT COMMENT '询盘质量评分',
lead_status         VARCHAR(50) COMMENT '询盘状态',
estimated_value     DECIMAL(15,2) COMMENT '预估价值',
actual_value        DECIMAL(15,2) COMMENT '实际价值',
 
 -- ========== 计算指标 ==========
 -- ROI相关
roas                DECIMAL(10,4) COMMENT 'ROAS = conversion_value / cost',
roi_percentage      DECIMAL(10,2) COMMENT 'ROI百分比 = (conversion_value - cost) / cost * 100',
cpa                 DECIMAL(15,2) COMMENT 'CPA = cost / conversions',
 
 -- 效率指标
cost_per_lead       DECIMAL(15,2) COMMENT '每个询盘成本',
value_per_lead      DECIMAL(15,2) COMMENT '每个询盘价值',
lead_to_value_ratio DECIMAL(10,4) COMMENT '询盘价值比',
 
 -- ========== 数据质量 ==========
attribution_method  VARCHAR(50) COMMENT '归因方法:automatic, manual, rule_based',
confidence_score    DECIMAL(5,4) COMMENT '归因置信度(0-1)',
data_completeness   DECIMAL(5,4) COMMENT '数据完整性(0-1)',
 
 -- 时间戳
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 -- ========== 索引 ==========
 INDEX idx_lead_id (lead_id),
 INDEX idx_gclid (gclid),
 INDEX idx_session_id (session_id),
 INDEX idx_campaign_id (campaign_id),
 INDEX idx_keyword_id (keyword_id),
 INDEX idx_search_term (search_term(100)),
 INDEX idx_conversion_time (conversion_time),
 INDEX idx_conversion_date (DATE(conversion_time)),
 INDEX idx_source_type (source_type),
 INDEX idx_attribution_model (attribution_model),
 INDEX idx_lead_status (lead_status),
 
 -- 复合索引
 INDEX idx_campaign_conversion (campaign_id, conversion_time),
 INDEX idx_keyword_conversion (keyword_id, conversion_time),
 
 -- 唯一索引(一个询盘一条归因记录)
 UNIQUE KEY uk_lead_id (lead_id)
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
PARTITION BY RANGE (TO_DAYS(conversion_time)) (
 PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
 PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01'))
);

这是整个系统的核心表,每一行代表一个询盘的完整归因信息。


3.7 维表设计

dim_keywords(关键词维表)

CREATE TABLE dim_keywords (
keyword_id          VARCHAR(50) PRIMARY KEY,
keyword_text        VARCHAR(500) NOT NULL,
match_type          VARCHAR(20) COMMENT 'exact, phrase, broad, bmm',
 
 -- 关键词分类
keyword_category    VARCHAR(100) COMMENT '关键词类别',
keyword_group       VARCHAR(100) COMMENT '关键词分组',
 
 -- 状态
 status              VARCHAR(50) DEFAULT 'active' COMMENT 'active, paused, deleted',
bid_strategy        VARCHAR(50) COMMENT '出价策略',
max_cpc             DECIMAL(15,2) COMMENT '最高CPC',
 
 -- 统计信息(定期更新)
total_clicks        INT UNSIGNED DEFAULT 0,
total_cost          DECIMAL(15,2) DEFAULT 0,
total_conversions   INT UNSIGNED DEFAULT 0,
avg_quality_score   DECIMAL(5,2) COMMENT '平均质量得分',
 
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 INDEX idx_status (status),
 INDEX idx_keyword_text (keyword_text(100))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

dim_campaigns(广告系列维表)

CREATE TABLE dim_campaigns (
campaign_id         VARCHAR(50) PRIMARY KEY,
account_id          VARCHAR(50) NOT NULL,
account_name        VARCHAR(255),
campaign_name       VARCHAR(255) NOT NULL,
 
 -- 系列类型
campaign_type       VARCHAR(50) COMMENT 'search, display, video, shopping',
campaign_status     VARCHAR(50) DEFAULT 'active' COMMENT 'active, paused, removed',
 
 -- 预算信息
budget              DECIMAL(15,2) COMMENT '预算',
budget_type         VARCHAR(50) COMMENT 'daily, total',
budget_currency     VARCHAR(10) DEFAULT 'USD',
 
 -- 目标
campaign_goal       VARCHAR(100) COMMENT 'campaign目标',
target_roas         DECIMAL(10,4) COMMENT '目标ROAS',
target_cpa          DECIMAL(15,2) COMMENT '目标CPA',
 
 -- 统计信息(定期更新)
total_clicks        INT UNSIGNED DEFAULT 0,
total_cost          DECIMAL(15,2) DEFAULT 0,
total_conversions   INT UNSIGNED DEFAULT 0,
avg_roas            DECIMAL(10,4) COMMENT '平均ROAS',
 
created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
 INDEX idx_account_id (account_id),
 INDEX idx_status (campaign_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

四、数据同步与ETL流程

4.1 数据采集流程

┌─────────────────────────────────────────────────────────────┐
│                   数据采集流程                               │
└─────────────────────────────────────────────────────────────┘

1. 实时采集(询盘提交时)
  ├── 从URL参数获取:gclid, utm参数
  ├── 从Cookie获取:_ga, _ga_session_id
  ├── 从Session获取:用户行为数据
  └── 创建 fact_leads 记录

2. 异步同步(后台任务)
  ├── 通过GCLID拉取Google Ads数据 → fact_ads_clicks
  ├── 通过Session ID拉取GA4数据 → fact_ga4_sessions
  ├── 拉取GA4事件数据 → fact_ga4_events
  └── 拉取Ads转化数据 → fact_ads_conversions

3. 定期批量同步
  ├── 每日同步前一天的完整数据
  ├── 每周同步历史数据
  └── 每月数据归档和清理

4.2 ETL归因流程

-- 归因ETL逻辑(伪代码)

-- 步骤1:从fact_leads获取所有询盘
-- 步骤2:通过gclid关联fact_ads_clicks
-- 步骤3:通过session_id关联fact_ga4_sessions和fact_ga4_events
-- 步骤4:计算归因权重(根据归因模型)
-- 步骤5:写入fact_lead_attribution

INSERT INTO fact_lead_attribution (
lead_id, gclid, session_id,
campaign_id, campaign_name,
keyword_id, keyword_text, search_term,
click_time, cost, conversion_time, conversion_value,
source_type, attribution_model, attribution_weight,
roas, roi_percentage, cpa
)
SELECT
l.lead_id,
l.gclid,
l.session_id,
a.campaign_id,
a.campaign_name,
a.keyword_id,
a.keyword_text,
a.search_term,
a.click_time,
a.cost,
l.lead_time as conversion_time,
 COALESCE(c.conversion_value, l.estimated_value, 0) as conversion_value,
 CASE
   WHEN l.gclid IS NOT NULL THEN 'ads'
   WHEN s.source = 'google' AND s.medium = 'organic' THEN 'seo'
   WHEN s.source IS NULL THEN 'direct'
   ELSE 'referral'
 END as source_type,
 'last_click' as attribution_model,
 1.0 as attribution_weight,
 CASE
   WHEN a.cost > 0 THEN COALESCE(c.conversion_value, l.estimated_value, 0) / a.cost
   ELSE NULL
 END as roas,
 CASE
   WHEN a.cost > 0 THEN (COALESCE(c.conversion_value, l.estimated_value, 0) - a.cost) / a.cost * 100
   ELSE NULL
 END as roi_percentage,
a.cost as cpa
FROM fact_leads l
LEFT JOIN fact_ads_clicks a ON l.gclid = a.gclid
LEFT JOIN fact_ga4_sessions s ON l.session_id = s.session_id
LEFT JOIN fact_ads_conversions c ON l.gclid = c.gclid AND c.conversion_action = 'lead'
WHERE l.sync_status = 'synced'
 AND NOT EXISTS (
   SELECT 1 FROM fact_lead_attribution attr
   WHERE attr.lead_id = l.lead_id
 );

五、关键优化点

5.1 性能优化

  1. 分区表设计
    • 所有事实表按日期分区
    • 提高查询性能,便于数据管理
  2. 索引策略
    • 为常用查询字段创建索引
    • 复合索引支持多维度查询
    • 前缀索引用于长文本字段
  3. 数据归档
    • 定期归档历史数据
    • 保留热数据在线上,冷数据归档

5.2 数据质量

  1. 唯一性约束
    • 防止重复数据
    • 保证数据完整性
  2. 数据验证
    • 同步状态字段
    • 数据完整性评分
  3. 错误处理
    • 保存原始数据
    • 支持数据重试和修复

5.3 扩展性

  1. JSON字段
    • 存储灵活的结构化数据
    • 便于扩展新字段
  2. 预留字段
    • 支持未来业务需求
    • 便于功能扩展

六、实现方案

6.1 技术栈

  • 数据库:MySQL 8.0+ / PostgreSQL 13+ / BigQuery
  • 后端:PHP 7.4+ (WordPress插件)
  • API集成
    • Google Ads API (v22)
    • GA4 Data API / BigQuery Export
  • 任务调度:WordPress Cron / 外部调度系统

6.2 实现步骤

阶段1:数据库表创建

  • 创建所有事实表和维表
  • 创建索引和分区
  • 验证表结构

阶段2:数据采集

  • 实现实时数据采集(询盘提交时)
  • 实现Google Ads API数据同步
  • 实现GA4 API数据同步

阶段3:ETL归因

  • 实现归因逻辑
  • 实现多种归因模型
  • 实现数据计算和聚合

阶段4:查询和分析

  • 实现常用查询接口
  • 实现报表生成
  • 实现数据可视化

七、查询与分析场景

7.1 广告效果分析

-- 查询每个广告系列的ROI
SELECT
campaign_name,
 SUM(cost) as total_cost,
 SUM(conversion_value) as total_value,
 COUNT(DISTINCT lead_id) as lead_count,
 SUM(conversion_value) / SUM(cost) as roas,
 (SUM(conversion_value) - SUM(cost)) / SUM(cost) * 100 as roi_percentage,
 SUM(cost) / COUNT(DISTINCT lead_id) as cpa
FROM fact_lead_attribution
WHERE source_type = 'ads'
 AND conversion_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY campaign_id, campaign_name
ORDER BY roas DESC;

7.2 搜索词效果分析

-- 查询搜索词的询盘效果
SELECT
search_term,
matched_keyword,
 COUNT(DISTINCT lead_id) as lead_count,
 SUM(cost) as total_cost,
 SUM(conversion_value) as total_value,
 AVG(conversion_value) as avg_value,
 SUM(cost) / COUNT(DISTINCT lead_id) as cpa
FROM fact_lead_attribution
WHERE source_type = 'ads'
 AND search_term IS NOT NULL
 AND conversion_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY search_term, matched_keyword
HAVING lead_count >= 1
ORDER BY lead_count DESC, total_value DESC;

7.3 用户转化路径分析

-- 查询用户的完整浏览路径
SELECT
attr.lead_id,
attr.session_id,
attr.first_visit_time,
attr.conversion_time,
DATEDIFF(attr.conversion_time, attr.first_visit_time) as days_to_conversion,
attr.pageview_count,
attr.session_duration,
 GROUP_CONCAT(e.page_path ORDER BY e.event_time SEPARATOR ' → ') as page_path
FROM fact_lead_attribution attr
LEFT JOIN fact_ga4_events e ON attr.session_id = e.session_id
WHERE attr.lead_id = 'LEAD_12345'
GROUP BY attr.lead_id, attr.session_id;

7.4 SEO vs 广告对比

-- 对比SEO和广告来源的效果
SELECT
source_type,
 COUNT(DISTINCT lead_id) as lead_count,
 SUM(conversion_value) as total_value,
 AVG(conversion_value) as avg_value,
 AVG(pageview_count) as avg_pageviews,
 AVG(session_duration) as avg_duration,
 AVG(days_to_conversion) as avg_days_to_conversion
FROM fact_lead_attribution
WHERE conversion_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY source_type
ORDER BY lead_count DESC;

八、性能优化策略

8.1 查询优化

  1. 使用分区剪枝
    • 查询时指定日期范围
    • 只扫描相关分区
  2. 索引优化
    • 复合索引支持多字段查询
    • 覆盖索引减少回表
  3. 物化视图
    • 预计算常用统计结果
    • 定期刷新

###

Comments are closed.