Documentation

Référence des règles

Les règles forment un document JSON par produit. Vous le modifiez dans le portail, par formulaire ou en JSON ; le SDK le télécharge dans InitializeAsync et l'évalue sur l'appareil chaque fois que votre application appelle TrackAsync.

Un exemple complet

{
  "version": 7,
  "triggers": {
    "session_end": {
      "privateAsk": {
        "minOccurrences": 5,
        "minDaysSinceInstall": 3,
        "cooldownDays": 60,
        "skipIfSubmittedWithinDays": 180
      }
    },
    "workout_completed": {
      "storePrompt": {
        "minOccurrences": 3,
        "minDaysSinceInstall": 7,
        "cooldownDays": 120,
        "maxPerYear": 2,
        "when": {
          "appVersion": { "gte": "2.3.0" },
          "plan": { "in": ["solo", "studio"] }
        }
      }
    }
  }
}

Une personne qui a terminé cinq sessions, trois jours ou plus après le premier lancement du SDK, voit la demande privée — sauf si elle a envoyé une note dans les 180 derniers jours. Une personne qui a terminé trois entraînements, au moins une semaine après, avec la version 2.3.0 ou plus récente et l'un des deux forfaits nommés, se voit proposer l'invite d'évaluation — au plus deux fois sur toute période de 365 jours, et jamais dans les 60 jours suivant une note ni les 7 jours suivant une demande. Ici, appVersion et plan sont des attributs que l'application fixe elle-même dans Attributes ; les conditions ne lisent que ceux-là, pas l'option AppVersion.

Le document

ChampSens
versionFixé par le serveur à chaque enregistrement. Vous pouvez envoyer la version que vous avez lue en dernier ; si les règles ont changé depuis, l'enregistrement est refusé avec rules.conflict. Zéro veut dire aucune vérification. C'est aussi l'ETag avec lequel les appareils revalident.
storeIdsCopié des réglages du produit à chaque enregistrement (androidPackage, iosAppId). Ce que vous envoyez ici est ignoré ; fixez-les sur la page du produit.
triggersUn objet : nom de déclencheur → ce que ce déclencheur peut causer. Un nom est fait de lettres minuscules, de chiffres et de traits de soulignement, de 1 à 40 caractères, et correspond à ce que votre code passe à TrackAsync.
privateAskFacultatif, par déclencheur. Quand afficher la demande privée.
storePromptFacultatif, par déclencheur. Quand demander à la plateforme son invite d'évaluation. Un déclencheur doit avoir au moins l'un des deux.

Un produit qui n'a pas encore de règles sert {"version":0,"triggers":{}} : rien ne s'affiche, rien ne part.

Seuils

Les deux blocs acceptent ces champs. Les « occurrences » sont comptées sur l'appareil, une par appel à TrackAsync pour ce déclencheur, et ne sont jamais remises à zéro. L'« installation » est le premier lancement du SDK sur cet appareil.

ChampDéfautPermisSens
minOccurrences11–1000Le déclencheur est survenu au moins ce nombre de fois.
minDaysSinceInstall00–365Au moins ce nombre de jours depuis l'installation.
cooldownDays301–365Au moins ce nombre de jours depuis la dernière action de ce bloc pour ce déclencheur (la demande a été affichée, ou l'invite a été demandée).
whenaucunejusqu'à 10Des conditions sur vos attributs ; voir plus bas. Toutes doivent être vraies.

Un champ propre à privateAsk :

ChampDéfautPermisSens
skipIfSubmittedWithinDays3650–730Ne pas solliciter qui a envoyé une note, depuis n'importe quel déclencheur, dans ce nombre de jours.

Un champ propre à storePrompt :

ChampDéfautPermisSens
maxPerYearplateforme1–3Le nombre maximal d'invites sur toute période glissante de 365 jours, en comptant chaque invite demandée par l'application, peu importe le déclencheur. S'il est omis, c'est 2 sur Android et 3 ailleurs. L'option MaxStorePromptsPerYear de l'application peut l'abaisser encore.

Conditions

when associe une clé d'attribut à une condition. Les attributs sont ceux que votre application fixe dans Attributes. Chaque condition a exactement un opérateur :

OpérateurVraie quand l'attribut…
eqest exactement ce texte.
inest exactement l'un de ces textes (une liste non vide).
gteest supérieur ou égal à cette valeur.
lteest inférieur ou égal à cette valeur.

Comment une décision est prise

Chaque appel à TrackAsync compte une occurrence, puis :

  1. Si la boucle a déjà affiché une demande ou lancé une invite d'évaluation, plus rien ne se passe pour le reste de sa vie — une action par session.
  2. Si le déclencheur a un privateAsk dont tous les seuils et conditions passent, et qu'aucune note n'a été envoyée dans les skipIfSubmittedWithinDays, la demande est lancée. La demande passe toujours en premier.
  3. Sinon, si le déclencheur a un storePrompt dont tous les seuils et conditions passent, le moteur vérifie ensuite ses périodes de silence fixes et le plafond, puis sollicite la plateforme.

Les limites fixes du moteur s'appliquent, quoi que disent les règles :

Limites

Un enregistrement est refusé, avec chaque problème énuméré, quand le document enfreint l'une de ces règles :

Le document enregistré doit aussi compter au plus 65 536 caractères (rules.too_large). Le SDK applique la même validation à un document téléchargé et garde ses règles en cache si le nouveau échoue.

Raisons

Quand rien ne se passe, la Reason de la Decision est l'une de ces chaînes stables, sûres à journaliser :

RaisonSens
no_rulesPas encore de règles, ou aucune téléchargée.
unknown_triggerLes règles ne nomment pas ce déclencheur.
invalid_triggerLe nom n'est pas fait de lettres minuscules, de chiffres et de traits de soulignement, 40 au plus.
below_min_occurrencesminOccurrences pas atteint.
too_soon_after_installminDaysSinceInstall pas atteint.
cooldownÀ l'intérieur de cooldownDays.
condition_failedUne condition when n'est pas vraie.
recently_submittedLa personne a envoyé une note trop récemment.
recent_askUne demande a été affichée à la personne trop récemment.
yearly_capLe plafond d'invites des 365 derniers jours est atteint.
already_acted_this_sessionCette boucle a déjà sollicité ou lancé une invite.
prompter_unavailableCette plateforme n'a pas d'invite d'évaluation (le Web, le bureau).
prompter_declinedLa plateforme n'a pas pu être sollicitée.
errorQuelque chose a échoué dans la boucle ; elle ne lève jamais d'exception dans votre application.