跨境独立站用户行为统计模块全栈开发:多维度用户分层数据可视化落地

精细化用户运营是跨境独立站、反向海淘平台提升复购率的核心抓手,而用户行为统计看板是运营分层运营的数据底座。我在完善 Taocarts 后台用户概况统计页面时发现,早期版本仅能统计累计用户总数,缺失访客流量、浏览量、新增用户、成交用户、地域分布、性别占比等核心分析维度,运营完全无法区分新老用户消费潜力,无法精准投放优惠券、定向营销活动。结合截图中用户趋势折线图、地域 TOP 表格、性别环形饼图的落地过程,本文完整分享跨境电商平台用户行为统计模块前后端开发流程,包含用户时序埋点聚合、地域数据分组、饼图环形可视化、环比增长率计算逻辑,附带完整可复用业务代码,解决绝大多数代购源码用户统计功能简陋、无分层分析能力的痛点。

先梳理跨境独立站用户统计的专属业务需求,和国内电商系统存在明显区别:

第一,用户地域无法精准识别国内省市,大量海外用户属地标记为 "未知",统计逻辑需要兼容未知地域分组;

第二,用户访问流量分散全球,访客、浏览量数据需要独立时序存储,不能和订单数据混合统计;

第三,需要区分订单成交用户、运单成交用户两类转化群体,分别统计环比增长;

第四,性别数据存在大量未知字段,饼图渲染时需要做占比加权处理,避免未知用户数据挤占可视化图表;

第五,环比增长率计算需要自动获取上一同期周期数据,减少运营手动切换日期对比的操作成本。

整套模块分为三层实现:前端用户行为埋点上报、后端定时聚合时序用户数据、后台可视化统计看板。前端页面加载、商品点击、下单操作时自动上报埋点数据存入日志表,每日凌晨定时任务汇总当日访客数、浏览量、新增注册用户、成交用户数据,写入用户时序统计表;后台接口根据起止日期读取预聚合数据,自动计算环比增减比例,同时按用户注册属地分组统计 TOP 地域数据,分别返回折线图、表格、饼图所需结构化数据。

后端用户统计环比、地域分组核心代码

typescript 复制代码
// src/modules/statistics/service/user-stat.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Between } from 'typeorm';
import { UserStatDaily } from 'src/modules/statistics/entities/user-stat-daily.entity';
import { User } from 'src/modules/user/entities/user.entity';

@Injectable()
export class UserStatService {
  constructor(
    @InjectRepository(UserStatDaily) private userStatRepo: Repository<UserStatDaily>,
    @InjectRepository(User) private userRepo: Repository<User>
  ) {}

  // 计算周期用户汇总+环比增长率
  async getUserOverview(start: Date, end: Date) {
    // 当前周期聚合数据
    const currStat = await this.userStatRepo
      .createQueryBuilder('stat')
      .select('SUM(stat.visitNum)', 'totalVisit')
      .addSelect('SUM(stat.viewNum)', 'totalView')
      .addSelect('SUM(stat.newUser)', 'totalNewUser')
      .addSelect('SUM(stat.orderPayUser)', 'orderPayUser')
      .addSelect('SUM(stat.transPayUser)', 'transPayUser')
      .where('stat.statDate BETWEEN :start AND :end', { start, end })
      .getRawOne();
    // 计算同期上一周期,用于环比计算
    const dayDiff = Math.ceil((end.getTime() - start.getTime()) / (1000 * 3600 * 24));
    const lastStart = new Date(start.getTime() - dayDiff * 24 * 3600 * 1000);
    const lastEnd = new Date(end.getTime() - dayDiff * 24 * 3600 * 1000);
    const lastStat = await this.userStatRepo
      .createQueryBuilder('stat')
      .select('SUM(stat.newUser)', 'lastNewUser')
      .addSelect('SUM(stat.orderPayUser)', 'lastOrderUser')
      .addSelect('SUM(stat.transPayUser)', 'lastTransUser')
      .where('stat.statDate BETWEEN :lStart AND :lEnd', { lStart: lastStart, lEnd: lastEnd })
      .getRawOne();
    
    // 环比增长率计算,避免除0报错
    const calcRate = (curr: number, last: number) => {
      if(last === 0) return curr > 0 ? '-100.00' : '0.00';
      return (((curr - last) / last) * 100).toFixed(2);
    }
    const totalUser = await this.userRepo.count();
    return {
      totalUser,
      visitNum: Number(currStat.totalVisit || 0),
      viewNum: Number(currStat.totalView || 0),
      newUser: Number(currStat.totalNewUser || 0),
      orderPayUser: Number(currStat.orderPayUser || 0),
      transPayUser: Number(currStat.transPayUser || 0),
      rateNewUser: calcRate(Number(currStat.totalNewUser || 0), Number(lastStat.lastNewUser || 0)),
      rateOrderUser: calcRate(Number(currStat.orderPayUser || 0), Number(lastStat.lastOrderUser || 0)),
      rateTransUser: calcRate(Number(currStat.transPayUser || 0), Number(lastStat.lastTransUser || 0))
    }
  }

  // 用户地域TOP数据统计
  async getUserAreaTop(start: Date, end: Date) {
    return this.userRepo
      .createQueryBuilder('user')
      .select('IFNULL(user.province, "未知")', 'areaName')
      .addSelect('COUNT(user.id)', 'totalUser')
      .addSelect("SUM(CASE WHEN user.createTime BETWEEN :start AND :end THEN 1 ELSE 0 END)", 'newUser')
      .groupBy('areaName')
      .orderBy('totalUser', 'DESC')
      .setParameters({ start, end })
      .getRawMany();
  }
}

前端可视化分为三块:顶部指标卡片展示全部汇总数据并标注环比增减;中间多指标折线图展示每日访客、新增用户、成交用户波动;下方左侧地域分布表格、右侧环形饼图展示用户性别占比。饼图自动合并占比过小的类目,优化可视化展示效果,适配海外用户性别数据大量未知的业务场景。

ECharts 环形饼图渲染代码

typescript 复制代码
const renderGenderPie = (userList) => {
  const genderMap = { man: 0, woman: 0, unknown: 0 };
  userList.forEach(item => {
    if(item.gender === 1) genderMap.man += 1;
    else if(item.gender === 2) genderMap.woman += 1;
    else genderMap.unknown += 1;
  })
  pieChart.setOption({
    tooltip: { trigger: 'item' },
    series: [{
      type: 'pie',
      radius: ['40%', '70%'],
      avoidLabelOverlap: false,
      label: { show: true, position: 'outside' },
      data: [
        { name: '男', value: genderMap.man },
        { name: '女', value: genderMap.woman },
        { name: '未知', value: genderMap.unknown }
      ]
    }]
  })
}

这套用户统计模块上线后,运营可以精准定位高转化用户地域、分析新老用户成交占比,针对性开展定向营销活动,大幅提升反向海淘跨境独立站的用户复购。市面上绝大多数代购源码仅提供简单用户列表,缺失完整行为统计与可视化分析能力,这套全栈开发方案可以直接嵌入淘宝 1688 代购系统、跨境转运平台二次开发,完整支撑精细化用户运营的数据需求。