Flutter SDK - 设置用户 ID 和哈希 User Details

设置用户 ID 和哈希 User Details

向 Singular 发送内部用户 ID,以实现跨设备跟踪和用户级数据报告。

注:如果使用Singular 的跨设备解决方案,则必须在所有平台上收集用户 ID。

用户ID要求

隐私和最佳实践

在实施用户 ID 跟踪时,请遵循以下准则,以确保隐私合规和正确的跨设备测量。

  • 无 PII:用户 ID 不应暴露个人身份信息 (PII),如电子邮件地址、用户名或电话号码。使用与第一方数据独一无二的哈希值。
  • 跨平台一致性:用户 ID 值必须是您在所有平台(网络/移动/PC/控制台/离线)上获取的相同内部标识符,以便进行准确的跨设备测量。
  • 第一方数据:Singular会在用户级导出、ETL和内部商业智能回传(如有配置)中包含用户ID。用户 ID 是第一方数据,不会与第三方共享。
  • 持久性:用户 ID 会一直存在,直到使用unsetCustomUserId() 明确取消设置或卸载应用程序为止。关闭或重启应用程序不会清除用户 ID。

实施概述

何时设置用户 ID

使用Singular.setCustomUserId() 设置用户标识符,使用Singular.unsetCustomUserId() 注销时清除用户标识符。

最佳实践:如果多个用户共用一台设备,请执行注销流程,登录时调用setCustomUserId() ,注销时调用unsetCustomUserId()

如果已经知道应用程序打开时的用户 ID,请在初始化 Singular SDK 之前使用customUserId 属性进行配置。这将确保 Singular 从第一次会话中接收到用户 ID。不过,在用户注册或登录之前,用户 ID 通常是不可用的,在这种情况下,请在注册或身份验证流程完成后调用setCustomUserId()


SDK 方法

设置自定义用户 ID

向 Singular 发送内部用户 ID,用于跨设备跟踪和用户级报告。

Dart
import 'package:singular_flutter_sdk/singular.dart';

// Set the user ID after login or registration
Singular.setCustomUserId('user_123456');

方法签名

static void setCustomUserId(String customUserId)

示例:登录后设置用户 ID

在用户成功完成身份验证后立即调用setCustomUserId() ,以确保所有后续事件都与用户 ID 相关联。

Dart
import 'package:singular_flutter_sdk/singular.dart';

Future<void> handleUserLogin(String email, String password) async {
  try {
    // Your authentication logic
    final response = await authenticateUser(email, password);

    if (response.success) {
      // Set the user ID in Singular after successful login
      Singular.setCustomUserId(response.userId);

      print('User ID set: ${response.userId}');

      // Navigate to home screen
      navigateToHome();
    }
  } catch (error) {
    print('Login failed: $error');
  }
}

取消设置自定义用户 ID

在用户注销时清除用户 ID,以确保多用户设备的准确会话跟踪。

Dart
import 'package:singular_flutter_sdk/singular.dart';

// Unset the user ID on logout
Singular.unsetCustomUserId();

方法签名

static void unsetCustomUserId()

示例:注销时取消设置用户 ID

在注销流程中调用unsetCustomUserId() ,清除用户 ID,防止后续事件的错误归因。

Dart
import 'package:singular_flutter_sdk/singular.dart';

Future<void> handleUserLogout() async {
  try {
    // Clear app data and user session
    await clearUserSession();

    // Unset the user ID in Singular
    Singular.unsetCustomUserId();

    print('User ID cleared');

    // Navigate to login screen
    navigateToLogin();
  } catch (error) {
    print('Logout failed: $error');
  }
}

在初始化过程中设置用户 ID

如果用户 ID 在应用程序启动时可用(例如,用户已登录),可在 SDK 初始化期间使用customUserId 属性进行配置。这样可确保首次会话包含用户 ID。

Dart
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    initializeSingular();
  }

  Future<void> initializeSingular() async {
    // Check if user is already logged in
    final prefs = await SharedPreferences.getInstance();
    final userId = prefs.getString('user_id');

    // Create configuration
    SingularConfig config = SingularConfig(
      'YOUR_SDK_KEY',
      'YOUR_SDK_SECRET'
    );

    // If user ID exists, set it during initialization
    if (userId != null) {
      config.customUserId = userId;
    }

    // Initialize SDK
    Singular.start(config);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

配置属性

String? customUserId

建议:对于具有持续登录会话的应用程序,请在初始化过程中使用customUserId配置属性。对于用户必须每次登录的应用程序,请在验证后调用setCustomUserId()


哈希 User Details(电子邮件和电话号码)

上面的用户 ID 是您自己的不透明标识符。如果您还想向 Singular 发送用户的电子邮件地址或电话号码,请使用单独的 SingularUserDetails API。SDK 会在设备上对这些值进行规范化并使用 SHA-256 哈希,因此原始电子邮件地址和电话号码绝不会被传输。

适用版本: Flutter SDK 1.9.1 及更高版本,其中捆绑了原生 iOS 12.14.2 和 Android 12.16.1。

选择哈希模式

提供 User Details 有两种方式。请为每个用户选择一种并保持一致。

  • 由 SDK 哈希(推荐): 设置明文的电子邮件或电话号码。SDK 会规范化该值、进行哈希,并生成 Singular 可用于匹配的所有变体。
  • 预先哈希: 设置您已自行规范化并使用 SHA-256 哈希的值。SDK 会原样存储,不做任何进一步处理。当您的应用在调用时不允许持有明文 User Details 时,请使用此方式。

重要: 如果您同时设置了明文值及其对应的预哈希变体,则以预哈希值为准。

SingularUserDetails 属性

SingularUserDetails 提供六个可为空的 String 属性。请仅赋值您拥有的属性,其余保持未设置。

属性 详细信息
email

模式: 由 SDK 哈希

明文电子邮件地址。SDK 会在哈希前去除空白并转换为小写。对于 gmail.comgooglemail.com 地址,它还会生成第二个变体,其中移除了本地部分的 +tag 后缀和所有点号。

示例: user@example.com

phoneNumber

模式: 由 SDK 哈希

明文电话号码。SDK 会生成两个变体:保留前导 + 并去除其他所有非数字字符的 E.164 格式,以及同时去除 + 的纯数字格式。请包含国家代码,以便 E.164 变体可用。

示例: +15551234567

emailSTD

模式: 预先哈希

去除空白并转换为小写后的电子邮件地址的 SHA-256 哈希值。

emailNoDots

模式: 预先哈希

去除空白、转换为小写,并移除 +tag 后缀和本地部分所有点号后的电子邮件地址的 SHA-256 哈希值。适用于 Gmail 类地址。

phoneE164

模式: 预先哈希

保留前导 + 的 E.164 格式电话号码的 SHA-256 哈希值。

phoneDigits

模式: 预先哈希

移除所有非数字字符(包括前导 +)后的电话号码的 SHA-256 哈希值。


在初始化时设置 User Details

在调用 Singular.start 之前,在 SingularConfig 上设置 User Details,这样它们会被附加到 SDK 发送的首个会话上。您可以直接赋值 userDetails 属性,也可以调用 withUserDetails,两者等效。

Dart
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
import 'package:singular_flutter_sdk/singular_user_details.dart';

SingularUserDetails userDetails = SingularUserDetails();
userDetails.email = 'user@example.com';
userDetails.phoneNumber = '+15551234567';

SingularConfig config = SingularConfig('SDK KEY', 'SDK SECRET');
config.withUserDetails(userDetails);

Singular.start(config);

方法签名:

void withUserDetails(SingularUserDetails userDetails)

注意: withUserDetails 返回 void,因此无法链接到 SingularConfig 构造函数上。请在单独的一行调用它,或直接赋值 config.userDetails


在初始化后设置 User Details

如果只有在登录或注册之后才能获得电子邮件地址或电话号码,请在那时调用 Singular.setUserDetails。此后,这些值会被附加到 SDK 发送的每个会话和事件上。

Dart
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_user_details.dart';

// 明文值,由 SDK 哈希
SingularUserDetails userDetails = SingularUserDetails();
userDetails.email = 'user@example.com';
userDetails.phoneNumber = '+15551234567';
Singular.setUserDetails(userDetails);

// 或提供您自己的 SHA-256 哈希值
SingularUserDetails hashed = SingularUserDetails();
hashed.emailSTD = 'b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514';
hashed.phoneE164 = '8a59780bb8cd2ba022bfa5ba2ea3b6e07af17a7d8b30c1f9b3390e36f69019e4';
Singular.setUserDetails(hashed);

方法签名:

static void setUserDetails(SingularUserDetails userDetails)

清除 User Details

已存储的 User Details 会在应用多次启动之间保留在设备上,并在卸载应用时被移除。请在用户登出时,或在用户撤回同意时调用 Singular.clearUserDetails 将其移除。

Dart
import 'package:singular_flutter_sdk/singular.dart';

// 在登出时移除已存储的 User Details
Singular.clearUserDetails();

方法签名:

static void clearUserDetails()

清除已存储详细信息的三种方式。 clearUserDetails 并不是唯一的方式。使用未设置任何属性的 SingularUserDetails 对象调用 setUserDetails 同样会清除它们;使用所有值都因无效而被拒绝的对象调用时也是如此——后一种情况会清除已存储的载荷,而不是保持不变。如果您希望保留已存储的详细信息,请完全不要调用 setUserDetails

注意: 在后续启动中设置 userDetails 不会抹除先前存储的内容,因此在您清除之前,先前存储的载荷会继续被发送。


验证与隐私行为

  • 电子邮件验证: 明文电子邮件必须恰好包含一个 @,且其后须有一个点号。无效值会被拒绝并记录日志,不会被发送。
  • 电话号码验证: 明文电话号码必须至少包含 6 位数字。更短的值会被拒绝并记录日志。
  • 错误模式保护: 看起来已经过哈希的值会被 emailphoneNumber 拒绝。同样,预哈希属性会拒绝任何不是 64 个字符 SHA-256 十六进制字符串的值。
  • 存储: 哈希后的载荷保存在各平台应用自身的私有存储中,并在卸载应用时被移除。明文值绝不会被存储。
  • Limit Data Sharing: 在启用 Limit Data Sharing 期间,User Details 载荷会从所有请求中排除。请参阅数据隐私
  • 同意: 仅在您有合法依据时才收集和发送电子邮件地址与电话号码。哈希并不能免除您在 GDPR、CCPA 或同等法规下的义务。