one_viewr_flutter 0.2.0 copy "one_viewr_flutter: ^0.2.0" to clipboard
one_viewr_flutter: ^0.2.0 copied to clipboard

Client Flutter embarquable pour Oneviewr CRM — identify/track/registerPushToken et source d'acquisition via une clé publique non secrète. Port direct de @oneviewr/js.

0.2.0 #

  • Vidéo YouTube dans les messages in-app (balisage « version 3 » de l'éditeur Oneviewr). Le bloc Vidéo accepte un lien YouTube : le message montre la vignette de la vidéo ; un toucher l'ouvre hors de l'application (l'app YouTube si elle est installée, sinon le navigateur), compte une fois comme clic (CLICKED) et laisse le message affiché.
    • Le message ne porte que l'identifiant de la vidéo (data-oneviewr-youtube, 11 caractères), revérifié côté page puis côté Dart ; l'adresse est construite par le plugin, jamais lue dans le message.
    • Le plugin annonce sdkCapabilities.compilerVersion: 3 : le serveur ne remet un message à vidéo YouTube qu'aux applications qui l'annoncent.
    • showInAppMessage(onVideoOpened:) : appelé à la première ouverture d'une vidéo pendant l'affichage.
    • Version mineure : une contrainte ^0.1.x ne la prend pas ; passer à one_viewr_flutter: ^0.2.0. Aucun autre changement d'API.

0.1.2 #

  • Outils de développement pour l'attribution et les liens profonds.
    • OneViewr.debugSimulateInstall(playReferrer:, linkCode:, clickedAt:) rejoue un premier lancement sans magasin ni vrai clic : le referrer Google Play simulé passe par le même lecteur que le vrai (UTM, gclid, publicité Meta, ov_link_code), le lien d'acquisition est résolu par le vrai serveur et deferredDeepLink le remet ensuite, une fois. Android, iOS et simulateurs. La source d'acquisition de l'appareil est remplacée durablement ; l'identité connectée ne bouge pas.
    • OneViewr.debugAttributionState() montre ce que le paquet a retenu : premier et dernier contact, premier contact envoyé ou non, lien différé (code, destination résolue, déjà remis, échecs). toString() en JSON indenté, pour un journal.
    • Les deux lèvent StateError dans une build --release.
    • README : section « Tester sans magasin », avec les commandes adb et xcrun simctl qui font ouvrir un lien par le système.

0.1.1 #

  • Sondages, carrousels et coupons des messages in-app réparés. Depuis la 0.1.0, toucher une réponse de sondage, une flèche de carrousel, « Copier » ou « Envoyer » ne faisait rien : le script lisait l'action en retirant 12 caractères, la longueur de l'ancien préfixe neero-inapp:, au lieu des 15 de oneviewr-inapp: (« p:choice » au lieu de « choice »). Le préfixe est maintenant déclaré une seule fois (inAppLinkScheme), partagé avec l'interception des liens, et l'action est lue d'après sa longueur. Le bouton d'action et la croix n'étaient pas touchés.

0.1.0 #

  • Renommage Neero → Oneviewr du balisage in-app : le paquet lit désormais oneviewr-inapp:*, data-oneviewr-* et les canaux OneviewrInAppHeight / OneviewrInAppAction, comme le serveur (migration V329). Rupture : une application qui embarque une version antérieure du paquet ne comprend plus les messages in-app (liens et sondages inertes) — elle doit être mise à jour.

  • Rapports d'installation Apple : au premier lancement sur iOS, le paquet enregistre l'installation auprès de SKAdNetwork (valeur de conversion 0). Sans cet appel, Apple n'envoie aucun rapport d'installation pour une publicité Meta, Google, TikTok… — ni à la régie, ni la copie qu'Oneviewr reçoit pour compter les installations iOS par régie et par campagne. Apple répercute cet appel dans AdAttributionKit : les rapports des deux cadres sont couverts, sans appeler AdAttributionKit ni le lier.

    • Une fois par installation, en arrière-plan (boot ne l'attend pas) ; un échec est retenté aux lancements suivants, trois fois au plus. Le marqueur survit à reset(). Rien avec attribution: false, ni sur Android ou le web. Aucun consentement ATT requis.
    • boot(appleAdAttribution: false) laisse un autre SDK (Meta, Firebase, AppsFlyer…) gérer les valeurs de conversion.
    • À faire dans l'application pour qu'Oneviewr reçoive les rapports : clés Info.plist NSAdvertisingAttributionReportEndpoint (copies SKAdNetwork) et AdAttributionKit › AttributionCopyEndpoint (copies AdAttributionKit), toutes deux = https://onvw.link (+ OptInForReengagementPostbackCopies, facultatif). Voir la section « Rapports d'installation Apple » du README.
    • Nouveau code natif iOS (registerAdAttribution) : l'application hôte doit être reconstruite. Framework StoreKit ajouté.
  • birthDate rejoint enfin les parcours d'anniversaire. La date partait dans l'attribut birth_date, que rien ne lit : l'import CSV, la fiche client et les parcours d'anniversaire lisent birthday. Elle part désormais dans le champ birthday de identify, au format AAAA-MM-JJ (une date ISO complète est acceptée, seule la date telle qu'écrite est gardée). Une date mal formée lève ArgumentError avant tout appel réseau, au lieu de faire échouer tout l'identify côté serveur. Les contacts déjà créés gardent leur ancien attribut birth_date : un nouvel identify remplit birthday.

  • Positions : trackLocation, trackLocations — transmission de positions fournies par l'application hôte, lots de 100, file hors-ligne AES-GCM limitée à 500 échantillons et 24 heures, avec rejeu idempotent.

  • Liens d'acquisition différés — le lien Oneviewr sur lequel l'utilisateur a cliqué avant d'installer l'application est retrouvé au premier lancement et rendu à l'application, qui l'envoie où le marchand l'a voulu (un écran précis). Nouveau OneViewr.deferredDeepLink() (une seule remise) et OneViewr.resolveDeepLink(uri) (application déjà installée, lien universel / App Link), qui rendent un DeepLink (status, appRoute, appParams, fallbackUrl…) via POST /api/v1/public/deep-link/resolve. Le paquet ne navigue jamais lui-même.

    • Android : ov_link_code, lu dans le Play Install Referrer — silencieux.
    • iOS : jeton signé copié dans le presse-papiers par la page de redirection. Désactivé par défaut : boot(readIosClipboard: true), car iOS 16 affiche « Autoriser le collage ? ». Seul un texte de la forme exacte d'un jeton Oneviewr est gardé ; il est effacé du presse-papiers après lecture. Un jeton expiré (dix minutes) n'est pas rattaché à l'installation.
    • AttributionTouch.acquisitionLinkCode : le code du lien, envoyé avec identify/track (premier/dernier contact) ; il compte à lui seul comme signal. recordDeepLink le relève dans /l/{code} ou dans /{code} sur onvw.link.
    • boot(deferredLinkSource:) remplace la recherche par défaut (DeferredLinkSource, comme installAttribution pour l'installation).
    • Nouveau code natif iOS (pasteboardToken) : l'application hôte doit être reconstruite après la mise à jour.
    • Au mieux, jamais garanti : voir la section « Liens d'acquisition Oneviewr » du README.
  • OneViewr.signupProgress(step:, stepNumber:, attemptId:, properties:) : une étape du formulaire d'inscription, envoyée comme l'événement signup_progress (step, step_number, attempt_id), même contrat que le SDK JS. L'inscription se termine par track('signup') ; la fiche client Oneviewr montre alors l'étape atteinte, les tentatives et les dates.

  • Sondages : on voit si l'on peut cocher une ou plusieurs réponses. Le compilateur d'Oneviewr pose devant chaque réponse un rond (choix unique) ou un carré (plusieurs), et le plugin y écrit ● ou ✓ quand la réponse est choisie — comme le SDK JS. Écrits en échappements JavaScript (\u25CF, \u2713) : le script reste en ASCII, insensible à l'encodage. Un message compilé avant (sans picto) s'affiche comme avant.

  • Messages in-app « version 2 » (Growth OS, lot 5.1) : carrousel, compte à rebours, coupon (copie dans le presse-papiers natif), sondage (réponses envoyées par answerInAppSurvey, fermeture automatique après 1,8 s, comptée comme un clic), barre de progression, vidéo. Le plugin annonce sdkCapabilities.compilerVersion: 2 : jusqu'ici, le serveur ne lui remettait jamais ces messages, ni ceux à écrans ciblés.

  • OneViewr.setScreen(nom, context:) : écran courant pour les « Écrans ciblés », envoyé avec chaque demande ; avec un contexte, la vérification repart aussitôt.

  • Sécurité du rendu : un script constant du paquet anime les blocs (aucun innerHTML, aucune URL, aucun réseau) ; un canal OneviewrInAppAction dont chaque message est revalidé ; clics synthétiques neutralisés ; toute navigation autre que le document et oneviewr-inapp:cta/dismiss est désormais refusée (avant, un lien https naviguait dans la boîte).

  • Encodage : le document du message déclare utf-8 — sans lui, un moteur pouvait relire « fidélité » en « fidélité ».

  • Publicités Meta sur Android : le bloc chiffré part au serveur. Au lieu d'être jeté, le détail du clic que Meta chiffre dans le referrer Google Play est transmis tel quel dans metaInstallReferrer (nouveau champ d'AttributionTouch, hors UTM, plafonné à 8 192 caractères). Le serveur Oneviewr l'ouvre avec la clé que le marchand enregistre dans Paramètres › Sources publicitaires, en tire la campagne, l'ensemble de publicités et la publicité, puis le jette — jamais stocké.

  • Source d'acquisition (Growth OS, lot 3.1, volet Flutter). Le paquet note d'où vient l'appareil et envoie le premier et le dernier contact dans identify (attribution) et le dernier dans track (context.attribution), au format du SDK JS. Android : Play Install Referrer (UTM, gclid des campagnes d'application Google Ads, publicité Meta — campagne chiffrée non déchiffrée). iOS : jeton Apple AdServices, échangé auprès d'Apple contre la campagne Apple Search Ads. Web : l'adresse de la page. Nouveau OneViewr.recordDeepLink(uri) pour les liens qui ouvrent l'application. boot(attribution: false) désactive et efface ; boot(installAttribution:) relaie un outil de mesure mobile. Tant que le premier contact n'est pas fixé, identify n'envoie aucune source (le serveur prendrait sinon le dernier contact pour le premier), puis le paquet le renvoie en arrière-plan dès qu'il l'est.

  • Le paquet devient un plugin natif (android/, ios/, canal one_viewr_flutter/attribution) : dépendance com.android.installreferrer:installreferrer, framework AdServices. Une application hôte doit être reconstruite après la mise à jour.

  • Les identifiants d'installation (clientRef in-app, deviceId push) sont résolus par un seul corps, qui mémoïse le Future et non la valeur. Deux appels concurrents arrivés avant que l'identifiant n'existe lisaient auparavant tous deux un stockage vide, généraient chacun leur UUID et en écrivaient un par-dessus l'autre : les deux requêtes partaient avec des identifiants différents pour le même appareil — exactement ce que cet identifiant existe pour éviter. Le cas n'est pas théorique, l'application hôte enregistrant son token push et vérifiant ses messages in-app depuis deux blocs qui avancent en parallèle.

  • registerPushToken accepte un deviceId explicite, en plus de celui que le paquet persiste déjà. De type FutureOr<String>?, parce que les sources d'identifiant d'appareil (FirebaseInstallations.getId(), device_info_plus) sont asynchrones ; résolu au moment de l'appel, une fois les gardes passées — un Future fourni n'est donc jamais attendu pour un appel qui échoue sur une identité manquante. Omis, rien ne change : le paquet envoie le sien.

  • FULLSCREEN s'affiche sur le Navigator racine et non sur celui d'où vient le BuildContext. Le contexte passé à checkInAppMessages vient presque toujours d'un écran d'onglet, donc d'un Navigator imbriqué : la route « plein écran » ne couvrait alors que la zone de cet onglet, et la barre de navigation de l'application hôte restait visible par-dessus le message, onglets toujours actifs. BOTTOM_SHEET posait déjà useRootNavigator: true pour cette raison ; BANNER suit désormais la même règle côté Overlay.

  • FULLSCREEN pose un Scaffold et une SafeArea, et la hauteur allouée déduit les encoches. Sans SafeArea, le haut du message passait sous la barre d'état et son bouton d'action sous l'indicateur d'accueil — pas seulement mal placé, intouchable. Sans Scaffold, les bandes laissées libres par les encoches ne peignaient rien de défini, une MaterialPageRoute n'ayant pas de fond propre.

  • reset() referme le message in-app affiché au moment de l'appel, et interrompt une vérification en cours — il appartenait à l'identité qu'on vient d'oublier. Aucun acquittement n'est émis dans ce cas : personne ne l'a fermé, il a été retiré de l'écran. Aligne le paquet sur @oneviewr/js, dont le reset démonte lui aussi l'overlay en place.

  • checkInAppMessages ne tourne plus qu'une fois à la fois : un appel concurrent rend la main en silence au lieu d'empiler une seconde boîte de dialogue. Même verrou que le polling/active du poller côté SDK JS, et le cas est courant ici — la méthode est censée être rappelée à chaque retour au premier plan, donc pendant qu'un message est déjà affiché.

  • ackInAppMessage refuse un messageId vide et un event hors SHOWN/CLICKED/DISMISSED, avant tout appel réseau (ArgumentError). Sans ce contrôle, une faute de frappe partait sur le réseau — et comme cette méthode avale volontairement les ApiException, l'appelant ne voyait jamais son erreur.

  • registerPushToken envoie maintenant un deviceId stable (généré une fois par appareil, persisté via le même KeyValueStore que clientRef, survit à reset()) — permet au backend de mettre à jour la même ligne côté serveur quand le token FCM tourne (normal, périodique) au lieu d'en créer une nouvelle à chaque fois. Aucun changement de signature publique.

0.0.1 #

  • Port initial du SDK JS public @oneviewr/js (neero-crm/sdk-js) : boot, identify, track, registerPushToken, unregisterPushToken, reset.
  • checkInAppMessages/ackInAppMessage — affichage des messages in-app (canal IN_APP) via une WebView (webview_flutter), avec ouverture du bouton d'action via url_launcher (« rupture de doctrine », voir le README) — appel manuel requis après identify() et à chaque retour au premier plan, contrairement au SDK JS.
  • trackNotificationClick — signale qu'une notification push a été tapée (POST /messages/{id}/ack), à appeler depuis votre propre intégration Firebase (onMessageOpenedApp/getInitialMessage) — ce paquet ne s'abonne jamais à Firebase lui-même. Ne lève jamais, renvoie false pour toute notification qui n'est pas d'origine Oneviewr ou en cas d'échec.
0
likes
130
points
106
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Client Flutter embarquable pour Oneviewr CRM — identify/track/registerPushToken et source d'acquisition via une clé publique non secrète. Port direct de @oneviewr/js.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

cryptography, dio, flutter, flutter_secure_storage, shared_preferences, url_launcher, webview_flutter

More

Packages that depend on one_viewr_flutter

Packages that implement one_viewr_flutter