Os lançamentos de campanhas não começam num painel. Começam numa spreadsheet que alguém partilhou no Slack. Os URLs estão na coluna A, os metadados UTM preenchem as colunas B a G, os slugs estão na coluna H, e o brief diz que o lançamento é amanhã. A parte mais lenta de todo o processo é copiar cada linha para uma UI de encurtador um link de cada vez - não porque seja tecnicamente difícil, mas porque não há razão para o fazer dessa forma.
Este artigo é o fluxo de trabalho direto: como é a sheet, como mapeia para o endpoint de importação em massa da Elido, três caminhos de importação dependendo do número de linhas, o passo de dry-run que apanha erros antes de estarem em produção, e um snippet de Apps Script que automatiza tudo num trigger. Para o contexto mais amplo sobre higiene UTM de ponta a ponta, o cornerstone de rastreio UTM cobre templates de workspace e reencaminhamento de conversões do lado do servidor em profundidade. Este artigo é a fatia de sheet-para-links-curtos desse pipeline.
TL;DR#
- Mantenha uma sheet por campanha:
target_url,slug,utm_source,utm_medium,utm_campaign,tagscomo colunas nomeadas. As colunas UTM que estão em branco são preenchidas a partir do seu template de workspace. - Três caminhos de importação: colar linhas na UI (até 1.000 linhas), upload de CSV (até 10.000 linhas), ou a API via script (ilimitado, repetível).
- Execute sempre com
dry_run=trueprimeiro. A pré-visualização mostra o link curto resolvido e a string de query UTM completamente renderizada sem comprometer nada. - Prefixe os slugs de campanha (
q2-,jun-) para os isolar em namespaces. Os conflitos surgem no dry run, não a meio da importação.
Forma da sheet#
As colunas obrigatórias são target_url e uma de slug ou auto_slug. Tudo o resto é opcional mas tem uma interpretação definida quando presente.
| Coluna | Obrigatório | Notas |
|---|---|---|
target_url | sim | URL de destino completo incluindo o esquema |
slug | um dos dois | Preferível - dá-lhe URLs curtos previsíveis |
auto_slug | um dos dois | Defina como true e a Elido gera um slug |
utm_source | opcional | Substitui o valor do template de workspace |
utm_medium | opcional | Substitui o valor do template de workspace |
utm_campaign | opcional | Substitui o valor do template de workspace |
utm_content | opcional | Normalmente a variante criativa |
utm_term | opcional | Palavra-chave paga ou segmento de audiência |
tags | opcional | Separado por vírgulas, aplicado ao link |
title | opcional | Mostrado na lista de links do painel |
A regra UTM é simples: se o target_url já contém um parâmetro de query ?utm_source= (ou qualquer utm_*), esses valores são passados sem alterações. Sem sobrescrever, sem mesclar. Se o URL de destino não tem parâmetros UTM, a Elido constrói-os a partir das colunas UTM, recorrendo ao seu template de workspace para qualquer coluna que esteja em branco. Isto importa na prática - algumas equipas mantêm URLs de destino pré-etiquetados para o seu fornecedor de serviços de e-mail, e uma ferramenta de importação em massa que os re-etiqueta silenciosamente produz análises incorretas. A Elido avisa em linhas de modo misto (alguns UTMs presentes, alguns em falta) e pede confirmação.
A coluna de tags merece a sua própria nota. Os valores são strings separadas por vírgulas: campaign:q2-spring, channel:paid-social, variant:hero-a. Essa forma de três partes (dimensão:valor) dá-lhe eixos filtráveis no painel sem precisar de uma configuração de taxonomia separada. Mais sobre isto na secção de taxonomia de tags abaixo.
Os três caminhos de importação#
Colar linhas na UI de importação em massa (até 1.000 linhas)#
Para qualquer coisa abaixo de 1.000 linhas, o caminho mais rápido é copiar o intervalo da sheet e colar na área de texto de importação em massa. A UI da Elido deteta automaticamente valores separados por tabulação de uma colagem de spreadsheet e mapeia as colunas pelo cabeçalho. Não exporta um CSV; simplesmente cola.
Isto funciona bem para o caso mais comum: um brief de campanha que já vive em Sheets, um prazo de lançamento uma hora depois e nenhuma vontade de usar scripting. A UI mostra uma pré-visualização de todas as linhas antes de confirmar (o mesmo dry-run que obteria da API) e permite corrigir qualquer linha que tenha falhado inline antes de prosseguir.
Uma armadilha: se a sua sheet tiver células mescladas ou formatação complexa, a colagem pode produzir output distorcido. O movimento seguro para qualquer sheet com uma estrutura não trivial é copiar primeiro para uma sheet limpa (colar como valores), depois colar o intervalo limpo na UI de importação.
Upload de CSV (até 10.000 linhas)#
Para lançamentos com mais de 1.000 linhas (campanhas de catálogo grande, códigos de eventos, links personalizados), o caminho de upload de CSV suporta até 10.000 linhas. Exporte a sheet como CSV (Ficheiro > Transferir > CSV) e carregue-o no diálogo de importação. O mapeamento de cabeçalho de coluna é o mesmo; a diferença é que uploads grandes são processados de forma assíncrona e reportam o seu estado via webhook ou endpoint de polling.
A exportação de CSV da Google Sheets via API (acedida a 2026-05-12) suporta exportar um intervalo nomeado em vez da folha inteira, o que é útil quando a sua sheet de campanha tem múltiplos separadores ou linhas de cabeçalho que não quer limpar manualmente.
Chamada de API de um script (mais de 10.000 linhas, ou execuções repetidas)#
Para catálogos grandes, ou para campanhas que correm semanalmente e precisam do mesmo processo automatizado, o caminho da API é o correto. Duas implementações comuns: Apps Script (não requer ferramentas locais, corre no browser) e Python (melhor para equipas com pipelines de dados existentes). O endpoint é o mesmo em qualquer caso.
curl -X POST \
https://api.elido.app/v1/links/bulk \
-H "Authorization: Bearer $ELIDO_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "csv=@q2_spring_links.csv" \
-F "campaign_id=cmp_8a2f" \
-F "dry_run=false" \
-F "on_conflict=skip"
O parâmetro on_conflict controla o que acontece quando um slug já existe: skip deixa o link existente no lugar e regista um aviso, fail aborta toda a importação no primeiro conflito, e replace atualiza o destino do link existente. Para a maioria das importações de campanhas, skip é o padrão correto: uma nova execução do mesmo CSV não vai sobrescrever links que já criou.
A API aceita até 10.000 linhas por chamada. Para catálogos maiores, agrupe em lotes de 5.000 linhas; cada chamada é independente e idempotente se usar slugs estáveis.
Dry run pré-importação#
Execute cada importação com dry_run=true antes de confirmar. A resposta é idêntica à importação real (cada linha mostra o seu link curto resolvido, a string de query UTM analisada, a lista de tags e quaisquer avisos) mas nada é escrito na base de dados.
As coisas que o dry-run apanha que não vai apanhar de outra forma antes do lançamento:
- Um slug na linha 14 que entra em conflito com um link existente no seu workspace (apresentado como um aviso de conflito)
- Uma coluna UTM que foi acidentalmente deixada em branco (a Elido sinaliza
utm_mediumem falta como aviso, não como erro grave, mas é algo que quer saber antes do lançamento) - Um
target_urlcom um espaço no final que sobreviveu à cópia da spreadsheet (o URL resolvido parece correto no CSV mas o destino real tem%20anexado) - Valores de tag que excedem 32 caracteres (truncados silenciosamente; o dry run torna o valor armazenado visível)
A resposta do dry-run é paginada no mesmo formato que um resultado de importação real. Abra a primeira página, verifique aleatoriamente a linha 2 (a primeira linha de dados após a linha 1 que provavelmente está perfeita) e a última linha. Depois veja as linhas que sinalizam um aviso. Dois minutos de revisão apanham os erros que de outra forma surgiriam como "por que é que este link de campanha está a dar 404?" na manhã após o lançamento.
Conflitos de slug#
Os conflitos de slug acontecem quando um slug que está a tentar importar já existe no seu workspace ou no seu domínio personalizado. A importação apresenta-os na resposta do dry-run com o tipo de conflito (same_workspace, same_domain, reserved) e o URL de destino do link existente.
A correção prática é o isolamento em namespaces. Prefixe os slugs de campanha com um identificador curto: q2-, jun26-, sm- (para redes sociais), em- (para e-mail). Um slug como q2-spring-hero-a dificilmente vai entrar em conflito com algo de uma campanha anterior. Os prefixos também tornam o filtro do painel óbvio - todos os links com etiqueta q2-* pertencem a um trimestre de campanha.
Um caso que vale a pena mencionar: se está a migrar de outro encurtador e quer preservar slugs legados, importe esses primeiro sem prefixo, depois use slugs prefixados para novo conteúdo de campanha. A importação em massa da Elido dir-lhe-á no dry run se algum dos slugs legados entra em conflito com os que já estão no workspace.
Taxonomia de tags#
As tags aplicadas no momento da importação têm a mesma estrutura de três partes que as colunas da sheet que as geraram: campaign:q2-spring, channel:email, variant:hero-a. Quando abre o painel mais tarde e filtra por channel:email, não está a pesquisar através de strings de texto livre - está a consultar uma taxonomia consistente.
Os nomes de dimensão (campaign, channel, variant) vêm da convenção da sua equipa, não de qualquer esquema imposto pela Elido. A restrição é o formato: um separador de dois pontos, sem espaços na chave, valores com menos de 32 caracteres. As equipas que impõem isto na sheet (uma coluna tags que uma fórmula constrói como "campaign:"&E2&", channel:"&F2) nunca têm tags malformadas no painel. As equipas que deixam a coluna de tags ser texto livre têm um problema de limpeza dentro de três campanhas.
Para a visão geral da funcionalidade de campanhas, o agrupamento baseado em tags é a forma principal como a Elido agrupa cliques por dimensão de campanha no painel de análise - por isso a taxonomia que define na sheet é a taxonomia pela qual vai filtrar no momento de reportar.
Automação com Apps Script#
Para equipas que executam a mesma estrutura de campanha semanalmente (links de newsletter, links de social pago, variantes de e-mail), o movimento certo é automatizar a importação inteiramente. O Google Apps Script corre no browser, tem acesso aos dados da sheet e pode disparar num cron baseado em tempo ou em envio de formulário.
O padrão: um trigger dispara, o script lê todas as linhas da sheet que não têm um valor short_link na coluna I, faz POST delas para a API de importação em massa e escreve os links curtos criados de volta na coluna I. No próximo trigger, as linhas já importadas são ignoradas porque a coluna I está preenchida.
// Google Apps Script - importação em massa de novas linhas via API da Elido
// Trigger: baseado em tempo, de hora a hora (ou no envio de formulário)
// Docs: https://developers.google.com/apps-script/guides/triggers (acedida a 2026-05-12)
function importNewLinks() {
const sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Q2 Spring");
const data = sheet.getDataRange().getValues();
const headers = data[0];
const urlCol = headers.indexOf("target_url");
const slugCol = headers.indexOf("slug");
const srcCol = headers.indexOf("utm_source");
const medCol = headers.indexOf("utm_medium");
const campCol = headers.indexOf("utm_campaign");
const tagsCol = headers.indexOf("tags");
const doneCol = headers.indexOf("short_link"); // escrever aqui
const newRows = [];
const rowIndexes = [];
for (let i = 1; i < data.length; i++) {
const row = data[i];
if (!row[urlCol] || row[doneCol]) continue; // ignorar vazias ou já importadas
newRows.push({
destination: row[urlCol],
slug: row[slugCol] || undefined,
utm_source: row[srcCol] || undefined,
utm_medium: row[medCol] || undefined,
utm_campaign: row[campCol] || undefined,
tags: row[tagsCol]
? String(row[tagsCol])
.split(",")
.map((t) => t.trim())
: [],
});
rowIndexes.push(i);
}
if (!newRows.length) return;
const payload = JSON.stringify({
links: newRows,
campaign_id: "cmp_8a2f",
on_conflict: "skip",
});
const resp = UrlFetchApp.fetch("https://api.elido.app/v1/links/bulk", {
method: "post",
contentType: "application/json",
headers: {
Authorization:
"Bearer " +
PropertiesService.getScriptProperties().getProperty("ELIDO_TOKEN"),
},
payload: payload,
muteHttpExceptions: true,
});
const result = JSON.parse(resp.getContentText());
const created = result.links || [];
// Escrever links curtos de volta na coluna I
created.forEach((link, idx) => {
if (!link.short_url) return;
const sheetRow = rowIndexes[idx] + 1; // indexado a partir de 1
sheet.getRange(sheetRow, doneCol + 1).setValue(link.short_url);
});
}
Algumas notas de implementação:
Armazene o token da API em PropertiesService.getScriptProperties(), não codificado diretamente no script. A documentação de triggers do Apps Script (acedida a 2026-05-12) cobre a configuração de triggers baseados em tempo e em eventos. Para uma sheet de campanha que uma equipa preenche colaborativamente, um trigger onEdit dispara quando a coluna A é preenchida; o link curto aparece na coluna I segundos depois de escrever o URL de destino.
A flag muteHttpExceptions: true é importante. Sem ela, um 422 da API lança uma exceção ao nível do script e o trigger para de tentar novamente. Com ela, obtém o corpo do erro e pode registá-lo em vez disso.
Para uma integração mais pesada (um script Python, um passo de CI que lê uma sheet via a API do Sheets, ou um job agendado no seu pipeline de dados existente), o endpoint spreadsheets.values.get da Sheets API (acedida a 2026-05-12) dá-lhe JSON diretamente. A partir daí a forma da chamada de importação em massa é idêntica ao exemplo com curl acima.
Erros comuns#
Espaços em branco no final dos slugs. Um slug copiado de uma célula de spreadsheet pode ter um espaço no final que é invisível na UI. A Elido permite-o (o slug é tecnicamente válido), mas go.exemplo.com/q2-promo com um espaço no final é um URL feio e a cópia para a área de transferência a partir da barra de endereços de um browser geralmente remove-o, por isso a pessoa que cola o link curto mais tarde recebe um 404. A correção é uma fórmula =TRIM(H2) na coluna de slug antes de exportar.
utm_medium em falta. A Elido avisa mas não bloqueia num utm_medium em falta porque algumas campanhas o omitem intencionalmente. Mas um medium em falta é quase sempre um erro: o GA4 encaminha qualquer coisa sem um para o canal (none), o que torna a atribuição por canal inútil. A referência canónica do GA4 URL builder (acedida a 2026-05-12) lista utm_medium como obrigatório para a atribuição de campanha funcionar corretamente. Se o seu template de workspace tiver um padrão de utm_medium, as células em branco na coluna herdam-no; se não tiver, o aviso do dry-run é a sua última oportunidade para o apanhar.
Valores de tag com mais de 32 caracteres. A Elido trunca silenciosamente os valores de tag que excedem 32 caracteres. A truncagem é invisível nos avisos do dry-run a menos que a procure (a resposta mostra o valor armazenado, não o original). Os valores de tag longos geralmente vêm de colar nomes de campanha UTM na coluna de tags: spring-2026-dach-email-reactivation-week3 tem 42 caracteres e passará a ser spring-2026-dach-email-reactivation-we no painel. Mantenha os valores de dimensão de tag curtos; mova os metadados detalhados para o título do link.
Esquecer dry_run=true em novas execuções. Se voltar a executar um upload de CSV contra uma campanha que já tem links, on_conflict=skip é seguro mas on_conflict=replace vai atualizar os URLs de destino em qualquer slug que apareça tanto no CSV antigo como no novo. Numa campanha em que os URLs de destino não mudaram, isto é inofensivo. Numa campanha em que atualizou os URLs de landing page a meio, é o que quer. Saiba em que modo está antes de confirmar.
O resumo da configuração ao lançamento#
A versão mais completa deste fluxo de trabalho: construa a sheet uma vez com nomes de coluna estáveis, defina um template UTM de workspace para que as colunas UTM em branco herdem padrões sensatos (coberto em setup-branded-short-links), execute a pré-importação a seco para apanhar conflitos e avisos, confirme, e escreva o trigger do Apps Script para que a próxima campanha não requeira passos manuais.
Para a camada de atribuição que fecha o ciclo após o clique, o rastreio de conversões do lado do servidor cobre como ligar o click_id da resposta de redirect da Elido ao Meta CAPI e GA4, a peça do lado do servidor que sobrevive ao ITP do Safari e à interferência de bloqueadores de anúncios. Esse artigo e este juntos dão-lhe uma imagem completa do fluxo de trabalho de campanha de solutions/marketers, da sheet ao link curto até à conversão atribuída.
A superfície completa de gestão de URLs de campanha - templates, importação em massa, agrupamento de campanhas, reencaminhamento de conversões - está na página features/campaigns.
Experimente Elido
Cole uma URL, obtenha um link curto
Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.
Grátis, sem necessidade de registo · 2 por dia