如何通过修复结帐页面上的错误来提高销售额和客户忠诚度

已发表: 2022-05-25

在现代、快速发展的数字世界中,客户依赖企业提供的在线机会,并期望一切都完美无缺。 一旦在客户旅程中遇到任何错误,这些客户会记住糟糕的服务,并更愿意寻找替代产品/服务。 这就是为什么防止任何困难并不断监控业务绩效如此重要的原因。

在这种情况下,我们描述了 OWOX BI 团队为一家消费电子和家电零售商提供的解决方案,该零售商在解决结账页面错误以提高销售额和客户忠诚度方面遇到了挑战。

目录

  • 挑战
  • 目标
  • 解决方案
    • 步骤 1. 收集有关错误的数据
    • 步骤 2. 处理数据
    • Step 3. 使用获取的数据
  • 结果

挑战

每天约有 700,000 人访问该零售商的网站,阅读产品评论或四处浏览以找到他们想要购买的商品。 但是,用户有时可能会在结帐页面遇到网站错误,导致他们无法在线完成订单,从而降低了公司的收入。

目标

分析师和测试人员仔细研究了客户的投诉,以定义典型的错误场景。 专家设法重现的错误已得到修复。 其余的关键错误需要设置监控。 此前,该公司不使用收集此类数据,仍然无法评估错误的确切数量以及它们如何影响转化率。 公司还需要知道每个 bug 是如何与特定用户相关联的,以帮助用户下订单。

分析师选择在网站设置关键漏洞监控,尽最大努力帮助客户在结账页面成功下单。 这将增加销售额并改善客户网站体验。 具有挑战性的因素是需要实时监控,以免失去任何当前试图在网站上订购商品的客户。

解决方案

为实现这一目标,制定了以下计划:

  1. 将附加代码放在网站上以收集有关错误的数据并将其发送到 Google BigQuery。
  2. 对获取的数据进行处理,并根据公司需要将其导出到具有结构的表中。
  3. 组织将有关用户和错误的数据发送到呼叫中心,呼叫中心将联系客户以帮助他们下订单。

以下是公司数据流的样子:

步骤 1. 收集有关错误的数据

该公司使用谷歌标签管理器来跟踪用户的在线行为。 但是,并非网站上的所有逻辑错误都可以通过标准的 Google Tag Manager 方式进行跟踪。 这就是为什么自定义脚本是专门编写的,并通过谷歌标签管理器在必要的网站页面上实现。 这些脚本将详细的错误数据添加到DataLayer

接下来,在 Google Tag Manager 标签的帮助下,错误数据通过 OWOX BI Pipeline 进入 Google BigQuery。 这允许从 Google BigQuery 中的网站近乎实时地获取原始未采样数据。

分析师使用 API 将有关用户的数据从 CRM 发送到 Google BigQuery,从而在云数据仓库中获取他们需要的所有数据:

  • 错误时间。
  • 错误类型。
  • 用户身份。
  • 用户电子邮件地址。
  • 用户城市。
  • 购物车中的当前产品状态。

步骤 2. 处理数据

使用OWOX BI Pipeline,获得了具有广泛参数的数据表。 OWOX BI 分析师创建了一个 SQL 查询来从表中提取数据,并以明确的结构返回它:一组行,每行代表一个错误。

下面是 SQL 查询示例:

    Select date, hour,minute, email, description, City, productIds, productnames, productprice, cartquantity, cartamount, From ( SELECT usererrors.date as date, usererrors.hour as hour, usererrors.minute as minute, usererrors.userEmail as email, usererrors.action as action, usererrors.error as error, case when action = 'disabled' and error = 'buttonCreateOrder' then 'Unable to checkout in cart' when action = 'notAdded' and error = 'productToCart' then 'Unable to add product to cart' when action = 'open' and error = 'emptyCart' then 'Product can not be viewed in cart' when action = 'open' and error = 'HoldingPageCheckout' then 'Maintenance work in progress (after checkout)' when action = 'absent' and error = ƋdiscountCart' then Ƌ% discount unavailable online (in cart)' when action = 'absent' and error = ƋdiscountCheckout' then Ƌ% discount unavailable online (at the checkout page)' when action = 'disabled' and error = 'buttonSubmit' then 'Button "Place Order" not working at the checkout page' else 'Other' end as description, Dimensions.city as City, Dimensions.productids as productIds, Dimensions.productnames as productnames, customMetrics.productprice as productprice, customMetrics.cartquantity as cartquantity, customMetrics.cartamount as cartamount, FROM (SELECT date, hour,minute, hitId, userEmail, eventInfo.eventAction as action, eventInfo.eventLabel as error, hour(CURRENT_TIMESTAMP())+2-hour as currenthour from TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') ) where eventInfo.eventCategory = 'Errors' and userEmail is not null group by 1,2,3,4,5,6,7,8) as usererrors left join (SELECT hitId, MAX(IF(customDimensions.index=4, customDimensions.value, NULL)) WITHIN hitId AS city, MAX(IF(customDimensions.index=21, customDimensions.value, NULL)) WITHIN hitId AS productids, Max(IF(customDimensions.index=22, customDimensions.value, NULL)) WITHIN hitId AS productnames from TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') )) as Dimensions ON Dimensions.hitId=usererrors.hitId left join (SELECT hitId, MAX(IF(customMetrics.index=1, customMetrics.value, NULL)) WITHIN hitId AS productprice, MAX(IF(customMetrics.index=4, customMetrics.value, NULL)) WITHIN hitId AS cartamount, Max(IF(customMetrics.index=5, customMetrics.value, NULL)) WITHIN hitId AS cartquantity FROM TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') )) as customMetrics ON customMetrics.hitId=usererrors.hitId where usererrors.currenthour=0 ) ORDER BY date asc, hour asc, minute asc, email asc
Select date, hour,minute, email, description, City, productIds, productnames, productprice, cartquantity, cartamount, From ( SELECT usererrors.date as date, usererrors.hour as hour, usererrors.minute as minute, usererrors.userEmail as email, usererrors.action as action, usererrors.error as error, case when action = 'disabled' and error = 'buttonCreateOrder' then 'Unable to checkout in cart' when action = 'notAdded' and error = 'productToCart' then 'Unable to add product to cart' when action = 'open' and error = 'emptyCart' then 'Product can not be viewed in cart' when action = 'open' and error = 'HoldingPageCheckout' then 'Maintenance work in progress (after checkout)' when action = 'absent' and error = ƋdiscountCart' then Ƌ% discount unavailable online (in cart)' when action = 'absent' and error = ƋdiscountCheckout' then Ƌ% discount unavailable online (at the checkout page)' when action = 'disabled' and error = 'buttonSubmit' then 'Button "Place Order" not working at the checkout page' else 'Other' end as description, Dimensions.city as City, Dimensions.productids as productIds, Dimensions.productnames as productnames, customMetrics.productprice as productprice, customMetrics.cartquantity as cartquantity, customMetrics.cartamount as cartamount, FROM (SELECT date, hour,minute, hitId, userEmail, eventInfo.eventAction as action, eventInfo.eventLabel as error, hour(CURRENT_TIMESTAMP())+2-hour as currenthour from TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') ) where eventInfo.eventCategory = 'Errors' and userEmail is not null group by 1,2,3,4,5,6,7,8) as usererrors left join (SELECT hitId, MAX(IF(customDimensions.index=4, customDimensions.value, NULL)) WITHIN hitId AS city, MAX(IF(customDimensions.index=21, customDimensions.value, NULL)) WITHIN hitId AS productids, Max(IF(customDimensions.index=22, customDimensions.value, NULL)) WITHIN hitId AS productnames from TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') )) as Dimensions ON Dimensions.hitId=usererrors.hitId left join (SELECT hitId, MAX(IF(customMetrics.index=1, customMetrics.value, NULL)) WITHIN hitId AS productprice, MAX(IF(customMetrics.index=4, customMetrics.value, NULL)) WITHIN hitId AS cartamount, Max(IF(customMetrics.index=5, customMetrics.value, NULL)) WITHIN hitId AS cartquantity FROM TABLE_DATE_RANGE([mvideo-ru:Streaming.streaming_], DATE_ADD(CURRENT_TIMESTAMP(), 0 ,'DAY'), DATE_ADD(CURRENT_TIMESTAMP(), 0 , 'DAY') )) as customMetrics ON customMetrics.hitId=usererrors.hitId where usererrors.currenthour=0 ) ORDER BY date asc, hour asc, minute asc, email asc

作为查询的结果,分析人员获得了一个包含以下信息的表:

  • 日期;
  • 小时;
  • 分钟;
  • 用户电子邮件地址;
  • 错误描述;
  • 用户城市;
  • 购物车中产品的 ID;
  • 购物车中的产品名称;
  • 购物车中产品的价格;
  • 购物车中的产品总数;
  • 购物车中产品的总价。

然后,使用 OWOX BI BigQuery Reports 插件设置数据导入到 Google 表格,该插件每小时自动更新表中的信息。 这意味着报告始终包含有关前一小时错误的最新数据。

您可以在下面找到此类报告的示例:

Step 3. 使用获取的数据

负责用户每小时(上午 9 点到下午 6 点,根据工作时间)自动收到错误报告。 接下来,他们会将其发送给公司的开发人员,以防有关键问题需要解决,并发送给客户成功经理,他们会打电话给用户并帮助他们通过电话完成订单。

结果

  • 创建结构化报告是为了监控阻止用户购买的网站错误。
  • 该公司的开发人员在网站上添加了一个反馈表。 每次未登录的用户看到错误时,它都会自动出现,从而允许他们报告问题并留下他们的联系方式。 这有助于公司对任何错误或错误做出快速反应,并扩大客户群,包括未登录用户的联系人。
  • 该公司的呼叫中心可以在将产品添加到购物车和结账时快速获取有关面临问题的用户的数据。 呼叫中心操作员了解购物车内的物品并帮助完成购买。
  • 由于网站错误而接到电话的用户中,约有 3% 的用户成功完成了电话下单。 如果忽略错误,这会给公司额外损失 1,600 美元。