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

OndePlanoComo
Checkout: morada de envio e de faturaçãoShopify PlusApp com Checkout UI extension (alvo purchase.address-autocomplete.suggest), escolhida pelo lojista em Settings › Checkout › Address autocompletion
CheckoutOutros planosNão há forma documentada de acrescentar scripts nem um fornecedor de autocomplete
Páginas do tema: contacto, páginas personalizadasTodosWidget 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;
}

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.

Fontes (verificadas a 2 de outubro de 2026)

Experimentar a demoDocumentação do widget