Créer un APK gratuit

API du pont JavaScript

La boîte de réception push et l'audience

Les messages envoyés par le créateur depuis un tableau de bord, conservés sur l'appareil afin que la page puisse afficher un historique plutôt qu'une simple notification : ainsi que l'identifiant d'utilisateur connecté et les tags qui permettent au centre d'envoi de cibler un utilisateur ou un tag, et de déclencher des automatisations comme un rappel de panier abandonné.

AppMint.trackEvent assistant#

window.AppMint.trackEvent

Exemple

Documenté avec WebToApk.trackEvent : l'exemple qui s'y trouve illustre aussi celui-ci.

Indique à l'application qu'un événement s'est produit ("signed_up", "checkout_done", "level:3"). Un message intégré à l'application créé par le créateur dans le centre d'envoi AppMint Push avec le déclencheur « Lorsqu'un événement se produit » et le même nom s'affiche alors (ou après le délai choisi par le créateur).

Retourne : true quand l'événement a été pris en compte ; false pour un nom hors lettres, chiffres et _ . : - (jusqu'à 64), et dans une application compilée sans AppMint Push. AppMint.trackEvent(name, props) est le même appel avec props sous forme d'objet. Nécessite : AppMint Push activé à l'étape Intégration (étape 3) lors de la compilation. propsJson est facultatif ('') et n'est pas conservé.

// After a purchase: the creator's "Thanks, rate us?" message is set to trigger on "purchase_done".
function onPurchaseDone(order) {
  if (window.AppMint && AppMint.trackEvent) {
    AppMint.trackEvent('purchase_done', { total: order.total });
  }
}

Le pont brut prend les propriétés sous forme de chaîne JSON (passez '' s'il n'y en a aucune) :

function track(name, props) {
  if (!(window.WebToApk && window.WebToApk.trackEvent)) return false;   // a browser: nothing to show
  return WebToApk.trackEvent(name, props ? JSON.stringify(props) : '');
}
track('level:3');
track('tutorial_skipped', { step: 2 });

Un changement d'écran que l'adresse ne montre pas (onglets, assistant, « page » modale) peut être signalé comme une route, afin que les messages « Sur une page » du créateur le voient. La page peut aussi envoyer l'événement appmint:route avec le chemin ; l'application l'écoute :

function showTab(name) {
  document.querySelectorAll('.tab').forEach(function (t) { t.hidden = t.id !== name; });
  if (window.AppMint && AppMint.trackEvent) AppMint.trackEvent('appmint:route', { path: '/' + name });
}

// Same thing, without touching the bridge at all:
window.dispatchEvent(new CustomEvent('appmint:route', { detail: { path: '/cart' } }));

Remarques : les messages par route suivent déjà d'eux-mêmes les vrais changements d'URL (chargements de page, routes history.pushState, #/hash) ; ne signalez une route que pour les vues dont l'adresse ne change pas. Les événements ne sont ni comptés ni stockés nulle part ; ils décident seulement si un message s'affiche.

clearPushInbox pont#

window.WebToApk.clearPushInbox(): Boolean

Vide la boîte de réception push (le panneau de notifications et l'historique du serveur ne sont pas touchés).

Exemple

Vide la boîte de réception push de ce téléphone.

Renvoie : true lorsque c'est fait ; false en cas d'erreur interne. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation.

document.getElementById('clear-inbox').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.clearPushInbox)) return;
  if (!confirm('Delete all messages? This cannot be undone.')) return;
  if (WebToApk.clearPushInbox()) renderInbox();
});

Videz la boîte de réception lorsque l'utilisateur se déconnecte, afin que la personne suivante sur ce téléphone ne voie pas ses messages :

async function signOut() {
  await myAuth.signOut();
  if (window.WebToApk && window.WebToApk.clearPushInbox) {
    WebToApk.clearPushInbox();
  }
  document.getElementById('bell-count').textContent = '';
  showLoginScreen();
}

Affichez une ligne de paramètres indiquant combien de messages sont stockés, désactivée quand il n'y a rien à supprimer :

function paintClearRow() {
  const btn = document.getElementById('clear-inbox');
  if (!(window.WebToApk && window.WebToApk.clearPushInbox)) { btn.hidden = true; return; }
  const count = JSON.parse(WebToApk.getPushInbox() || '[]').length;
  btn.textContent = count ? 'Delete ' + count + ' messages' : 'No messages';
  btn.disabled = count === 0;
}

document.getElementById('clear-inbox').addEventListener('click', function () {
  if (WebToApk.clearPushInbox()) paintClearRow();
  else alert('Could not delete the messages. Please try again.');
});

paintClearRow();

Remarques : c'est permanent - contrairement à dismissPushMessage, il n'y a pas d'annulation. Les notifications du volet et votre historique d'envoi dans AppMint ne sont pas touchés. Les nouveaux messages arrivent toujours.

dismissPushMessage pont#

window.WebToApk.dismissPushMessage(id: String): Boolean

Écarte UN message de la boîte de réception : le balayage par ligne dont un écran de boîte de réception a besoin (clearPushInbox est tout ou rien). RÉVERSIBLE par conception : l'entrée est masquée, pas détruite, de sorte que l'interface peut proposer « Annuler » pendant quelques secondes après le balayage. Local uniquement : la notification du panneau et l'historique du créateur ne sont pas touchés.

Exemple

Masque un message de la boîte de réception push (un balayage pour l'écarter). Peut être annulé avec restorePushMessage(id).

Retourne : true si le message a été masqué ; false si l'id est inconnu ou s'il était déjà masqué. Nécessite : activez AppMint Push à l'étape Intégration (étape 3) lors de la compilation.

Écartez par balayage avec un Annuler de 5 secondes :

function dismissRow(id, rowEl) {
  if (!(window.WebToApk && window.WebToApk.dismissPushMessage)) return;
  if (!WebToApk.dismissPushMessage(id)) return;
  rowEl.remove();

  const bar = document.getElementById('undo-bar');
  bar.hidden = false;
  const timer = setTimeout(function () { bar.hidden = true; }, 5000);
  document.getElementById('undo-btn').onclick = function () {
    clearTimeout(timer);
    bar.hidden = true;
    WebToApk.restorePushMessage(id);         // back in its old place
    renderInbox();
  };
}

Rangez la boîte de réception à son ouverture en masquant les messages lus de plus de 30 jours :

function hideOldReadMessages() {
  if (!(window.WebToApk && window.WebToApk.dismissPushMessage)) return 0;
  const cutoff = Date.now() - 30 * 24 * 60 * 60 * 1000;
  let hidden = 0;
  JSON.parse(WebToApk.getPushInbox() || '[]').forEach(function (m) {
    if (m.read && m.receivedAt < cutoff && WebToApk.dismissPushMessage(m.id)) hidden++;
  });
  return hidden;
}

if (hideOldReadMessages() > 0) renderInbox();

Écartez une ligne par un vrai balayage du doigt (en la faisant glisser sur plus de 40 % de sa largeur) :

function makeSwipeable(rowEl, id) {
  let startX = null;
  rowEl.addEventListener('pointerdown', function (e) { startX = e.clientX; rowEl.setPointerCapture(e.pointerId); });
  rowEl.addEventListener('pointermove', function (e) {
    if (startX !== null) rowEl.style.transform = 'translateX(' + (e.clientX - startX) + 'px)';
  });
  rowEl.addEventListener('pointerup', function (e) {
    const dx = startX === null ? 0 : e.clientX - startX;
    startX = null;
    if (Math.abs(dx) > rowEl.offsetWidth * 0.4 && window.WebToApk && WebToApk.dismissPushMessage(id)) {
      rowEl.remove();
    } else {
      rowEl.style.transform = '';            // not far enough: snap back
    }
  });
}

Remarques : seule la boîte de réception de ce téléphone change. La notification du panneau et votre historique d'envoi dans AppMint restent. Les messages masqués ne sont pas renvoyés par getPushInbox().

getInAppCampaigns pont#

window.WebToApk.getInAppCampaigns(): String

Messages intégrés à l'application que cette installation détient : JSON [{id, name}] ("[]" sans AppMint Push).

Exemple

Liste les messages in-app que cette installation détient en ce moment (les campagnes du créateur issues du centre d'envoi AppMint Push dont cet utilisateur fait partie de l'audience) sous forme de chaîne JSON [{"id": "...", "name": "..."}].

Retourne : une chaîne de tableau JSON ; "[]" quand il n'y en a aucun et dans une application compilée sans AppMint Push. Nécessite : AppMint Push activé à l'étape Intégration (étape 3) lors de la compilation. La liste s'actualise à chaque démarrage de l'application (et environ toutes les heures au premier plan).

var list = [];
if (window.WebToApk && window.WebToApk.getInAppCampaigns) {
  try { list = JSON.parse(WebToApk.getInAppCampaigns()); } catch (e) {}
}
console.log('in-app messages on this phone:', list.map(function (c) { return c.name; }));

Affichez une liste de débogage dans votre propre écran d'administration :

function renderInAppDebug(el) {
  var raw = (window.WebToApk && WebToApk.getInAppCampaigns) ? WebToApk.getInAppCampaigns() : '[]';
  var items = JSON.parse(raw);
  el.innerHTML = items.length
    ? items.map(function (c) { return '<li>' + c.name + ' <code>' + c.id + '</code></li>'; }).join('')
    : '<li>No in-app messages for this install</li>';
}
renderInAppDebug(document.getElementById('inapp-debug'));

Ignorez votre propre message de bienvenue lorsque le créateur diffuse déjà un message portant ce nom :

function hasCampaign(name) {
  try { return JSON.parse(WebToApk.getInAppCampaigns()).some(function (c) { return c.name === name; }); }
  catch (e) { return false; }
}
if (!hasCampaign('Welcome tour')) showMyOwnWelcome();

Remarques : seuls l'id et le nom sont exposés ; le message lui-même atteint la page via l'événement appmint:inapp quand il s'affiche (voir setInAppPresentation).

getPushInbox pont#

window.WebToApk.getPushInbox(): String

Boîte de réception AppMint Push (messages envoyés par le créateur, du plus récent au plus ancien, 50 max) : tableau JSON de {id, title, body, imageUrl, link, receivedAt, read}. Toujours l'état complet et actuel - une application qui se monte tard ne perd rien pour avoir manqué les événements `appmint:push` en direct.

Exemple

Lit la boîte de réception intégrée des messages push que vous avez envoyés avec AppMint Push : du plus récent au plus ancien, jusqu'à 50, sans ceux que l'utilisateur a écartés.

Retourne : une chaîne JSON, de façon synchrone. Analysez-la. Chaque élément : { id, title, body, imageUrl, link, receivedAt, read } (receivedAt en ms epoch ; imageUrl et link valent '' quand le message n'en a pas), plus des champs de design facultatifs quand vous avez utilisé un modèle dans AppMint : template, accent, iconUrl, buttons: [{label, link}], badge, inapp, countdownAt, progress, lines, collapse. '[]' quand c'est vide. Nécessite : activez AppMint Push à l'étape Intégration (étape 3) lors de la compilation ; sans cela, la boîte de réception est toujours vide.

Affichez la boîte de réception, et actualisez-la en direct avec appmint:push :

function loadInbox() {
  if (!(window.WebToApk && window.WebToApk.getPushInbox)) return [];
  try { return JSON.parse(WebToApk.getPushInbox() || '[]'); } catch (e) { return []; }
}

function renderInbox() {
  const inbox = loadInbox();
  const unread = inbox.filter(function (m) { return !m.read; }).length;
  document.getElementById('bell-count').textContent = unread ? String(unread) : '';
  const ul = document.getElementById('inbox');
  ul.innerHTML = '';
  inbox.forEach(function (m) {
    const li = document.createElement('li');
    li.className = m.read ? 'read' : 'unread';
    li.textContent = m.title + ' — ' + m.body;
    li.onclick = function () {
      WebToApk.markPushRead(m.id);
      if (m.link) location.href = m.link;
      renderInbox();
    };
    ul.appendChild(li);
  });
}

// While the app is open:
window.addEventListener('appmint:push', function (e) {
  // { type: 'received', message: {id, title, body, ...}, presented: true|false }
  // { type: 'revoked', id }  — you retracted the message
  // presented = the app already showed it on screen (see setPushPresentation)
  if (e.detail.type === 'received' && !e.detail.presented) showBanner(e.detail.message.title);
  renderInbox();
});

renderInbox();

Mettez à jour le compteur de non lus sur votre cloche chaque fois que l'utilisateur revient dans l'application (les messages arrivés pendant qu'elle était en arrière-plan sont déjà dans la boîte de réception) :

function unreadCount() {
  if (!(window.WebToApk && window.WebToApk.getPushInbox)) return 0;
  try {
    return JSON.parse(WebToApk.getPushInbox() || '[]').filter(function (m) { return !m.read; }).length;
  } catch (e) { return 0; }
}

function paintBell() {
  const n = unreadCount();
  const badge = document.getElementById('bell-count');
  badge.textContent = n > 9 ? '9+' : (n ? String(n) : '');
  badge.hidden = n === 0;
}

document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'visible') paintBell();
});
paintBell();

Affichez l'image d'un message et ses boutons (uniquement si vous l'avez conçu avec), ainsi que l'heure de réception :

function renderCard(m) {
  const card = document.createElement('article');
  if (m.accent) card.style.borderLeft = '4px solid ' + m.accent;
  if (m.imageUrl) {
    const img = document.createElement('img');
    img.src = m.imageUrl; img.alt = '';
    card.appendChild(img);
  }
  const h = document.createElement('h3');
  h.textContent = m.title;
  const p = document.createElement('p');
  p.textContent = m.body;
  const time = document.createElement('time');
  time.textContent = new Date(m.receivedAt).toLocaleString();
  card.append(h, p, time);
  (m.buttons || []).forEach(function (b) {
    const btn = document.createElement('button');
    btn.textContent = b.label;
    btn.onclick = function () { WebToApk.markPushRead(m.id); if (b.link) location.href = b.link; };
    card.appendChild(btn);
  });
  return card;
}

if (window.WebToApk && window.WebToApk.getPushInbox) {
  const list = document.getElementById('inbox');
  JSON.parse(WebToApk.getPushInbox() || '[]').forEach(function (m) { list.appendChild(renderCard(m)); });
}

Remarques : la boîte de réception est conservée sur le téléphone ; lisez-la donc à l'ouverture de votre écran : les événements n'arrivent que lorsque l'application est à l'écran. Un message que vous retirez depuis AppMint disparaît de la boîte de réception et du panneau de notifications. Les messages envoyés en « push uniquement » (panneau) ne sont pas ajoutés à la boîte de réception. Le même détail est aussi transmis à window.onAppMintPush(detail) si vous le définissez.

getPushTags pont#

window.WebToApk.getPushTags(): String

Les tags de cette installation sous forme de chaîne d'objet JSON, par ex. {"plan":"pro"}.

Exemple

Lit les tags AppMint Push de cette installation.

Renvoie : une chaîne JSON, de façon synchrone : un objet de valeurs textuelles, par ex. '{"plan":"pro","cart":"open"}' ; '{}' s'il n'y en a aucune. Analysez-la. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation.

Lire un tag :

function pushTags() {
  if (!(window.WebToApk && window.WebToApk.getPushTags)) return {};
  try { return JSON.parse(WebToApk.getPushTags() || '{}'); } catch (e) { return {}; }
}

const plan = pushTags().plan || 'free';

Ne définissez un tag que lorsqu'il change - chaque appel setPushTag fait se signaler l'installation auprès d'AppMint Push, donc évitez ceux qui ne changent rien :

function ensureTag(key, value) {
  if (!(window.WebToApk && window.WebToApk.getPushTags)) return;
  const tags = JSON.parse(WebToApk.getPushTags() || '{}');
  if ((tags[key] || '') !== value) WebToApk.setPushTag(key, value);
}

ensureTag('plan', user.isPro ? 'pro' : 'free');

Listez-les sur un écran de débogage pendant que vous testez l'envoi à un tag :

const list = document.getElementById('push-tags');
if (window.WebToApk && window.WebToApk.getPushTags) {
  const tags = JSON.parse(WebToApk.getPushTags() || '{}');
  list.textContent = Object.keys(tags).length
    ? Object.keys(tags).map(function (k) { return k + ' = ' + tags[k]; }).join('\n')
    : 'No tags yet';
}

Remarques : c'est ce que détient le téléphone ; le centre d'envoi le voit après la prochaine synchronisation de l'installation, quelques secondes après une modification lorsque le téléphone est en ligne.

getPushUser pont#

window.WebToApk.getPushUser(): String

Le dernier identifiant d'utilisateur défini avec setPushUser ("" lorsque déconnecté ou jamais défini).

Exemple

Lit l'identifiant d'utilisateur que cette installation a donné en dernier à AppMint Push avec setPushUser.

Renvoie : une string, de façon synchrone : l'identifiant enregistré, ou '' lorsque personne n'est connecté ou qu'il n'a jamais été défini. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation.

Ne définissez l'identifiant que s'il a changé (à chaque démarrage de l'application) :

function syncPushUser(currentUserId) {
  if (!(window.WebToApk && window.WebToApk.getPushUser)) return;
  const want = currentUserId || '';
  if (WebToApk.getPushUser() !== want) WebToApk.setPushUser(want);
}

syncPushUser(localStorage.getItem('userId'));

Effacez un identifiant périmé lorsque votre propre session a expiré alors que l'application était fermée :

async function checkSession() {
  const session = await myBackend.currentSession();       // null when expired
  if (!session && window.WebToApk && window.WebToApk.getPushUser && WebToApk.getPushUser() !== '') {
    WebToApk.setPushUser('');                              // stop personal messages to this phone
  }
}

checkSession();

Affichez-le sur un écran de débogage pendant que vous testez l'envoi à un seul utilisateur :

const info = document.getElementById('push-debug');
if (window.WebToApk && window.WebToApk.getPushUser) {
  const id = WebToApk.getPushUser();
  info.textContent = id ? 'Push user: ' + id : 'Push user: nobody signed in';
} else {
  info.textContent = 'Not inside the app';
}

Remarques : c'est ce que détient le téléphone. Le centre d'envoi voit une modification après la prochaine synchronisation de l'installation, quelques secondes plus tard lorsque le téléphone est en ligne.

markPushRead pont#

window.WebToApk.markPushRead(id: String): Boolean

Marque un message push comme lu ; passez "" pour marquer tous les messages comme lus.

Exemple

Marque un message de la boîte de réception push comme lu, ou tous quand vous passez ''.

Retourne : true si un message a changé ; false si rien n'a changé (id inconnu, déjà lu, ou AppMint Push non activé). Nécessite : activez AppMint Push à l'étape Intégration (étape 3) lors de la compilation.

function openMessage(id) {
  if (!(window.WebToApk && window.WebToApk.markPushRead)) return;
  WebToApk.markPushRead(id);                 // one message
  updateBellCount();
}

document.getElementById('mark-all-read').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.markPushRead)) return;
  WebToApk.markPushRead('');                 // every message
  updateBellCount();
});

function updateBellCount() {
  const inbox = JSON.parse(WebToApk.getPushInbox() || '[]');
  const unread = inbox.filter(function (m) { return !m.read; }).length;
  document.getElementById('bell-count').textContent = unread ? String(unread) : '';
}

Marquez un message comme lu une fois que l'utilisateur l'a réellement vu à l'écran, pas seulement quand il le touche :

if (window.WebToApk && window.WebToApk.markPushRead) {
  const seen = new IntersectionObserver(function (entries) {
    entries.forEach(function (entry) {
      if (!entry.isIntersecting) return;
      const id = entry.target.dataset.msgId;
      seen.unobserve(entry.target);
      if (WebToApk.markPushRead(id)) {       // true only when it was unread
        entry.target.classList.replace('unread', 'read');
        updateBellCount();
      }
    });
  }, { threshold: 0.6 });

  document.querySelectorAll('#inbox li.unread').forEach(function (li) { seen.observe(li); });
}

Effacez le badge à l'ouverture de l'écran de la boîte de réception, et ne redessinez que lorsqu'un élément était réellement non lu :

function openInboxScreen() {
  showScreen('inbox');
  if (!(window.WebToApk && window.WebToApk.markPushRead)) return;
  const changed = WebToApk.markPushRead('');  // false: nothing was unread
  if (changed) {
    document.getElementById('bell-count').textContent = '';
    renderInbox();
  }
}

Remarques : l'état de lecture est stocké uniquement sur ce téléphone. Il ne supprime pas la notification du panneau de notifications.

restorePushMessage pont#

window.WebToApk.restorePushMessage(id: String): Boolean

Annule un masquage : remet le message à sa place dans la boîte de réception.

Exemple

Annule dismissPushMessage(id) : le message revient dans la boîte de réception push à son ancienne place.

Renvoie : true si le message a été restauré ; false si l'identifiant est inconnu ou s'il n'était pas masqué. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation.

let lastDismissed = null;

function onSwipe(id) {
  if (!(window.WebToApk && window.WebToApk.dismissPushMessage)) return;
  if (WebToApk.dismissPushMessage(id)) {
    lastDismissed = id;
    showUndo();
    renderInbox();
  }
}

document.getElementById('undo-btn').addEventListener('click', function () {
  if (!lastDismissed || !window.WebToApk) return;
  if (WebToApk.restorePushMessage(lastDismissed)) renderInbox();
  lastDismissed = null;
});

Annulez plusieurs balayages d'un coup : mémorisez chaque message masqué sur cet écran et rétablissez-les tous :

const hiddenThisVisit = [];

function hide(id) {
  if (window.WebToApk && WebToApk.dismissPushMessage(id)) {
    hiddenThisVisit.push(id);
    document.getElementById('undo-all').hidden = false;
    renderInbox();
  }
}

document.getElementById('undo-all').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.restorePushMessage)) return;
  hiddenThisVisit.splice(0).forEach(function (id) { WebToApk.restorePushMessage(id); });
  this.hidden = true;
  renderInbox();
});

Proposez une liste « Récemment masqués » à partir de laquelle l'utilisateur pourra restaurer plus tard. getPushInbox() ne renvoie pas les messages masqués : conservez donc vous-même leurs identifiants et titres :

function loadHidden() {
  try { return JSON.parse(localStorage.getItem('hiddenMsgs') || '[]'); } catch (e) { return []; }
}

function renderHidden() {
  const ul = document.getElementById('recently-hidden');
  ul.innerHTML = '';
  loadHidden().forEach(function (h) {
    const li = document.createElement('li');
    li.textContent = h.title + ' ';
    const btn = document.createElement('button');
    btn.textContent = 'Restore';
    btn.onclick = function () {
      WebToApk.restorePushMessage(h.id);     // false: retracted, cleared or already back
      const rest = loadHidden().filter(function (x) { return x.id !== h.id; });
      try { localStorage.setItem('hiddenMsgs', JSON.stringify(rest)); } catch (e) {}
      renderHidden();
      renderInbox();
    };
    li.appendChild(btn);
    ul.appendChild(li);
  });
}

Remarques : un message effacé avec clearPushInbox() ou retiré par vous depuis AppMint ne peut pas être restauré.

setInAppPresentation pont#

window.WebToApk.setInAppPresentation(mode: String): Boolean

Présentation des messages in-app : "auto" (par défaut) laisse l'application dessiner le design du créateur ; "none" (conservé) transmet chaque message à la page comme `appmint:inapp` {type:'shown', presented:false, message} pour qu'elle le dessine elle-même.

Exemple

Choisit qui affiche un message intégré à l'application (une campagne du centre d'envoi AppMint Push) lorsque son déclencheur se produit : l'application ('auto', par défaut : le bandeau, la carte centrée, la feuille inférieure ou le design plein écran du créateur) ou votre propre page ('none').

Retourne : true quand le mode a été enregistré (il reste sur le téléphone jusqu'à modification) ; false pour toute autre valeur et dans une application compilée sans AppMint Push. Nécessite : AppMint Push activé à l'étape Intégration (étape 3) lors de la compilation.

Chaque message intégré à l'application déclenche l'événement appmint:inapp (et appelle window.onAppMintInApp(detail) si vous l'avez défini) avec type 'shown', 'clicked', 'dismissed' ou 'answered' (une réponse par étoiles ou par note de 0 Ă 10, avec question et value):

window.addEventListener('appmint:inapp', function (e) {
  var d = e.detail;   // { type, id, name, template?, presented?, message?, button?, link?, question?, value? }
  if (d.type === 'shown') analytics('inapp_shown', d.name);
  if (d.type === 'clicked') analytics('inapp_clicked', d.name + ' #' + d.button);
  if (d.type === 'dismissed') analytics('inapp_closed', d.name);
  if (d.type === 'answered') analytics('inapp_answer', d.name + ' ' + d.question + '=' + d.value);
});

Affichez vous-même les messages ; l'application vous remet chacun d'eux au lieu de l'afficher :

if (window.WebToApk && WebToApk.setInAppPresentation) WebToApk.setInAppPresentation('none');

window.onAppMintInApp = function (d) {
  if (d.type !== 'shown' || d.presented) return;   // presented = the app already drew it
  var m = d.message;                                // { title, body, imageUrl, link, inapp, accent?, buttons?, emoji?, question?, lines? }
  showMyDialog(m.title, m.body, (m.buttons || []).map(function (b) {
    return { label: b.label, onClick: function () { if (b.link) location.href = b.link; } };
  }));
};

Rendez le choix à l'application (par exemple depuis un interrupteur des paramètres) :

document.getElementById('native-popups').addEventListener('change', function (e) {
  if (window.WebToApk && WebToApk.setInAppPresentation) {
    WebToApk.setInAppPresentation(e.target.checked ? 'auto' : 'none');
  }
});

Remarques : avec 'none', un message compte quand même comme affiché (ses limites de fréquence s'appliquent) dès qu'il est remis à la page. Définir 'none' ferme aussi un message que l'application affiche en ce moment. Les messages push ont leur propre interrupteur, setPushPresentation.

setPushPresentation pont#

window.WebToApk.setPushPresentation(mode: String): Boolean

Présentation native des messages push dans l'application : "auto" (par défaut) laisse la coque afficher le bandeau / la fenêtre modale / la feuille / la carte plein écran choisis par le créateur lorsque l'application est ouverte ; "none" la désactive définitivement (conservé) : pour les applications qui affichent la leur. L'événement `appmint:push` et la boîte de réception ne sont pas affectés dans les deux cas ; l'indicateur `presented` de l'événement reçu indique si la coque l'a affiché.

Exemple

Active ('auto', par défaut) ou désactive ('none') l'affichage à l'écran, par l'application elle-même, des messages AppMint Push - pour les applications qui dessinent leur propre bannière à partir de l'événement appmint:push.

Renvoie : true lorsque le mode a été enregistré ; false pour toute valeur autre que 'auto' ou 'none'. Le choix est enregistré sur le téléphone et reste jusqu'à modification. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation.

Dessinez votre propre bannière à la place de celle de l'application :

if (window.WebToApk && window.WebToApk.setPushPresentation) {
  WebToApk.setPushPresentation('none');       // 'auto' to give it back to the shell
}

window.addEventListener('appmint:push', function (e) {
  const d = e.detail;
  // { type: 'received', message: {...}, presented: false } — presented = the shell already showed it
  if (d.type === 'received' && !d.presented) showMyBanner(d.message.title, d.message.body, d.message.link);
  if (d.type === 'revoked') hideMyBanner(d.id);
});

Laissez l'utilisateur désactiver les fenêtres contextuelles dans votre écran de paramètres. Il n'existe pas de getter : conservez donc votre propre copie du choix pour afficher l'interrupteur :

const toggle = document.getElementById('show-popups');
let saved = null;
try { saved = localStorage.getItem('pushPopups'); } catch (e) {}
toggle.checked = saved !== 'none';

toggle.addEventListener('change', function () {
  if (!(window.WebToApk && window.WebToApk.setPushPresentation)) return;
  const mode = toggle.checked ? 'auto' : 'none';
  if (WebToApk.setPushPresentation(mode)) {
    try { localStorage.setItem('pushPopups', mode); } catch (e) {}
  }
});

Avec 'auto', découvrez ce que l'utilisateur a fait d'un message affiché à l'écran par l'application : opened lorsqu'il l'a touché (action vaut -1 pour le message lui-même, sinon l'index du bouton), closed lorsqu'il l'a fermé sans le toucher :

window.addEventListener('appmint:push', function (e) {
  const d = e.detail;
  if (d.type === 'opened') {
    // the message is already marked read in the inbox
    track('push_opened', { id: d.id, button: d.action, link: d.link });
    updateBellCount();
  } else if (d.type === 'closed') {
    track('push_closed', { id: d.id });
  }
});

Remarques : avec 'auto', un message envoyé avec un style intégré à l'application s'affiche par-dessus l'application tant qu'elle est ouverte (et n'est alors pas aussi placé dans le panneau de notifications). Avec 'none', la coque ne l'affiche jamais ; la boîte de réception (getPushInbox) et l'événement appmint:push fonctionnent de la même façon dans les deux cas. Définir 'none' ferme aussi un message que la coque affiche en ce moment.

setPushTag pont#

window.WebToApk.setPushTag(key: String, value: String): Boolean

Définit un tag AppMint Push (clé : lettres, chiffres, _ jusqu'à 32 ; valeur jusqu'à 128) : le centre d'envoi peut cibler "plan = pro", et une automatisation peut se déclencher un certain temps après la définition d'un tag (panier abandonné : définir cart=open, l'effacer à la validation de la commande). Une valeur vide supprime le tag. Jusqu'à 50 tags par installation.

Exemple

Définit un tag AppMint Push sur cette installation, tel que plan = pro ou city = pune. Le centre d'envoi (Accueil > Notifications) peut envoyer à tous ceux qui ont un tag, et une automatisation par tag peut envoyer un message un certain temps après la définition d'un tag - un panier abandonné, un niveau terminé. Une valeur vide supprime le tag.

Renvoie : true lorsque c'est enregistré ; false lorsque la clé n'est pas composée de 1 à 32 lettres, chiffres ou _, que la valeur dépasse 128 caractères, ou que l'installation aurait plus de 50 tags (rien n'est alors enregistré). Les tags sont conservés sur le téléphone et transmis à AppMint Push un instant plus tard (ou au prochain lancement hors ligne). Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation. Le ciblage par tag et les automatisations atteignent les téléphones exécutant une application compilée avec AppMint à partir du 30 sept. 2026.

Taguez ce que l'utilisateur a acheté ou choisi, afin de pouvoir envoyer uniquement à "plan = pro" :

function pushTag(key, value) {
  if (!(window.WebToApk && window.WebToApk.setPushTag)) return false;
  return WebToApk.setPushTag(key, value);
}

pushTag('plan', user.isPro ? 'pro' : 'free');
pushTag('city', user.city.toLowerCase());

Panier abandonné : définissez un tag lorsque des articles sont dans le panier et effacez-le à la validation de la commande. Dans le centre d'envoi, ajoutez une automatisation par tag sur cart avec un délai (disons 60 minutes) ; un téléphone ne reçoit le rappel que si cart est toujours défini à l'échéance :

function onCartChanged(items) {
  if (!(window.WebToApk && window.WebToApk.setPushTag)) return;
  // Setting 'open' again while it is already 'open' does not restart the automation's clock.
  WebToApk.setPushTag('cart', items.length > 0 ? 'open' : '');
}

function onCheckoutComplete() {
  if (window.WebToApk && window.WebToApk.setPushTag) WebToApk.setPushTag('cart', '');   // bought: no reminder
}

Effacez les tags propres à l'utilisateur à la déconnexion, avec l'id utilisateur :

function signOutOfPush() {
  if (!(window.WebToApk && window.WebToApk.setPushUser)) return;
  WebToApk.setPushUser('');
  WebToApk.setPushTag('plan', '');
  WebToApk.setPushTag('cart', '');
}

Remarques : les tags appartiennent à cette installation, pas à l'utilisateur connecté. Définir un tag sur la valeur qu'il a déjà ne change rien sur le serveur. Après la suppression d'un tag, le définir de nouveau permet à une automatisation par tag d'envoyer à nouveau un message. Ne mettez jamais d'adresse e-mail, de numéro de téléphone ou quoi que ce soit de privé dans un tag.

setPushTags pont#

window.WebToApk.setPushTags(json: String): Boolean

Définit plusieurs tags à la fois à partir d'une chaîne d'objet JSON ; les valeurs "" suppriment.

Exemple

Définit plusieurs tags AppMint Push à la fois à partir d'une chaîne d'objet JSON, par ex. '{"plan":"pro","team":"red"}'. Une valeur "" supprime ce tag ; les tags que vous ne nommez pas sont conservés.

Renvoie : true lorsque c'est enregistré ; false lorsque la chaîne n'est pas un objet JSON, qu'une clé n'est pas composée de 1 à 32 lettres, chiffres ou _, qu'une valeur dépasse 128 caractères, ou que l'installation finirait avec plus de 50 tags : rien n'est alors enregistré du tout. Nécessite : activer AppMint Push à l'étape Intégrer (étape 3) lors de la compilation. Le ciblage par tag et les automatisations atteignent les téléphones exécutant une application compilée avec AppMint à partir du 30 sept. 2026.

Après la connexion, taguez le profil en un seul appel :

function tagProfile(profile) {
  if (!(window.WebToApk && window.WebToApk.setPushTags)) return false;
  return WebToApk.setPushTags(JSON.stringify({
    plan: profile.plan,                   // 'free' | 'pro'
    level: String(profile.level),         // values are text: turn numbers into strings
    team: profile.team || ''              // '' removes the tag
  }));
}

À la déconnexion, supprimez-les tous (lisez les tags actuels, renvoyez chacun avec ''):

function clearPushTags() {
  if (!(window.WebToApk && window.WebToApk.getPushTags)) return;
  const tags = JSON.parse(WebToApk.getPushTags() || '{}');
  Object.keys(tags).forEach(function (k) { tags[k] = ''; });
  WebToApk.setPushTags(JSON.stringify(tags));
  WebToApk.setPushUser('');
}

Niveau terminé : taguez-le, et laissez une automatisation par tag sur level_done (disons 10 minutes) envoyer le défi suivant :

function onLevelComplete(level, score) {
  if (!(window.WebToApk && window.WebToApk.setPushTags)) return;
  WebToApk.setPushTags(JSON.stringify({
    level_done: String(level),            // a new value each level, so the automation can fire again
    last_score: String(score)
  }));
}

Remarques : un appel correspond à une modification : tout est enregistré ou rien. L'installation transmet les nouveaux tags à AppMint Push un instant plus tard (ou au prochain lancement hors ligne).

setPushUser pont#

window.WebToApk.setPushUser(id: String): Boolean

Audience AppMint Push : indique au centre d'envoi du créateur QUI est cette installation, afin qu'un message puisse être envoyé à un seul utilisateur connecté ("u_42") ou à tous ceux qui ont un tag. Appelez-la après la connexion avec votre propre identifiant de compte stable ; passez "" à la déconnexion. Lettres, chiffres et _ @ . : + - (jusqu'à 128). Renvoie false pour tout autre contenu, et dans une application qui n'utilise pas AppMint Push (OneSignal / Firebase personnel : rien n'est envoyé, 2026-10-03). Ne transmettez jamais d'adresse e-mail ni de numéro de téléphone : utilisez l'identifiant de votre base de données.

Exemple

Indique à AppMint Push lequel de VOS utilisateurs est connecté sur ce téléphone, afin que le centre d'envoi (Accueil > Notifications) puisse envoyer un message à cet utilisateur précis. Appelez-la après la connexion avec votre propre identifiant de compte stable ; appelez-la avec '' à la déconnexion.

Retourne : true quand l'id a été enregistré ; false pour un id contenant autre chose que des lettres, des chiffres et _ @ . : + -, ou de plus de 128 caractères (rien n'est alors enregistré). L'id est conservé sur le téléphone jusqu'à ce que vous le changiez, et cette installation le signale à AppMint Push un instant plus tard (ou au prochain lancement si elle est hors ligne). Nécessite : activez AppMint Push à l'étape Intégration (étape 3) lors de la compilation. L'envoi à un utilisateur atteint les téléphones exécutant une application compilée avec AppMint à partir du 30 sept. 2026 ; les anciennes compilations reçoivent toujours les messages envoyés à Tout le monde.

Après la connexion et à la déconnexion : utilisez l'identifiant de votre base de données, jamais une adresse e-mail ni un numéro de téléphone :

function pushUser(id) {
  if (!(window.WebToApk && window.WebToApk.setPushUser)) return false;   // browser, or an older build
  return WebToApk.setPushUser(id);
}

async function signIn(email, password) {
  const user = await myBackend.signIn(email, password);   // your own sign-in
  pushUser(user.id);                                      // e.g. 'u_42' or a UUID
}

async function signOut() {
  await myBackend.signOut();
  pushUser('');                                           // this phone is nobody's now
}

Supabase : suivez la session, afin qu'une session restaurée compte autant qu'une nouvelle connexion :

supabase.auth.onAuthStateChange(function (event, session) {
  if (!(window.WebToApk && window.WebToApk.setPushUser)) return;
  const id = session ? session.user.id : '';     // the auth UUID: letters, digits and '-'
  if (WebToApk.getPushUser() !== id) WebToApk.setPushUser(id);
});

Rendez un identifiant acceptable lorsque le vôtre peut contenir d'autres caractères (espaces, /, #), et journalisez le rare cas qui est tout de même refusé :

function pushUserIdFrom(rawId) {
  return String(rawId).trim().replace(/[^A-Za-z0-9_@.:+\-]/g, '_').slice(0, 128);
}

if (window.WebToApk && window.WebToApk.setPushUser) {
  const ok = WebToApk.setPushUser(pushUserIdFrom(currentUser.id));
  if (!ok) console.warn('push user id refused', currentUser.id);
}

Remarques : un même utilisateur connecté sur deux téléphones est joint sur les deux. L'identifiant appartient à cette installation, pas au compte : la déconnexion doit l'effacer, sinon le téléphone continue de recevoir les messages de l'utilisateur précédent. setPushUser('') n'efface pas les tags définis avec setPushTag ; effacez aussi les tags propres à l'utilisateur à la déconnexion.

trackEvent pont#

window.WebToApk.trackEvent(name: String, propsJson: String): Boolean

Messages in-app : signale un événement sur lequel les campagnes du créateur peuvent se déclencher (déclencheur « event », même nom). propsJson est du JSON facultatif. Le nom `appmint:route` avec {"path":"/x"} signale un changement de vue que l'URL ne montre pas. False pour un nom hors de [A-Za-z0-9_.:-]{1,64}, et sans AppMint Push.

Exemple

Indique à l'application qu'un événement s'est produit ("signed_up", "checkout_done", "level:3"). Un message intégré à l'application créé par le créateur dans le centre d'envoi AppMint Push avec le déclencheur « Lorsqu'un événement se produit » et le même nom s'affiche alors (ou après le délai choisi par le créateur).

Retourne : true quand l'événement a été pris en compte ; false pour un nom hors lettres, chiffres et _ . : - (jusqu'à 64), et dans une application compilée sans AppMint Push. AppMint.trackEvent(name, props) est le même appel avec props sous forme d'objet. Nécessite : AppMint Push activé à l'étape Intégration (étape 3) lors de la compilation. propsJson est facultatif ('') et n'est pas conservé.

// After a purchase: the creator's "Thanks, rate us?" message is set to trigger on "purchase_done".
function onPurchaseDone(order) {
  if (window.AppMint && AppMint.trackEvent) {
    AppMint.trackEvent('purchase_done', { total: order.total });
  }
}

Le pont brut prend les propriétés sous forme de chaîne JSON (passez '' s'il n'y en a aucune) :

function track(name, props) {
  if (!(window.WebToApk && window.WebToApk.trackEvent)) return false;   // a browser: nothing to show
  return WebToApk.trackEvent(name, props ? JSON.stringify(props) : '');
}
track('level:3');
track('tutorial_skipped', { step: 2 });

Un changement d'écran que l'adresse ne montre pas (onglets, assistant, « page » modale) peut être signalé comme une route, afin que les messages « Sur une page » du créateur le voient. La page peut aussi envoyer l'événement appmint:route avec le chemin ; l'application l'écoute :

function showTab(name) {
  document.querySelectorAll('.tab').forEach(function (t) { t.hidden = t.id !== name; });
  if (window.AppMint && AppMint.trackEvent) AppMint.trackEvent('appmint:route', { path: '/' + name });
}

// Same thing, without touching the bridge at all:
window.dispatchEvent(new CustomEvent('appmint:route', { detail: { path: '/cart' } }));

Remarques : les messages par route suivent déjà d'eux-mêmes les vrais changements d'URL (chargements de page, routes history.pushState, #/hash) ; ne signalez une route que pour les vues dont l'adresse ne change pas. Les événements ne sont ni comptés ni stockés nulle part ; ils décident seulement si un message s'affiche.

Généré à partir de l'environnement d'exécution de l'application et de ses fichiers d'exemple à chaque compilation de la documentation. Lire en Markdown · Toutes les familles.

Vérifié par rapport au pont publié le 22/10/2026.