Autocomplete de moradas no Shopify
O checkout do Shopify não aceita scripts do tema. Sugestões de morada e CP7 exato no checkout só com uma app, e só em lojas Shopify Plus. Nas páginas do tema — formulário de contacto, páginas personalizadas — o widget funciona em qualquer plano.
Funciona no checkout: Com app (só Shopify Plus)
O checkout do Shopify não executa código do tema nem scripts adicionais nos passos de informação, envio e pagamento. A única via para sugestões de morada é uma Checkout UI extension com o alvo purchase.address-autocomplete.suggest, e essas extensões só estão disponíveis em lojas no plano Shopify Plus. O autocomplete nativo do Shopify não cobre Portugal.
Para que serve o widget no Shopify: formulários nas páginas do tema (contacto, pedido de orçamento, páginas personalizadas), em qualquer plano. No checkout, não.
Não testado numa loja real: o esboço abaixo segue a documentação do Shopify de 2 de outubro de 2026. Não existe, hoje, uma app Moradas na Shopify App Store.
O que o Shopify permite, por plano
| Onde | Plano | Como |
|---|---|---|
| Checkout: morada de envio e de faturação | Shopify Plus | App com Checkout UI extension (alvo purchase.address-autocomplete.suggest), escolhida pelo lojista em Settings › Checkout › Address autocompletion |
| Checkout | Outros planos | Não há forma documentada de acrescentar scripts nem um fornecedor de autocomplete |
| Páginas do tema: contacto, páginas personalizadas | Todos | Widget no código do tema (Online Store › Themes › Edit code) |
Shopify Plus: app com Checkout UI extension
Um programador cria a app com o Shopify CLI e gera uma extensão de checkout (shopify app generate extension --template checkout_ui). No shopify.extension.toml, o alvo é purchase.address-autocomplete.suggest e o acesso à rede fica ligado, porque a extensão chama a API do Moradas:
[[extensions.targeting]] module = "./src/suggest.js" target = "purchase.address-autocomplete.suggest" [extensions.capabilities] network_access = true
A extensão recebe o texto escrito (value), o campo (field) e o país escolhido (selectedCountryCode) e devolve até cinco sugestões. A função abaixo converte a resposta de /suggest do Moradas no formato que o Shopify espera (id, label, matchedSubstrings, formattedAddress). A assinatura da função de extensão e a forma de obter o signal dependem da api_version: siga a documentação do Shopify.
// Moradas /suggest → Shopify address suggestions (max. 5)
async function suggestPT(value, selectedCountryCode, signal) {
const q = (value || '').trim();
if (selectedCountryCode !== 'PT' || q.length < 2) return [];
const r = await fetch('https://moradas.dev/suggest?q=' + encodeURIComponent(q) + '&count=5', { signal });
if (!r.ok) return [];
const { suggestions } = await r.json();
return (suggestions || []).slice(0, 5).map((s, i) => {
const d = s.data;
const street = d.street ? (d.numero ? d.street + ' ' + d.numero : d.street) : '';
const label = d.numero ? s.value.split(',')[0] + ' ' + d.numero + ', ' + d.localidade : s.value;
return {
id: String(d.art_id || i),
label: label,
matchedSubstrings: matched(label, q),
formattedAddress: { address1: street, city: d.localidade, zip: d.cp7 || '', provinceCode: '', countryCode: 'PT' }
};
});
}
// ranges of the typed words inside the label, for highlighting
function matched(label, q) {
const low = label.toLowerCase(), out = [];
q.toLowerCase().split(/\s+/).forEach((w) => {
const i = w.length > 1 ? low.indexOf(w) : -1;
if (i >= 0) out.push({ offset: i, length: w.length });
});
return out;
}
- Numa rua com vários códigos postais, a sugestão vem sem CP7 até o cliente escrever o número de porta na pesquisa (por exemplo «av liberdade lisboa 196»); aí o
zipchega preenchido. - Depois do
shopify app deploy, o lojista escolhe a app em Settings › Checkout, secção Address autocompletion, e testa com uma morada portuguesa. - A app precisa de acesso à rede aprovado e de acesso a dados protegidos de clientes, ambos pedidos no Partner Dashboard; a documentação do Shopify lista os requisitos de privacidade e segurança.
Qualquer plano: o widget nas páginas do tema
Formulários que vivem no tema — contacto, pedido de orçamento, registo de morada para entregas — aceitam o widget como qualquer página HTML. Em Online Store › Themes › Edit code, carregue o script no template ou na secção da página e ligue-o ao campo da morada. Os ids são os dos seus campos, e o código tem de correr depois de os campos existirem (no fim do template):
<script src="https://moradas.dev/widget.js"></script>
<script>
PTAddress.attach(document.querySelector('#ContactForm-morada'), {
fill: { postal: '#ContactForm-cp7', city: '#ContactForm-localidade' }
});
</script>
O que o widget faz
O widget.js carrega-se com uma linha e liga-se ao campo da morada com PTAddress.attach. Enquanto o cliente escreve aparecem sugestões de ruas e localidades portuguesas; ao escolher, os campos indicados em fill recebem o código postal, a localidade, o concelho e o distrito. Numa rua com vários códigos postais, o CP7 exato chega com o número de porta. Se o serviço não responder, o formulário continua a funcionar como antes. Todas as opções — endpoint, fill, onSelect, onResolve, lang, beacon — estão na documentação do widget.
Porque é que o CP7 exato importa
Em Portugal uma rua pode ter vários códigos postais, por troços e pela paridade dos números. Na Avenida da Liberdade, em Lisboa, o n.º 196 tem o código 1250-147, e os números ímpares de 1 a 57 têm o 1250-139. Uma gralha no código postal pode mandar a encomenda para a morada errada.
E os dados dos clientes?
O Moradas não usa cookies e não guarda o texto pesquisado — só contagens agregadas de utilização e, se o beacon ficar ligado, um relatório mínimo quando o serviço falha. Pode remeter para a página de privacidade na política da sua loja.