衡量表单中的浏览器自动填充功能

Maud Nalpas
Maud Nalpas

发布时间:2024 年 11 月 20 日

电子商务的成败取决于顺畅的结账流程。表单对于转化至关重要。为了优化用户体验,了解用户如何与您的表单互动至关重要。自动填充功能在此过程中发挥着重要作用。

Chrome 中的自动填充功能演示。
Chrome 中的自动填充功能

顺畅的自动填充体验可以提高转化次数、加快表单提交速度、降低表单放弃率,并提升用户满意度。

但您是否了解自己网站上的自动填充功能使用情况和使用障碍?

本指南介绍了如何收集和分析有关用户如何在表单中使用自动填充功能的数据。

您可以通过以下方式使用这些自动填充数据分析:

  • 使测试方法与真实用户的工作流程保持一致。如果自动填充功能使用情况分析信号表明您的用户非常依赖自动填充功能,那么您就知道必须将自动填充测试纳入工作流中。
  • 找出回归问题。比较影响表单用户体验的各个部署中各个字段的自动填充使用信号。差异较大可能表示自动填充行为出现了回归。
  • 确保支持自动填充的实现按预期运行。检测用户似乎手动填充您希望他们使用自动填充功能的字段的趋势。

演示和代码

试用我们的演示版,并研究 GitHub 上的代码

自动填充观察器演示。
使用演示代码以编程方式观察用户对每个表单字段的操作(留空、手动填充、使用自动填充功能填充,或使用自动填充功能填充,然后修改字段)。 试试看

可以尝试的操作:

  • 自动填充所有字段。
  • 自动填充字段,然后手动将其清空。
  • 自动填充字段,然后手动进行修改。
  • 完全手动填写字段。
  • 将某个字段留空。

浏览器支持

此演示适用于最新的设备和浏览器版本。它依赖于检测 :autofill CSS 伪类,该伪类在各浏览器中都得到了良好支持。

第 1 步:收集自动填充数据

定义自动填充状态

首先,定义您感兴趣的可能的自动填充字段状态:

  • EMPTY:用户将该字段留空。
  • AUTOFILLED:用户仅使用自动填充功能填充字段。
  • AUTOFILLED_THEN_MODIFIED:用户先使用自动填充功能填充字段,然后手动修改自动填充的值。例如,用户自动填充了地址和详细联系信息,但手动输入了其他电话号码。
  • ONLY_MANUAL:用户完全手动填写该字段。
// Possible values for autofill statuses
const EMPTY = 'empty';
const AUTOFILLED = 'autofilled';
const AUTOFILLED_THEN_MODIFIED = 'autofilled-then-modified';
const ONLY_MANUAL = 'only-manual';

实现实用函数

现在,我们来实现此代码的核心功能:检查字段是否刚刚自动填充。在后台,此操作使用了两个函数:

  • getAllAutofilledFields 会查看给定表单中的所有 <input><select> 元素,并检查是否存在 :autofill CSS 伪类。它会输出已自动填充的元素列表。
  • 然后,checkIsAutofilled 会检查特定元素是否属于此列表。
// Get all elements that are autofilled, using the :autofill pseudo-class
function getAllAutofilledFields(formElement) {
  return formElement.querySelectorAll(':autofill');
}

// Check if the passed element is in the list of autofilled fields
function checkIsAutofilled(allAutofilledFields, fieldElement) {
  return Array.from(allAutofilledFields).includes(fieldElement);
}

// Usage
const allAutofilledFields = getAllAutofilledFields(formElement);
const isAutofilled = checkIsAutofilled(allAutofilledFields, fieldElement);

此外,您还需要一个实用函数来检查字段是否为空。

// Check if the value of the element is empty
function checkIsEmpty(fieldElement) {
  const value = fieldElement.value.trim();
  // value is a string, even for a type = number field
  const isEmpty = value === '';
  return isEmpty;
}

初始化自动填充状态

创建一个全局对象 autofillStatuses,用于存储每个字段的自动填充状态。

从表单中收集所有字段 id,并将每个字段的状态初始化为 EMPTY

// Global variable storing autofill statuses for each field
const autofillStatuses = {};
// Example: {
//     "name": "autofilled",
//     "street-address": "autofilled-then-modified",
//     "country": "only-manual"
// }

// Initialize autofill status for all fields
function initializeAutofillStatuses(formElement) {
  const allFieldsAsArray = getAllFieldsAsArray(formElement);
  allFieldsAsArray.forEach((fieldElement) => {
    autofillStatuses[fieldElement.id] = EMPTY;
  });
}

initializeAutofillStatuses(document.getElementById('form'));

如需收集您感兴趣的所有字段元素,initializeAutofillStatuses 会使用实用函数:

// Collect all field elements for a given form
function getAllFieldsAsArray(formElement) {
  return Array.from(formElement.querySelectorAll('input, select'));
}

观察更改

现在,一切都已准备就绪,可以观察自动填充行为了。

为每个表单元素附加一个更改事件监听器。发生更改时,它会使用 checkIsAutofilled 实用程序函数检查元素当前是否正在自动填充。然后,系统会根据当前状态和上一个状态,在 autofillStatuses 对象中更新元素的自动填充状态。

例如,如果之前的状态为 AUTOFILLED,而该字段现在未自动填充(即不具有 :autofill 类),则表示该字段在自动填充后已手动更新。因此,状态会更新为 AUTOFILLED_THEN_MODIFIED

// Add event listener to all fields to update autofill status
function initializeChangeObserver(formElement) {
  const allFieldsAsArray = getAllFieldsAsArray(formElement);
  allFieldsAsArray.forEach((fieldElement) => {
    fieldElement.addEventListener('change', () => {
      updateAutofillStatus(formElement, fieldElement);
    });
  });
}

// Update autofill status
function updateAutofillStatus(formElement, fieldElement) {
  const isEmpty = checkIsEmpty(fieldElement);
  const allAutofilledFields = getAllAutofilledFields(formElement);
  const isAutofilled = checkIsAutofilled(allAutofilledFields, fieldElement);
  const previousAutofillStatus = autofillStatuses[fieldElement.id];
  if (isEmpty) {
    autofillStatuses[fieldElement.id] = EMPTY;
    // NOTE: if (previousAutofillStatus === AUTOFILLED), the field has just been emptied manually. Autofill can't empty fields.
  } else {
    if (isAutofilled) {
      autofillStatuses[fieldElement.id] = AUTOFILLED;
    } else {
      if (
        previousAutofillStatus === ONLY_MANUAL ||
        previousAutofillStatus === EMPTY
      ) {
        // NOTE: ONLY_MANUAL is only used for fields where autofilled was *never* used. A field where autofilled was used will be AUTOFILLED_THEN_MODIFIED, even if the user has completely retyped the whole value
        autofillStatuses[fieldElement.id] = ONLY_MANUAL;
      } else if (
        previousAutofillStatus === AUTOFILLED ||
        previousAutofillStatus === AUTOFILLED_THEN_MODIFIED
      ) {
        autofillStatuses[fieldElement.id] = AUTOFILLED_THEN_MODIFIED;
      }
    }
  }
}

initializeChangeObserver(document.getElementById('form'));

将结果发送到您的服务器

表单提交后,将 autofillStatuses 对象发送到服务器。例如,对于地址表单,您会在服务器上收到以下数据:

{
    "name": "only-manual",
    "street-address": "only-manual",
    "postal-code": "autofilled-then-modified",
    "city": "autofilled",
    "country": "autofilled"
}
自动填充观察器演示:显示各种自动填充状态的区域。
显示各种字段的自动填充状态的区域。仅用于演示目的。

第 2 步:分析结果

汇总您从多位用户收到的 autofillStatuses 对象,并分析数据中的趋势。

首先,查看有关自动填充功能总体使用情况的数据分析:有多少用户使用浏览器自动填充功能填充了至少一个字段?

然后,您可以深入了解各个字段。例如,您发现有相当一部分用户未自动填充应该支持自动填充的某些字段。现在,您可以调查可能的原因。

  • <label> 字段不明确?是否有任何提示或占位符可能具有误导性?
  • 您是否为 autocomplete 值使用了正确的语法?一个常见问题是 <input autocomplete="first-name">,浏览器不会填充该值,因为正确的值为 "given-name"

总结

通过了解和利用自动填充行为,您可以提升网站上的用户体验。实现本指南中介绍的技术,深入了解用户如何与您的表单互动,并找出有待改进的地方。

请注意,自动填充功能是一款可简化用户体验的强大工具。针对自动填充功能优化表单有助于为访问者打造更人性化的体验。

查看我们的所有自动填充资源