关于 customer-accounts
customer-accounts 是面向电商店铺开发者和运营者的客户账户配置技能,涵盖 Shopify、WooCommerce、BigCommerce 及自定义店面。它指导启用注册登录、账户页面和购后账户创建,并强调保留访客结账选项。
主要功能
- 01配置账户注册与登录
- 02定制订单和账户页面
- 03管理地址簿与愿望清单
- 04设置购后账户创建
- 05说明自定义认证方案
适用场景
- 01为新店面启用客户账户
- 02添加订单历史和物流跟踪
- 03帮助回头客保存多个地址
- 04将访客买家转为注册客户
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill customer-accounts安装后在 Claude Code 中输入/customer-accounts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/address-book-crud-and-schema/criteria.jsontask.mdevals/password-reset-and-session-security/criteria.jsontask.mdevals/registration-and-login-security/criteria.jsontask.md详细介绍
客户账户
概述
客户账户让购物者可以保存地址,以便更快结账;查看订单历史记录、跟踪配送情况并管理个人资料。所有主流电商平台都内置了这项功能——Shopify、WooCommerce 和 BigCommerce 均提供账户注册、登录、地址簿和订单历史记录,无需进行任何自定义开发。主要需要决定的是:账户设为可选还是必需,以及是否要为平台默认账户页面添加更多功能。
何时使用此技能
- 在新的在线商店中启用客户注册和登录
- 使用订单历史记录和配送跟踪功能自定义账户控制面板
- 添加地址簿,加快回头客的结账速度
- 将访客结账用户转化为注册客户
- 添加愿望清单或稍后保存功能
核心说明
步骤 1:确定平台并启用客户账户
| 平台 | 账户系统 | 推荐扩展 |
|---|---|---|
| Shopify | 原生客户账户(经典版或新版) | Customer Accounts Concierge 或 Flits,用于增强账户页面 |
| WooCommerce | 我的账户页面(内置,可自定义) | YITH WooCommerce Wishlist;WooCommerce Memberships,用于限制内容访问 |
| BigCommerce | 客户账户门户(内置) | Customer Groups,用于分级访问;LoyaltyLion,用于集成忠诚度计划 |
| 自定义 / 无头架构 | 使用 JWT 会话和 bcrypt 密码哈希构建 | 需要完全掌控身份验证和账户用户体验时使用 |
步骤 2:平台专属设置
Shopify
Shopify 提供两种账户体验:经典账户和较新的新客户账户(所有套餐均可使用)。
启用账户并选择体验方式:
- 前往设置 → 客户账户
- 选择以下一种:
- 经典账户:传统的电子邮件 + 密码登录,可通过 Liquid 主题自定义账户页面
- 新客户账户:通过电子邮件链接免密码登录;由 Shopify 托管并控制的页面(设置更快,但自定义空间较小)
- 将账户设为可选(推荐)或必需
设置经典账户:
- 在“设置 → 客户账户”中启用经典账户
- 账户页面位于
/account— 页面布局由主题控制 - 在在线商店 → 主题 → 自定义 → 客户账户页面中自定义账户页面
- 主要页面:登录、注册、账户概览、订单详情、地址
将账户设为可选(强烈推荐):
- 始终允许访客结账 — 绝不要强制用户先注册再购买
- 结账后显示“创建账户以保存您的详细信息”提示
- 客户使用曾用于过往订单的同一邮箱注册时,Shopify 会自动处理“将访客转为账户”的流程
扩展账户页面:
如需增强账户功能(愿望清单、忠诚度积分、社交登录、带跟踪信息的近期订单):
- 从应用商店安装 Flits — 全面的账户页面自定义功能
- 或安装 Customer Accounts Concierge — 添加愿望清单、最近浏览和重新订购功能
WooCommerce
WooCommerce 内置了 My Account 页面,包含订单历史记录、地址和个人资料管理功能。
设置 My Account:
- 前往 WooCommerce → Settings → Accounts & Privacy
- 配置:
- Guest checkout:勾选“Allow customers to place orders without an account”
- Account creation:可选择在结账时自动创建账户
- Account erasure:启用“Allow customers to request account deletion”
- My Account 页面会自动创建在
/my-account/
自定义 My Account 标签页:
默认标签页包括:仪表盘、订单、下载、地址、账户详情、退出。添加或移除标签页:
- 在子主题的 functions.php 中使用
woocommerce_account_menu_items过滤器添加自定义标签页,或安装 YITH WooCommerce Customize My Account Page 等插件 - 修改过滤器中的数组以调整标签页顺序
地址簿:
- 前往 WooCommerce → Settings → Accounts → Allow customers to store multiple addresses
- 客户可以在 My Account → Addresses 中添加或编辑多个地址
- WooCommerce 会自动在结账时预填默认地址
愿望清单:
- 安装 YITH WooCommerce Wishlist(免费版/高级版)
- 在商品页面添加“Add to Wishlist”按钮,并在 My Account 中添加愿望清单页面
购买后将访客转为注册用户:
启用账户功能但设为可选时,WooCommerce 会自动在订单确认邮件中显示“Create account”提示。
BigCommerce
BigCommerce 内置了客户门户。
启用并配置:
- 前往 Store Setup → Store Settings → Display → Customer Account Access
- 设为“Optional”,以允许访客结账
- 账户页面由主题管理,可在 Stencil 主题编辑器中自定义
客户群组:
使用客户群组实现分级访问、B2B 定价或仅限会员访问的分类:
- 前往 Customers → Customer Groups → Add Group
- 设置群组专属定价、分类可见性或配送规则
- 手动为客户分配群组,或根据购买历史自动分配
地址簿:
- 客户账户门户中内置了地址簿
- 客户可以保存多个地址,并在结账时选择地址
Custom / Headless
对于无头店面,构建一套完整且安全的身份验证账户系统:
// lib/auth.ts
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { z } from 'zod';
const registerSchema = z.object({
email: z.string().email(),
password: z.string().min(8).max(128),
firstName: z.string().min(1).max(100),
lastName: z.string().min(1).max(100),
acceptsMarketing: z.boolean().default(false),
});
// POST /api/customers/register
export async function register(req: Request, res: Response) {
const input = registerSchema.parse(req.body);
const existing = await db.customers.findByEmail(input.email.toLowerCase());
if (existing) return res.status(409).json({ error: 'An account with this email already exists' });
const passwordHash = await bcrypt.hash(input.password, 12); // Cost factor 12 minimum
const customer = await db.customers.create({ ...input, email: input.email.toLowerCase(), passwordHash });
await sendVerificationEmail(customer);
const token = jwt.sign({ sub: customer.id, type: 'customer' }, process.env.JWT_SECRET!, { expiresIn: '7d' });
res.status(201).json({ customer: omit(customer, ['passwordHash']), token });
}
// POST /api/customers/login
export async function login(req: Request, res: Response) {
const { email, password } = req.body;
const customer = await db.customers.findByEmail(email.toLowerCase());
// Use the same error for both "not found" and "wrong password" to prevent email enumeration
if (!customer || !customer.passwordHash) return res.status(401).json({ error: 'Invalid email or password' });
if (customer.status === 'disabled') return res.status(403).json({ error: 'This account has been disabled' });
const valid = await bcrypt.compare(password, customer.passwordHash);
if (!valid) return res.status(401).json({ error: 'Invalid email or password' });
const token = jwt.sign({ sub: customer.id, type: 'customer' }, process.env.JWT_SECRET!, { expiresIn: '7d' });
res.json({ customer: omit(customer, ['passwordHash']), token });
}
// Address book CRUD — GET /api/customers/me/addresses
export async function listAddresses(req: AuthRequest, res: Response) {
const addresses = await db.customerAddresses.findMany({ where: { customerId: req.customerId } });
res.json({ addresses });
}
// POST /api/customers/me/addresses
export async function addAddress(req: AuthRequest, res: Response) {
const existing = await db.customerAddresses.findMany({ where: { customerId: req.customerId } });
const input = { ...addressSchema.parse(req.body), customerId: req.customerId };
if (input.isDefault || existing.length === 0) {
await db.customerAddresses.updateMany({ where: { customerId: req.customerId }, data: { isDefault: false } });
input.isDefault = true;
}
const address = await db.customerAddresses.create({ data: input });
res.status(201).json({ address });
}
// GET /api/customers/me/orders — paginated order history with tracking
export async function listOrders(req: AuthRequest, res: Response) {
const page = parseInt(req.query.page as string) || 1;
const limit = Math.min(parseInt(req.query.limit as string) || 10, 50);
const [orders, total] = await Promise.all([
db.orders.findMany({ where: { customerId: req.customerId }, skip: (page - 1) * limit, take: limit, orderBy: { createdAt: 'desc' }, include: { lineItems: true, shipments: true } }),
db.orders.count({ where: { customerId: req.customerId } }),
]);
res.json({ orders, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } });
}
第 3 步:配置结账后的账户创建
成功完成首次购买后立即邀请客户创建账户,是邀请其创建账户的最佳时机,效果优于购买前邀请。
Shopify: 启用客户账户但设为可选时,订单确认页面会自动包含“Create account”按钮。可在 Online Store → Themes → Customize → Order status page 中自定义提示信息。
WooCommerce: 在 WooCommerce → Settings → Accounts 中自定义“Thank you”页面提示信息,或使用 Checkout Field Editor 插件添加结账后创建账户的提示。
提示内容:“保存您的详细信息,下次结账更快捷”比“创建账户”更有吸引力——应突出益处,而不是具体操作。
最佳实践
- 始终将账户设为可选——切勿在购买前强制用户注册;购买后的转化率远高于购买前
- 尽可能提供社交登录(Google、Facebook)——显著降低移动用户的操作门槛;Shopify 可使用 Single Sign-On (SSO) 等应用,WooCommerce 可使用 WooCommerce Social Login
- 使用已保存的地址自动填充结账信息——账户的主要价值在于加快结账;确保自动预填默认地址
- 结账 24 小时后向访客买家发送再互动邮件,邀请他们创建账户——发送时机很重要
- 启用 GDPR/CCPA 账户删除功能——各平台都支持此功能;确保用户容易找到“删除我的账户”选项;有关数据擦除流程,请参阅平台文档
常见问题
| 问题 | 解决方案 |
|---|---|
| 客户创建账户后看不到之前的订单 | 在 Shopify 中,访客结账产生的历史订单会在客户使用相同邮箱注册后关联到该账户;请确认已在 Settings → Customer accounts 中启用账户关联 |
| 国际客户的地址验证失败 | 不要将州/省设为必填项——许多国家没有这类行政区划;WooCommerce 会根据国家动态显示字段 |
| JWT 令牌的有效期过长 | 使用有效期为 15 分钟的访问令牌,并搭配刷新令牌以提高安全性;或者使用服务端会话,并设置安全的 HttpOnly Cookie |
| 无法合并重复的客户记录 | Shopify 和 WooCommerce 都支持在管理后台合并客户;对于自定义构建,请开发一个合并工具来整合订单和地址 |
相关技能
- @customer-segmentation
- @customer-lifetime-value
- @personalization-engine