Los experimentos son una forma de pruebas A/B que utiliza Discord tanto del lado cliente como del servidor en sus aplicaciones para mostrar diferentes experiencias o comportamientos a usuarios diferentes aleatoriamente y/o basados en la ubicación, versión del cliente, etc.
En esencia, las implementaciones (rollouts) son simplemente YAML introducido en el panel administrativo de Discord; sin embargo, no todos los datos son requeridos por los clientes. Por eso los experimentos que los clientes ven están minificados y resultan complejos de descifrar.
Huella Digital
Incluso el sitio web de marketing utiliza tests A/B para atraer usuarios a la app. Por ello, la aplicación necesita una forma única de identificar a quien usa la web sin usar autenticación (para usuarios que inicialmente visitan la landing page), así que recurre a "fingerprints" o huellas digitales.
Estas no son las típicas fingerprints generadas por información del navegador; son snowflakes generados por peticiones no autenticadas a obtener asignaciones de experimento. Se espera que las fingerprints se envíen en la cabecera X-Fingerprint en todas las peticiones posteriores a la API hasta autenticarse, para rastrear las pruebas A/B y permitir el acceso a partes de experimentos limitadas por API.
Una fingerprint consiste en un snowflake y un valor criptográfico hasheado. Tiene este aspecto: 1084179945133187083.JQddgNMmwJPghoBtFmaH7jTmdsw.
Al registrar una nueva cuenta, la fingerprint se pasa, y (si es válida) se utiliza como ID del usuario creado. Esto es para preservar los experimentos en el usuario que acaba de registrarse. Por tanto, el tiempo de creación de una cuenta teóricamente representa la primera vez que visitó la web de marketing de Discord.
Implementaciones
Las implementaciones de experimentos se definen en poblaciones basadas en la posición de implementación del usuario o servidor y pueden tener filtros que limiten la disponibilidad de cada población.
Control y None están representados en la API como los valores enteros 0 y -1, respectivamente. Como advertencia, hay instancias donde ciertos experimentos tienen tratamientos innecesarios etiquetados como Control indexados como 1.
Posiciones de implementación
Una posición de implementación se calcula con el siguiente seudocódigo, donde exp_name es el nombre del experimento y resource_id es el ID de usuario, fingerprint o servidor. Esta posición se usa junto con las poblaciones y filtros para averiguar a qué bucket ha sido asignado el experimento simplemente comprobando en qué tratamiento entra la población.
Estructuras de datos
Hay dos tipos de experimentos, experimentos de usuario y experimentos de servidor. Los metadatos y nombres legibles por humanos están disponibles en los clientes. En la API los objetos no traen estos datos, salvo los experimentos de servidor, que pueden tener el nombre para el hash.
La mayoría de los objetos siguientes están representados como arrays siguiendo el orden documentado en los campos.
Experimentos de usuario
La información devuelta por la API sobre experimentos de usuario es muy limitada. En contraste con la variedad de datos de los rollouts de servidor, solo obtenemos el bucket asignado al usuario o la huella digital.
Los experimentos de usuario aplican los mismos filtros y funcionamiento que los de servidor, aunque solo se da el resultado calculado.
Estructura de experimento de usuario
Este objeto es un array de los siguientes campos:
1 El bucket para experimentos A/A test debe ser None (-1) salvo que haya sobrescritura para el recurso.
2 La información de holdout está presente solo si hay bucket asignado. Si hay holdout y el bucket es None (-1), el experimento está deshabilitado por el holdout. Los clientes pueden omitir este campo y solo seguir el campo population como siempre.
Campo
Tipo
Descripción
hash
integer
Hash Murmur3 de 32 bits sin signo del nombre del experimento.
revision
integer
Versión actual del rollout.
bucket
integer
El bucket experimental asignado al usuario o fingerprint.
override
integer
Indica si el usuario o fingerprint tiene sobrescritura para el experimento (-1 falso, 0 verdadero).
population
integer
El grupo interno de población al que pertenece el usuario o fingerprint.
hash_result
integer
La posición de implementación calculada a usar, priorizada a cálculos locales.
aa_mode 1
integer
Modo A/A testing, representado como booleano entero.
trigger_debugging
integer
Indica si trigger debugging de análisis está activado (booleano entero).
holdout_name 2
?string
Nombre legible de un experimento (formato año-mes_nombre) que deshabilita el experimento.
holdout_revision 2
?integer
Revisión del experimento holdout.
holdout_bucket 2
?integer
Bucket experimental asignado para el experimento holdout.
Ejemplo de experimento de usuario
Experimentos de servidor
La información aquí es más detallada porque el cliente debe calcular el bucket a asignar por cada servidor. Puede parecer difícil de parsear dada la cantidad de arrays, pero es sencillo.
En casos raros, los experimentos de servidor han controlado rollouts de grupos DM; en estos casos la API no cambia, solo los filtros que no aplican no se usan. Ejemplo: experimento 2025-04_gdm_bedazzling.
Estructura de experimento de servidor
Este objeto es un array de los siguientes campos:
1 Usado para agrupar varios experimentos coordinados.
2 Bucket para experimentos A/A test debe ser None (-1) salvo sobrescritura.
3 Si hay holdout y el servidor está en el bucket holdout, el bucket de población será None (-1) deshabilitando el experimento, salvo sobrescrituras.
Campo
Tipo
Descripción
hash
integer
Hash Murmur3 de 32 bits sin signo del nombre del experimento.
hash_key 1
?string
Nombre legible de experimento (formato año-mes_nombre) para hash, prioriza al usado en cliente.
revision
integer
Revisión actual de la implementación.
populations
array[objeto población experimental]
Las poblaciones rollout del experimento.
overrides 2
array[objeto sobrescritura experimental]
Sobrescrituras específicas para el experimento.
overrides_formatted 2
array[array[objeto población experimental]]
Poblaciones de sobrescritura para el experimento.
holdout_name 3
?string
Nombre legible de experimento (formato año-mes_nombre) que lo deshabilita.
holdout_bucket 3
?integer
Bucket holdout que deshabilita el experimento.
aa_mode 2
integer
Modo A/A testing representado como booleano entero.
trigger_debugging
integer
Si trigger debugging de analíticas está activado (booleano entero).
Ejemplo experimento de servidor
Objeto de población experimental
Define los filtros y rangos de posición que debe cumplir una población.
Estructura de objeto de población experimental
Es un array de los siguientes campos:
Campo
Tipo
Descripción
ranges
array[objeto rango de población experimental]
Los rangos para esta población.
filters
objeto de filtros de población experimental
Los filtros que el recurso debe cumplir para entrar en la población.
Ejemplo población experimental
Objeto de rango de población experimental
Si los filtros de la población son válidos y el rango incluye la posición de rollout, el recurso es elegible para ese bucket.
Estructura de objeto de rango de población experimental
Este objeto se representa como un array de los siguientes campos:
Campo
Tipo
Descripción
bucket
integer
El bucket que otorga este rango.
rollout
array[objeto rollout de población experimental]
El rango del rollout.
Estructura rollout de población experimental
Campo
Tipo
Descripción
s
integer
El inicio de este rango.
e
integer
El final de este rango.
Ejemplo de rango de población experimental
Objeto de filtros de población experimental
Define los filtros necesarios para ser elegible para los rangos. Todos los filtros deben cumplirse para que el recurso sea elegible al bucket.
Los filtros son un objeto representado como array de arrays. El primer elemento del array anidado es el key hash, el segundo el valor. El orden es siempre el documentado aquí.
Si el servidor debe tener vanity url para ser elegible.
guild_in_range_by_hash?
objeto filtro por hash/rango
Límites especiales de posición de implementarción.
1 La edad del servidor se determina por el ID. Consulta la documentación de snowflake. Puede calcularse así:
Estructuras de filtros
Campo
Tipo
Descripción
guild_features
array [string]
Las funcionalidades del servidor elegibles; con que tenga una basta.
Campo
Tipo
Descripción
min_id
?snowflake
El mínimo exclusivo para este rango, si existe.
max_id
?snowflake
El máximo exclusivo para este rango, si existe.
Campo
Tipo
Descripción
guild_ids
array [snowflake]
Lista de IDs elegibles para esa población.
Campo
Tipo
Descripción
guild_hub_types
array [integer]
Tipos de hub elegibles para esa población.
Campo
Tipo
Descripción
guild_has_vanity_url
boolean
El requisito de tener enlace personalizado para esa población.
Estructura filtro rango por hash
Este filtro se utiliza para limitar la posición de implementación (rollout) mediante una clave hash adicional. La posición de implementación calculada debe ser menor que el objetivo proporcionado. La posición de implementación puede calcularse utilizando el siguiente pseudocódigo, donde hash_key es la clave hash proporcionada y resource_id es el ID de la guild:
Campo
Tipo
Descripción
hash_key
integer
Hash Murmur3 de 32 bits sin signo usado para determinar elegibilidad.
target
integer
Límite de posición para esta población.
Ejemplo filtros de población experimental
Objeto de sobrescritura de bucket experimental
Una sobrescritura representa el ajuste manual por empleados de Discord para dar acceso temprano o concreto a un experimento.
Estructura de sobrescritura de bucket experimental
Los experimentos devueltos dependen de las propiedades del cliente.
Una fingerprint solo se genera si no hay autorización ni fingerprint en las cabeceras de petición. El límite es 3 fingerprints válidas por 2 minutos por IP. Las extra no serán válidas.
Parámetros de cadena de consulta
1 Incluir este parámetro requiere autenticación válida.
Campo
Tipo
Descripción
with_guild_experiments?
boolean
Si devolver experimentos de servidor en la respuesta.
platform? 1
string
Si incluir experimentos para la plataforma dada.
Plataforma de experimentos
Valor
Descripción
DEVELOPER_PORTAL
El portal de desarrolladores.
Cuerpo de respuesta
Campo
Tipo
Descripción
fingerprint?
string
Una fingerprint generada de la fecha y hora actual.