API da ponte JavaScript
A caixa de entrada de push e o público
Mensagens que o criador enviou de um painel, mantidas no dispositivo para que a página possa mostrar um histórico e não apenas um pop-up na bandeja - além do ID de usuário conectado e das tags que permitem à central de envio segmentar um usuário ou uma tag e disparar automações, como um lembrete de carrinho abandonado.
AppMint.trackEvent helper#
window.AppMint.trackEvent
Exemplo
Documentado junto com WebToApk.trackEvent - o exemplo de lá mostra este também.
Informa ao app que algo aconteceu ("signed_up", "checkout_done", "level:3"). Uma mensagem no app criada pelo criador na central de envio do AppMint Push com o gatilho "Quando um evento acontece" e o mesmo nome aparece agora (ou após a espera escolhida pelo criador).
Retorna: true quando o evento foi aceito; false para um nome fora de letras, dígitos e _ . : - (até 64), e em um app compilado sem o AppMint Push. AppMint.trackEvent(name, props) é a mesma chamada com props como objeto. Requer: AppMint Push ativado na etapa Integrar (Etapa 3) ao compilar. propsJson é opcional ('') e não é armazenado.
// 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 });
}
}A ponte bruta recebe as props como uma string JSON (passe '' para nenhuma):
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 });Uma mudança de tela que o endereço não mostra (abas, um assistente, uma "página" modal) pode ser informada como uma rota, para que as mensagens "Em uma página" do criador a vejam. A página também pode disparar o evento appmint:route com o caminho; o app o escuta:
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' } }));Observações: as mensagens por rota já acompanham mudanças reais de URL (carregamentos de página, rotas history.pushState, #/hash) por conta própria; informe uma rota apenas para telas em que o endereço não muda. Os eventos não são contados nem armazenados em lugar nenhum; eles só decidem se uma mensagem aparece.
clearPushInbox ponte#
window.WebToApk.clearPushInbox(): Boolean
Esvazia a caixa de entrada de push (a bandeja e o histórico do servidor não são alterados).
Exemplo
Esvazia a caixa de entrada de push neste celular.
Retorna: true quando concluído; false em um erro interno. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
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();
});Esvazie a caixa de entrada quando o usuário sair, para que a próxima pessoa neste celular não veja as mensagens dele:
async function signOut() {
await myAuth.signOut();
if (window.WebToApk && window.WebToApk.clearPushInbox) {
WebToApk.clearPushInbox();
}
document.getElementById('bell-count').textContent = '';
showLoginScreen();
}Mostre uma linha de configurações com quantas mensagens estão armazenadas, desativada quando não há nada para excluir:
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();Observações: isto é permanente — ao contrário de dismissPushMessage, não há desfazer. As notificações da bandeja e seu histórico de envios no AppMint não são afetados. Novas mensagens continuam chegando.
dismissPushMessage ponte#
window.WebToApk.dismissPushMessage(id: String): Boolean
Dispensa UMA mensagem da caixa de entrada - o deslizar por linha de que uma tela de caixa de entrada precisa (clearPushInbox é tudo ou nada). REVERSÍVEL por design: a entrada é ocultada, não destruída, então a interface pode oferecer "Desfazer" por alguns segundos após o deslize. Apenas local: a notificação da bandeja e o histórico do criador não são alterados.
Exemplo
Oculta uma mensagem da caixa de entrada de push (deslizar para dispensar). Pode ser desfeito com restorePushMessage(id).
Retorna: true se a mensagem foi ocultada; false se o id é desconhecido ou ela já estava oculta. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
Deslize para dispensar com Desfazer de 5 segundos:
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();
};
}Arrume a caixa de entrada quando ela abrir, ocultando mensagens lidas com mais de 30 dias:
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();Dispense uma linha com um deslize real do dedo (arraste mais de 40% da largura dela):
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
}
});
}Observações: apenas a caixa de entrada deste celular muda. A notificação da bandeja e o seu histórico de envios no AppMint permanecem. Mensagens ocultas não são retornadas por getPushInbox().
getInAppCampaigns ponte#
window.WebToApk.getInAppCampaigns(): String
Mensagens no app que esta instalação possui: JSON [{id, name}] ("[]" sem o AppMint Push).
Exemplo
Lista as mensagens no app que esta instalação mantém agora (as campanhas do criador, da central de envio do AppMint Push, para as quais este usuário está no público) como uma string JSON [{"id": "...", "name": "..."}].
Retorna: uma string de array JSON; "[]" quando não há nenhuma e em um app compilado sem o AppMint Push. Requer: AppMint Push ativado na etapa Integrar (Etapa 3) ao compilar. A lista é atualizada a cada início do app (e a cada hora, mais ou menos, em primeiro plano).
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; }));Mostre uma lista de depuração na sua própria tela de administração:
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'));Pule a sua própria dica de boas-vindas quando o criador já tiver uma mensagem em execução com esse nome:
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();Observações: apenas o id e o nome são expostos; a mensagem em si chega à página pelo evento appmint:inapp quando é exibida (veja setInAppPresentation).
getPushInbox ponte#
window.WebToApk.getPushInbox(): String
Caixa de entrada do AppMint Push (mensagens enviadas pelo criador, mais recentes primeiro, máx. 50): array JSON de {id, title, body, imageUrl, link, receivedAt, read}. Sempre a verdade atual completa — um app que monta tarde não perde nada por ter perdido os eventos `appmint:push` ao vivo.
Exemplo
Lê a caixa de entrada no app das mensagens de push que você enviou com o AppMint Push: mais recentes primeiro, até 50, sem as que o usuário dispensou.
Retorna: uma string JSON, de forma síncrona. Faça o parse. Cada item: { id, title, body, imageUrl, link, receivedAt, read } (receivedAt em epoch ms; imageUrl e link são '' quando a mensagem não tem), mais campos opcionais de design quando você usou um modelo no AppMint: template, accent, iconUrl, buttons: [{label, link}], badge, inapp, countdownAt, progress, lines, collapse. '[]' quando vazio. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar; sem isso a caixa de entrada fica sempre vazia.
Renderize a caixa de entrada e atualize-a ao vivo com 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();Atualize a contagem de não lidas no seu sininho sempre que o usuário voltar ao app (as mensagens que chegaram enquanto ele estava em segundo plano já estão na caixa de entrada):
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();Mostre a imagem de uma mensagem e seus botões (somente quando você a criou com eles), junto com o horário em que chegou:
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)); });
}Observações: a caixa de entrada fica no celular, então leia-a quando sua tela abrir - os eventos só chegam enquanto o app está na tela. Uma mensagem que você retirar do AppMint some da caixa de entrada e da bandeja. Mensagens enviadas como "somente push" (bandeja) não são adicionadas à caixa de entrada. O mesmo detalhe também é passado a window.onAppMintPush(detail) se você o definir.
getPushTags ponte#
window.WebToApk.getPushTags(): String
As tags desta instalação como uma string de objeto JSON, por exemplo {"plan":"pro"}.
Exemplo
Lê as tags do AppMint Push desta instalação.
Retorna: uma string JSON, de forma síncrona - um objeto de valores de texto, por exemplo '{"plan":"pro","cart":"open"}'; '{}' quando não há nenhuma. Faça o parse. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
Leia uma tag:
function pushTags() {
if (!(window.WebToApk && window.WebToApk.getPushTags)) return {};
try { return JSON.parse(WebToApk.getPushTags() || '{}'); } catch (e) { return {}; }
}
const plan = pushTags().plan || 'free';Defina uma tag apenas quando ela mudar — cada chamada de setPushTag faz a instalação se comunicar com o AppMint Push, então pule as que não mudam nada:
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');Liste-as em uma tela de depuração enquanto você testa o envio para uma 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';
}Observações: isto é o que o celular guarda; a central de envio vê isso após a próxima verificação da instalação, poucos segundos depois de uma mudança quando o celular está online.
getPushUser ponte#
window.WebToApk.getPushUser(): String
O último ID de usuário definido com setPushUser ("" quando desconectado ou nunca definido).
Exemplo
Lê o ID de usuário que esta instalação informou por último ao AppMint Push com setPushUser.
Retorna: uma string, de forma síncrona - o ID salvo, ou '' quando ninguém está conectado ou nunca foi definido. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
Defina o ID somente quando ele mudou (a cada inicialização do app):
function syncPushUser(currentUserId) {
if (!(window.WebToApk && window.WebToApk.getPushUser)) return;
const want = currentUserId || '';
if (WebToApk.getPushUser() !== want) WebToApk.setPushUser(want);
}
syncPushUser(localStorage.getItem('userId'));Limpe um ID obsoleto quando a sua própria sessão expirou com o app fechado:
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();Mostre-o em uma tela de depuração enquanto testa o envio para um usuário:
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';
}Observações: isto é o que o celular guarda. A central de envio vê uma mudança após a próxima verificação da instalação, poucos segundos depois quando o celular está online.
markPushRead ponte#
window.WebToApk.markPushRead(id: String): Boolean
Marca uma mensagem de push como lida; passe "" para marcar todas as mensagens como lidas.
Exemplo
Marca uma mensagem da caixa de entrada de push como lida, ou todas elas quando você passa ''.
Retorna: true se uma mensagem mudou; false se nada mudou (id desconhecido, já lida, ou AppMint Push não ativado). Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
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) : '';
}Marque uma mensagem como lida quando o usuário realmente a tiver visto na tela, não apenas quando a tocar:
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); });
}Limpe o selo quando a tela da caixa de entrada abrir, e só redesenhe quando algo realmente não estava lido:
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();
}
}Observações: o estado de leitura fica salvo apenas neste celular. Ele não remove a notificação da bandeja.
restorePushMessage ponte#
window.WebToApk.restorePushMessage(id: String): Boolean
Desfaz uma dispensa: coloca a mensagem de volta no seu lugar na caixa de entrada.
Exemplo
Desfaz dismissPushMessage(id): a mensagem volta para a caixa de entrada de push no mesmo lugar de antes.
Retorna: true se a mensagem foi restaurada; false se o ID é desconhecido ou ela não estava oculta. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
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;
});Desfaça vários deslizes de uma vez: lembre cada mensagem ocultada nesta tela e traga todas de volta:
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();
});Ofereça uma lista "Ocultadas recentemente" da qual o usuário possa restaurar depois. getPushInbox() não retorna mensagens ocultas, então guarde você mesmo os IDs e títulos delas:
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);
});
}Observações: uma mensagem limpa com clearPushInbox() ou retirada por você no AppMint não pode ser restaurada.
setInAppPresentation ponte#
window.WebToApk.setInAppPresentation(mode: String): Boolean
Apresentação da mensagem no app: "auto" (padrão) deixa o shell desenhar o design do criador; "none" (persistido) entrega cada mensagem à página como `appmint:inapp` {type:'shown', presented:false, message} para ela mesma desenhar.
Exemplo
Escolhe quem desenha uma mensagem no app (uma campanha da central de envio do AppMint Push) quando o gatilho acontece: o app ('auto', o padrão: o banner, cartão central, painel inferior ou design em tela cheia do criador) ou a sua própria página ('none').
Retorna: true quando o modo foi salvo (ele fica no celular até ser mudado); false para qualquer outro valor e em um app compilado sem o AppMint Push. Requer: AppMint Push ativado na etapa Integrar (Etapa 3) ao compilar.
Toda mensagem no app dispara o evento appmint:inapp (e chama window.onAppMintInApp(detail) se você o definiu) com type 'shown', 'clicked', 'dismissed' ou 'answered' (uma resposta de estrelas ou nota de 0 a 10, com question e 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);
});Desenhe você mesmo as mensagens; o app entrega cada uma em vez de exibi-la:
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; } };
}));
};Devolva a escolha ao app (por exemplo, a partir de um interruptor nas configurações):
document.getElementById('native-popups').addEventListener('change', function (e) {
if (window.WebToApk && WebToApk.setInAppPresentation) {
WebToApk.setInAppPresentation(e.target.checked ? 'auto' : 'none');
}
});Observações: com 'none', uma mensagem ainda conta como exibida (valem os limites de frequência) no momento em que é entregue à página. Definir 'none' também fecha uma mensagem que o app esteja exibindo agora. As mensagens de push têm seu próprio interruptor, setPushPresentation.
setPushPresentation ponte#
window.WebToApk.setPushPresentation(mode: String): Boolean
Apresentação nativa no app das mensagens de push: "auto" (padrão) deixa o shell desenhar o banner / modal / painel / cartão em tela cheia que o criador escolheu enquanto o app está aberto; "none" desativa de vez (persistente) - para apps que desenham os seus próprios. O evento `appmint:push` e a caixa de entrada não são afetados nos dois casos; o sinalizador `presented` do evento recebido informa se o shell o exibiu.
Exemplo
Liga ('auto', o padrão) ou desliga ('none') a exibição na tela, feita pelo próprio app, das mensagens do AppMint Push — para apps que desenham o próprio banner a partir do evento appmint:push.
Retorna: true quando o modo foi salvo; false para qualquer valor diferente de 'auto' ou 'none'. A escolha é salva no celular e permanece até ser alterada. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar.
Desenhe seu próprio banner em vez do banner do shell:
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);
});Deixe o usuário desativar os pop-ups na sua tela de configurações. Não há um getter, então guarde sua própria cópia da escolha para desenhar o interruptor:
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) {}
}
});Com 'auto', descubra o que o usuário fez com uma mensagem que o app mostrou na tela: opened quando tocou nela (action é -1 para a própria mensagem, senão o índice do botão), closed quando dispensou sem tocar:
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 });
}
});Observações: com 'auto', uma mensagem enviada com estilo no app é exibida sobre o app enquanto ele está aberto (e então não vai também para a bandeja). Com 'none', o shell nunca a desenha; a caixa de entrada (getPushInbox) e o evento appmint:push funcionam igual nos dois casos. Definir 'none' também fecha uma mensagem que o shell esteja exibindo agora.
setPushTag ponte#
window.WebToApk.setPushTag(key: String, value: String): Boolean
Define uma tag do AppMint Push (chave: letras, dígitos, _ até 32; valor até 128) - a central de envio pode segmentar "plan = pro", e uma automação pode disparar um tempo definido depois que uma tag é definida (um carrinho abandonado: defina cart=open e limpe no checkout). Um valor vazio remove a tag. Até 50 tags por instalação.
Exemplo
Define uma tag do AppMint Push nesta instalação, como plan = pro ou city = pune. A central de envio (Início > Notificações) pode enviar para todos que têm uma tag, e uma automação de tag pode enviar uma mensagem um tempo depois que uma tag é definida — um carrinho abandonado, uma fase concluída. Um valor vazio remove a tag.
Retorna: true quando salva; false quando a chave não tem de 1 a 32 letras, dígitos ou _, o valor tem mais de 128 caracteres, ou a instalação passaria a ter mais de 50 tags (nada é salvo nesse caso). As tags ficam no celular e são informadas ao AppMint Push um instante depois (ou na próxima abertura, se estiver offline). Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar. A segmentação por tags e as automações alcançam celulares com um app criado com o AppMint a partir de 30/09/2026.
Marque o que o usuário comprou ou escolheu, para poder enviar apenas a "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());Carrinho abandonado: defina uma tag quando houver itens no carrinho e limpe-a no checkout. Na central de envio, adicione uma automação de tag em cart com um atraso (digamos 60 minutos); um celular só recebe o lembrete se cart ainda estiver definida quando o tempo acabar:
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
}Limpe as tags específicas do usuário ao sair da conta, junto com o id do usuário:
function signOutOfPush() {
if (!(window.WebToApk && window.WebToApk.setPushUser)) return;
WebToApk.setPushUser('');
WebToApk.setPushTag('plan', '');
WebToApk.setPushTag('cart', '');
}Observações: as tags pertencem a esta instalação, não ao usuário conectado. Definir uma tag com o valor que ela já tem não muda nada no servidor. Depois que uma tag é removida, defini-la de novo permite que uma automação de tag envie mais uma vez. Nunca coloque e-mail, telefone ou qualquer dado privado em uma tag.
setPushTags ponte#
window.WebToApk.setPushTags(json: String): Boolean
Define várias tags de uma vez a partir de uma string de objeto JSON; valores "" removem.
Exemplo
Define várias tags do AppMint Push de uma vez a partir de uma string de objeto JSON, por exemplo '{"plan":"pro","team":"red"}'. Um valor "" remove essa tag; as tags que você não citar são mantidas.
Retorna: true quando salvo; false quando a string não é um objeto JSON, alguma chave não tem de 1 a 32 letras, dígitos ou _, algum valor tem mais de 128 caracteres, ou a instalação passaria a ter mais de 50 tags - nesse caso nada é salvo. Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar. A segmentação por tags e as automações alcançam celulares com um app criado com o AppMint a partir de 30/09/2026.
Após o login, marque o perfil com tags em uma única chamada:
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
}));
}Ao sair, remova todas (leia as tags atuais, envie cada uma de volta como ''):
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('');
}Terminou uma fase: marque com uma tag e deixe uma automação de tag em level_done (digamos 10 minutos) enviar o próximo desafio:
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)
}));
}Observações: uma chamada é uma mudança: tudo é salvo ou nada é salvo. A instalação informa as novas tags ao AppMint Push um instante depois (ou na próxima abertura, se estiver offline).
setPushUser ponte#
window.WebToApk.setPushUser(id: String): Boolean
Audiência do AppMint Push: informa à central de envio do criador QUEM é esta instalação, para que uma mensagem possa ir a um único usuário conectado ("u_42") ou a todos com uma tag. Chame após o login com o ID estável da sua própria conta; passe "" ao sair. Letras, dígitos e _ @ . : + - (até 128). Retorna false para qualquer outra coisa, e em um app que não usa o AppMint Push (OneSignal / Firebase próprio: nada é enviado, 03/10/2026). Nunca passe um e-mail ou número de telefone - use o ID do seu banco de dados.
Exemplo
Informa ao AppMint Push qual dos SEUS usuários está conectado neste celular, para que a central de envio (Início > Notificações) possa enviar uma mensagem a esse usuário. Chame após o login com o ID estável da sua própria conta; chame com '' ao sair.
Retorna: true quando o id foi salvo; false para um id com qualquer coisa além de letras, dígitos e _ @ . : + -, ou com mais de 128 caracteres (nada é salvo nesse caso). O id fica no celular até você mudá-lo, e esta instalação o informa ao AppMint Push um instante depois (ou na próxima abertura quando estiver offline). Requer: ative o AppMint Push na etapa Integrar (Etapa 3) ao compilar. Enviar para um usuário alcança celulares com um app criado com o AppMint a partir de 30 Sep 2026; builds mais antigas ainda recebem mensagens enviadas para Todos.
Após o login e ao sair - use o ID do seu banco de dados, nunca um e-mail ou número de telefone:
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: acompanhe a sessão, para que uma sessão restaurada conte tanto quanto um novo login:
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);
});Torne um ID aceitável quando o seu puder conter outros caracteres (espaços, /, #), e registre em log o raro que ainda for recusado:
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);
}Observações: o mesmo usuário conectado em dois celulares é alcançado nos dois. O ID pertence a esta instalação, não à conta - o logout deve limpá-lo, ou o celular continua recebendo as mensagens do usuário anterior. setPushUser('') não limpa as tags definidas com setPushTag; limpe também as tags específicas do usuário ao sair.
trackEvent ponte#
window.WebToApk.trackEvent(name: String, propsJson: String): Boolean
Mensagens no app: informa um evento em que as campanhas do criador podem se basear (gatilho "event", mesmo nome). propsJson é um JSON opcional. O nome `appmint:route` com {"path":"/x"} informa uma mudança de visualização que a URL não mostra. False para um nome fora de [A-Za-z0-9_.:-]{1,64} e sem o AppMint Push.
Exemplo
Informa ao app que algo aconteceu ("signed_up", "checkout_done", "level:3"). Uma mensagem no app criada pelo criador na central de envio do AppMint Push com o gatilho "Quando um evento acontece" e o mesmo nome aparece agora (ou após a espera escolhida pelo criador).
Retorna: true quando o evento foi aceito; false para um nome fora de letras, dígitos e _ . : - (até 64), e em um app compilado sem o AppMint Push. AppMint.trackEvent(name, props) é a mesma chamada com props como objeto. Requer: AppMint Push ativado na etapa Integrar (Etapa 3) ao compilar. propsJson é opcional ('') e não é armazenado.
// 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 });
}
}A ponte bruta recebe as props como uma string JSON (passe '' para nenhuma):
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 });Uma mudança de tela que o endereço não mostra (abas, um assistente, uma "página" modal) pode ser informada como uma rota, para que as mensagens "Em uma página" do criador a vejam. A página também pode disparar o evento appmint:route com o caminho; o app o escuta:
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' } }));Observações: as mensagens por rota já acompanham mudanças reais de URL (carregamentos de página, rotas history.pushState, #/hash) por conta própria; informe uma rota apenas para telas em que o endereço não muda. Os eventos não são contados nem armazenados em lugar nenhum; eles só decidem se uma mensagem aparece.