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
| Champ | Sens |
|---|---|
version | Fixé 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. |
storeIds | Copié des réglages du produit à chaque enregistrement (androidPackage, iosAppId). Ce que vous envoyez ici est ignoré ; fixez-les sur la page du produit. |
triggers | Un 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. |
privateAsk | Facultatif, par déclencheur. Quand afficher la demande privée. |
storePrompt | Facultatif, 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.
| Champ | Défaut | Permis | Sens |
|---|---|---|---|
minOccurrences | 1 | 1–1000 | Le déclencheur est survenu au moins ce nombre de fois. |
minDaysSinceInstall | 0 | 0–365 | Au moins ce nombre de jours depuis l'installation. |
cooldownDays | 30 | 1–365 | Au 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). |
when | aucune | jusqu'à 10 | Des conditions sur vos attributs ; voir plus bas. Toutes doivent être vraies. |
Un champ propre à privateAsk :
| Champ | Défaut | Permis | Sens |
|---|---|---|---|
skipIfSubmittedWithinDays | 365 | 0–730 | Ne pas solliciter qui a envoyé une note, depuis n'importe quel déclencheur, dans ce nombre de jours. |
Un champ propre à storePrompt :
| Champ | Défaut | Permis | Sens |
|---|---|---|---|
maxPerYear | plateforme | 1–3 | Le 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érateur | Vraie quand l'attribut… |
|---|---|
eq | est exactement ce texte. |
in | est exactement l'un de ces textes (une liste non vide). |
gte | est supérieur ou égal à cette valeur. |
lte | est inférieur ou égal à cette valeur. |
- Un attribut que l'application n'a pas fixé fait échouer sa condition.
eqetincomparent le texte exactement, casse comprise. Un attribut numérique ou booléen est comparé sous sa forme texte invariante ; un booléen se litTrueouFalse.gteetltecomparent soit deux versions à points (deux points ou plus, comme2.3.0), soit deux nombres décimaux (10,0.75). Une version contre un nombre échoue plutôt que de deviner : écrivez2.3.0, pas2.3, pour comparer des versions. Une valeur qui n'est ni l'un ni l'autre est refusée à l'enregistrement.- Les clés d'attribut sont faites de lettres, de chiffres, de
_et de-, de 1 à 40 caractères.
Comment une décision est prise
Chaque appel à TrackAsync compte une occurrence, puis :
- 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.
- Si le déclencheur a un
privateAskdont tous les seuils et conditions passent, et qu'aucune note n'a été envoyée dans lesskipIfSubmittedWithinDays, la demande est lancée. La demande passe toujours en premier. - Sinon, si le déclencheur a un
storePromptdont 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 :
- Au plus 3 invites d'évaluation sur toute période glissante de 365 jours, sur toutes les plateformes.
- Aucune invite dans les 60 jours suivant une note envoyée par la personne.
- Aucune invite dans les 7 jours suivant une demande affichée à la personne, qu'elle y ait répondu ou non.
Limites
Un enregistrement est refusé, avec chaque problème énuméré, quand le document enfreint l'une de ces règles :
- Au plus 50 déclencheurs, chacun avec un nom valide et au moins un bloc.
- Au plus 10 conditions par bloc, chacune avec une clé valide et exactement un opérateur.
- Chaque seuil dans sa plage permise (plus haut).
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 :
| Raison | Sens |
|---|---|
no_rules | Pas encore de règles, ou aucune téléchargée. |
unknown_trigger | Les règles ne nomment pas ce déclencheur. |
invalid_trigger | Le nom n'est pas fait de lettres minuscules, de chiffres et de traits de soulignement, 40 au plus. |
below_min_occurrences | minOccurrences pas atteint. |
too_soon_after_install | minDaysSinceInstall pas atteint. |
cooldown | À l'intérieur de cooldownDays. |
condition_failed | Une condition when n'est pas vraie. |
recently_submitted | La personne a envoyé une note trop récemment. |
recent_ask | Une demande a été affichée à la personne trop récemment. |
yearly_cap | Le plafond d'invites des 365 derniers jours est atteint. |
already_acted_this_session | Cette boucle a déjà sollicité ou lancé une invite. |
prompter_unavailable | Cette plateforme n'a pas d'invite d'évaluation (le Web, le bureau). |
prompter_declined | La plateforme n'a pas pu être sollicitée. |
error | Quelque chose a échoué dans la boucle ; elle ne lève jamais d'exception dans votre application. |