Introdução
A maioria dos fundadores trata SEO como uma caixa preta. Eles ficam olhando para dashboards do Google Search Console cheios de impressões e cliques, e têm dificuldade em responder a única pergunta que realmente importa: o que eu devo fazer agora?
Vivi esse problema por anos construindo sites para clientes e meus próprios produtos SaaS. Os dados estavam lá - milhares de linhas de performance de palavras-chave, rankings de páginas, tendências de CTR - mas extrair insights acionáveis exigia ou profundo conhecimento em SEO ou horas de manipulação de planilhas. Decidi preencher essa lacuna construindo o HeySeo: uma plataforma de analytics SEO com IA que permite que você tenha uma conversa com seus dados de busca.
Esta é a história completa da construção. Decisões de arquitetura, prompt engineering com LLM, integração com API do Google, design do servidor MCP, estratégia de precificação e o que aprendi ao lançar o produto. Vou compartilhar o código real e os erros reais.
O Problema: Dados de SEO São Difíceis de Usar
O Google Search Console é gratuito, abrangente e quase completamente impraticável para a maioria dos donos de sites.
A interface oferece:
- Uma tabela plana de consultas ranqueadas por volume de impressões
- Performance em nível de página dividida por dispositivo
- Relatórios de cobertura cheios de códigos de erro confusos
- Core Web Vitals e dados de PageSpeed escondidos atrás de múltiplos cliques
O que ele não oferece são respostas. Você ainda precisa saber o suficiente sobre SEO para olhar um CTR de 0,8% em uma palavra-chave na posição 4 e raciocinar: "Essa title tag está com desempenho abaixo do esperado para essa intenção. Reescreva."
As ferramentas profissionais de SEO, como Ahrefs, Semrush e Moz, resolvem parte do problema adicionando análise de backlinks, pesquisa de concorrentes e scores de dificuldade de palavras-chave. Mas custam $99–$500 por mês, têm curvas de aprendizado íngremes e ainda exigem interpretação manual significativa.
Existe uma lacuna entre "dados brutos" e "próxima ação clara" que nenhuma ferramenta estava preenchendo bem para desenvolvedores independentes, pequenas equipes de marketing e criadores de conteúdo. Essa é a lacuna para a qual o HeySeo foi construído.
A Ideia: Converse Com Seus Dados
O insight que desencadeou tudo foi simples. LLMs são genuinamente bons em raciocinar sobre dados estruturados quando você dá a eles o contexto certo. E se, em vez de construir mais um dashboard de SEO, eu deixasse os usuários simplesmente fazerem perguntas?
- "Quais páginas perderam mais ranking nos últimos 30 dias?"
- "Para quais palavras-chave estou ranqueando entre 6º e 15º que eu deveria priorizar?"
- "Por que o CTR da minha homepage é tão baixo comparado aos meus posts do blog?"
- "Me dê uma lista de tarefas de SEO que devo atacar esta semana, ordenadas por impacto esperado."
Esse último é o caso de uso matador. Não apenas análise - recomendações priorizadas. O LLM pode raciocinar sobre melhores práticas de SEO, analisar os dados e produzir uma lista de tarefas concreta. Nenhuma expertise necessária do lado do usuário.
A partir dessa ideia central, o conjunto de funcionalidades se expandiu:
- Interface de chat em linguagem natural sobre dados do Search Console
- Relatórios semanais automatizados de SEO entregues por email ou Slack
- Monitoramento de PageSpeed com acompanhamento de tendências e comentários gerados por LLM
- Gerenciamento de indexação - verificar quais páginas o Google indexou, enviar URLs para crawling
- Quadro Kanban para tarefas de SEO, pré-preenchido por análise de IA
- Servidor MCP para conectar o HeySeo ao Claude, Cursor e Windsurf
Visão Geral da Arquitetura
Arquitetura do Sistema HeySeo
Fluxo de requisição do navegador ao LLM e de volta
Escolhi o Nuxt 3 como framework full-stack porque o conheço bem, ele lida com SSR e rotas de API em um único codebase de forma limpa, e a camada de servidor Nitro (H3) é genuinamente rápida. Sem necessidade de um backend Express separado.
O banco de dados é o Supabase. Os dados do Google Search Console são cacheados agressivamente no Redis porque a API do GSC é limitada por rate e relativamente lenta - você não quer que a latência de resposta do LLM inclua um fetch frio do GSC em cada mensagem.
Construindo a Interface de Chat
A interface de chat foi a primeira coisa que construí porque era o diferencial central. Acertar o modelo de interação cedo moldou todo o resto.
As decisões-chave de design:
Respostas em streaming. Esperar 5–10 segundos por uma resposta completa do LLM mata a sensação conversacional. Eu faço stream de tokens da rota da API diretamente para o navegador usando Server-Sent Events.
// server/api/chat.post.ts
import { streamText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
export default defineEventHandler(async (event) => {
const { messages, siteId } = await readBody(event)
const user = await requireAuth(event)
const context = await buildSeoContext(siteId, user.id)
const result = streamText({
model: anthropic('claude-3-5-sonnet-20241022'),
system: buildSystemPrompt(context),
messages,
maxTokens: 2048,
})
return result.toDataStreamResponse()
})Construção de contexto composável. Antes de cada mensagem no chat, eu construo um objeto de contexto SEO estruturado contendo os dados recentes do site. Isso é serializado no system prompt. Vou cobrir o prompt engineering em detalhes abaixo.
Histórico de mensagens. Persisto a conversa no Supabase para que os usuários possam retornar a uma thread e continuar. Cada site tem seu próprio histórico de conversa indexado por site_id + user_id.
No lado do Vue, o componente de chat usa o composable useChat do Vercel AI SDK:
<!-- components/SeoChat.vue -->
<script setup lang="ts">
import { useChat } from '@ai-sdk/vue'
const props = defineProps<{ siteId: string }>()
const { messages, input, handleSubmit, isLoading } = useChat({
api: '/api/chat',
body: { siteId: props.siteId },
initialMessages: await loadConversationHistory(props.siteId),
})
</script>
<template>
<div class="flex h-full flex-col">
<ChatMessageList :messages="messages" :is-loading="isLoading" />
<ChatInput
v-model="input"
:disabled="isLoading"
@submit="handleSubmit"
/>
</div>
</template>O componente ChatMessageList renderiza markdown do assistente - importante porque o LLM naturalmente formata recomendações de SEO como bullet points, tabelas e cabeçalhos. Usei @nuxtjs/mdc para renderização de markdown dentro do stream.
Conectando o Google Search Console
OAuth 2.0 com o Google é simples na teoria e doloroso na prática. O ponto de dor específico com o GSC é que os access tokens expiram após uma hora e você precisa lidar com refresh tokens corretamente em sessões de longa duração.
A API do Google Search Console retorna dados como linhas de séries temporais. Para um site e período de data específicos, você pode consultar por:
query(o termo de busca)page(a URL que ranqueou)countrydevice
Cada linha retorna clicks, impressions, ctr e position. Essa é a matéria-prima.
// server/utils/gsc.ts
import { google } from 'googleapis'
export async function fetchSearchAnalytics(
accessToken: string,
siteUrl: string,
dateRange: { startDate: string; endDate: string },
dimensions: string[],
): Promise<SearchAnalyticsRow[]> {
const auth = new google.auth.OAuth2()
auth.setCredentials({ access_token: accessToken })
const searchconsole = google.searchconsole({ version: 'v1', auth })
const response = await searchconsole.searchanalytics.query({
siteUrl,
requestBody: {
startDate: dateRange.startDate,
endDate: dateRange.endDate,
dimensions,
rowLimit: 1000,
},
})
return response.data.rows ?? []
}A estratégia de caching importa muito aqui. Os dados do GSC para datas passadas nunca mudam, então eu faço cache no nível de data com um TTL de 24 horas para o dia atual e indefinidamente para todos os dias anteriores. Isso significa que a maioria das mensagens do chat resolve o contexto do Redis em menos de 50ms em vez de fazer chamadas de API ao vivo.
// server/utils/gsc-cache.ts
export async function getCachedAnalytics(
siteId: string,
dateRange: DateRange,
): Promise<SearchAnalyticsRow[]> {
const cacheKey = `gsc:${siteId}:${dateRange.startDate}:${dateRange.endDate}`
const cached = await redis.get(cacheKey)
if (cached) return JSON.parse(cached)
const rows = await fetchFromGSC(siteId, dateRange)
const ttl = isCurrentDay(dateRange.endDate) ? 3600 : 0
await redis.set(cacheKey, JSON.stringify(rows), ttl > 0 ? { ex: ttl } : undefined)
return rows
}Uma pegadinha: a API do GSC retorna dados com um atraso de 3–4 dias. Aprendi isso da pior maneira quando os usuários perguntaram "o que aconteceu com meu tráfego ontem" e o LLM respondeu com confiança que nada mudou - porque os dados literalmente não estavam lá ainda. Agora incluo uma nota sobre o atraso no system prompt e exibo na interface.
Prompt Engineering para Dados de SEO com LLM
É aqui que a maioria da iteração aconteceu. A qualidade das respostas do HeySeo depende inteiramente de dar ao LLM o contexto certo no formato certo.
O objeto de contexto. Antes de cada turno da conversa, eu construo um snapshot de contexto contendo:
interface SeoContext {
site: {
url: string
verified: boolean
addedAt: string
}
summary: {
last28Days: PerformanceSummary
previous28Days: PerformanceSummary
deltaClicksPct: number
deltaImpressionsPct: number
}
topQueries: SearchAnalyticsRow[] // top 50 por cliques
decliningQueries: SearchAnalyticsRow[] // maiores quedas de cliques YoY
topPages: SearchAnalyticsRow[] // top 20 páginas por cliques
quickWins: SearchAnalyticsRow[] // pos 4-15, CTR abaixo da média
pagespeed: PagespeedSummary | null
pendingTasks: SeoTask[]
recentInsights: Insight[]
}Eu deliberadamente limito os dados passados ao LLM. Enviar todas as 1000 linhas do GSC excederia os limites de contexto e adicionaria ruído. A etapa de pré-processamento - calcular deltas, identificar quick wins, sinalizar declínios - faz o trabalho pesado para que o LLM possa se concentrar em raciocínio e recomendações.
O system prompt. Passei semanas iterando nisso. A versão final tem quatro seções:
- Papel e enquadramento - o que o HeySeo é, qual é o trabalho do assistente
- Base de conhecimento de SEO - princípios centrais que o LLM deve aplicar (benchmarks de CTR por posição, lógica de identificação de quick wins, melhores práticas de indexação)
- Contexto de dados atual - o objeto
SeoContextserializado - Diretrizes de resposta - como formatar as respostas, quando sugerir tarefas, tom
function buildSystemPrompt(context: SeoContext): string {
return `You are an expert SEO analyst assistant for HeySeo. Your job is to help the user understand their search performance and take concrete actions to improve it.
## SEO Principles You Apply
- Position 1-3: expected CTR 15-30%. Below 10% suggests a title/meta issue.
- Position 4-15: high-opportunity zone. These keywords rank but don't convert to clicks.
- Quick wins: keywords in positions 4-15 with above-average impressions and below-average CTR.
- A click decline with stable impressions usually means a CTR problem (title, meta description).
- A click decline with impression decline usually means a ranking drop (content, backlinks, technical).
## Current Site Data
Site: ${context.site.url}
Last 28 days: ${context.summary.last28Days.clicks} clicks, ${context.summary.last28Days.impressions} impressions
Change vs prior period: ${context.summary.deltaClicksPct > 0 ? '+' : ''}${context.summary.deltaClicksPct.toFixed(1)}% clicks
Top queries by clicks:
${formatQueryTable(context.topQueries)}
Quick win opportunities (pos 4-15, low CTR):
${formatQueryTable(context.quickWins)}
Pages with biggest click declines:
${formatPageTable(context.decliningQueries)}
## Response Guidelines
- Be specific. Reference actual keywords, URLs, and numbers from the data.
- When suggesting tasks, format them as a numbered list with estimated impact (High / Medium / Low).
- If the user asks something you cannot answer from the available data, say so clearly.
- Keep answers concise. Use markdown tables for data-heavy responses.
- Current data lag: GSC reports with a 3-4 day delay. Mention this when relevant.`
}O helper formatQueryTable converte linhas em tabelas markdown compactas que o LLM lida bem sem desperdiçar tokens com JSON verboso.
Output estruturado para geração de tarefas. Quando o usuário pede ao assistente para gerar uma lista de tarefas, eu mudo para uma chamada de output estruturado que retorna objetos SeoTask[] tipados que são escritos diretamente no quadro Kanban:
import { generateObject } from 'ai'
import { z } from 'zod'
const SeoTaskSchema = z.object({
tasks: z.array(z.object({
title: z.string(),
description: z.string(),
category: z.enum(['content', 'technical', 'onpage', 'indexing']),
impact: z.enum(['high', 'medium', 'low']),
effort: z.enum(['high', 'medium', 'low']),
targetUrl: z.string().optional(),
targetKeyword: z.string().optional(),
})),
})
export async function generateSeoTasks(
context: SeoContext,
): Promise<SeoTask[]> {
const { object } = await generateObject({
model: anthropic('claude-3-5-sonnet-20241022'),
schema: SeoTaskSchema,
prompt: buildTaskGenerationPrompt(context),
})
return object.tasks.map((task) => ({
...task,
id: crypto.randomUUID(),
status: 'todo' as const,
createdAt: new Date().toISOString(),
}))
}O Quadro Kanban para Tarefas de SEO
Uma das funcionalidades que os usuários abraçaram imediatamente foi o quadro Kanban. A interface de chat é ótima para exploração e perguntas, mas você precisa de um lugar para capturar e acompanhar o trabalho real.
O quadro tem quatro colunas: A Fazer, Em Progresso, Feito e Dispensado. As tarefas podem ser geradas pela IA, adicionadas manualmente ou criadas de dentro de uma conversa no chat (o assistente pode dizer "Adicionei isso ao seu quadro de tarefas" e realmente fazer isso via tool call).
<!-- components/SeoKanban.vue -->
<script setup lang="ts">
import { useSeoTasks } from '~/composables/useSeoTasks'
const { tasks, moveTask, updateTask, deleteTask } = useSeoTasks()
const columns = [
{ id: 'todo', label: 'To Do' },
{ id: 'in_progress', label: 'In Progress' },
{ id: 'done', label: 'Done' },
{ id: 'dismissed', label: 'Dismissed' },
] as const
function onDrop(taskId: string, targetStatus: SeoTask['status']) {
moveTask(taskId, targetStatus)
}
</script>A função moveTask no composable chama um RPC do Supabase que atualiza o status da tarefa e registra uma entrada de histórico com timestamp. Esse histórico é passado de volta ao LLM como contexto para que ele possa ver quais tarefas o usuário já completou ao gerar futuras recomendações.
Relatórios Automatizados e Integração com Slack
Nem todo usuário quer abrir o app para se manter informado. Relatórios automatizados entregam um resumo semanal diretamente na caixa de entrada ou no canal do Slack.
A geração de relatório roda como um job BullMQ toda segunda-feira de manhã:
// server/jobs/weekly-report.ts
export async function generateWeeklyReport(siteId: string): Promise<void> {
const [context, user, reportSettings] = await Promise.all([
buildSeoContext(siteId, { days: 28 }),
getUserBySiteId(siteId),
getReportSettings(siteId),
])
const { text: reportMarkdown } = await generateText({
model: anthropic('claude-3-5-sonnet-20241022'),
system: REPORT_SYSTEM_PROMPT,
prompt: buildReportPrompt(context),
})
const reportRecord = await saveReport(siteId, reportMarkdown)
if (reportSettings.emailEnabled) {
await sendReportEmail(user.email, reportMarkdown, reportRecord.id)
}
if (reportSettings.slackWebhookUrl) {
await sendSlackReport(reportSettings.slackWebhookUrl, reportMarkdown)
}
}A integração com Slack usa incoming webhooks, o que mantém a fricção de setup baixa - os usuários colam uma URL de webhook na página de configurações e funciona. Considerei construir um app Slack completo com OAuth, mas para o caso de uso (entrega de relatório unidirecional) webhooks são mais simples e confiáveis.
O prompt do relatório pede ao LLM para estruturar o output como:
- Resumo de performance (mudança de tráfego, maiores movimentos)
- Top 3 vitórias da última semana
- Top 3 preocupações ou declínios
- Áreas de foco recomendadas para a próxima semana
Curto, opinativo e acionável. Os usuários me disseram nos feedbacks iniciais que os relatórios anteriores de outras ferramentas que recebiam eram longos e pesados em dados demais. Eles queriam um briefing estilo CFO, não uma planilha.
Monitoramento de PageSpeed
PageSpeed é a métrica de SEO que a maioria dos donos de sites ignora até o Google penalizá-los por isso. O HeySeo consulta a API do PageSpeed Insights semanalmente para cada URL registrada e armazena os dados de série temporal no Supabase.
O dashboard de monitoramento mostra tendências de Core Web Vitals (LCP, CLS, FID/INP) com um gráfico spark-line e um badge de status com código de cores. Quando um score cai abaixo de um limite, o sistema gera uma explicação via LLM sobre o que provavelmente causou e o que corrigir.
// server/utils/pagespeed.ts
export async function fetchPagespeedScore(
url: string,
strategy: 'mobile' | 'desktop' = 'mobile',
): Promise<PagespeedResult> {
const apiUrl = new URL('https://www.googleapis.com/pagespeedonline/v5/runPagespeed')
apiUrl.searchParams.set('url', url)
apiUrl.searchParams.set('strategy', strategy)
apiUrl.searchParams.set('key', process.env.GOOGLE_PAGESPEED_API_KEY!)
const response = await $fetch<PagespeedApiResponse>(apiUrl.toString())
return {
url,
strategy,
score: Math.round((response.lighthouseResult.categories.performance.score ?? 0) * 100),
lcp: response.lighthouseResult.audits['largest-contentful-paint'].numericValue,
cls: response.lighthouseResult.audits['cumulative-layout-shift'].numericValue,
fid: response.lighthouseResult.audits['total-blocking-time'].numericValue,
fetchedAt: new Date().toISOString(),
}
}Uma coisa que aprendi: a API do PageSpeed tem seus próprios rate limits e às vezes retorna erros 500 para URLs completamente válidas. Adicionei exponential backoff com 3 tentativas e silenciosamente pulo falhas em vez de exibir erros ruidosos aos usuários.
Gerenciamento de Indexação
A seção de indexação integra tanto o relatório de Cobertura do Google Search Console quanto a API de Indexação do Google.
Os usuários podem ver quais páginas estão indexadas, quais têm erros (404s, cadeias de redirecionamento, bloqueadas pelo robots.txt) e enviar URLs diretamente para re-crawling. Para a maioria dos sites pequenos, o fluxo de envio manual no GSC é desajeitado - você precisa navegar até URL Inspection, colar a URL, clicar em Request Indexing e repetir para cada página.
O gerenciador de indexação do HeySeo permite que os usuários colem ou importem uma lista de URLs, vejam o status de indexação atual em massa e enfileirem o envio com um clique.
// server/api/indexing/submit.post.ts
export default defineEventHandler(async (event) => {
const { urls, siteId } = await readBody<{ urls: string[]; siteId: string }>(event)
const user = await requireAuth(event)
const accessToken = await getGoogleAccessToken(user.id)
const results = await Promise.allSettled(
urls.map((url) => submitUrlForIndexing(accessToken, url)),
)
const succeeded = results
.filter((r): r is PromiseFulfilledResult<IndexingResult> => r.status === 'fulfilled')
.map((r) => r.value)
const failed = results
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
.map((_, i) => urls[i])
await recordIndexingSubmissions(siteId, succeeded)
return { succeeded: succeeded.length, failed: failed.length, failedUrls: failed }
})A API de Indexação tem uma cota de 200 envios de URL por dia por propriedade. Exibo esse limite na interface e acompanho os envios em relação a ele para que os usuários não encontrem erros inesperados da API.
Integração com Servidor MCP
Esta é a funcionalidade pela qual estou mais empolgado. O Model Context Protocol (MCP) permite que assistentes de codificação com IA como Claude Desktop, Cursor e Windsurf chamem ferramentas externas. Construí um servidor MCP do HeySeo que expõe toda a funcionalidade da plataforma como um conjunto de ferramentas.
O resultado prático: desenvolvedores podem ficar em seu editor, perguntar ao Claude "quais problemas de SEO meu site tem hoje?" e obter uma resposta ao vivo extraída do Google Search Console - sem abrir um navegador.
O servidor MCP é um processo Node.js standalone que encapsula a API do HeySeo:
// mcp/index.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
const server = new McpServer({
name: 'heyseo',
version: '1.0.0',
})
server.tool(
'get_search_performance',
'Fetch search performance data for a site from Google Search Console',
{
siteUrl: z.string().describe('The site URL registered in HeySeo'),
days: z.number().default(28).describe('Number of days to look back'),
},
async ({ siteUrl, days }) => {
const data = await heyseoClient.getSearchPerformance(siteUrl, { days })
return {
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
}
},
)
server.tool(
'get_seo_recommendations',
'Get AI-generated SEO recommendations for a site',
{ siteUrl: z.string() },
async ({ siteUrl }) => {
const recommendations = await heyseoClient.getRecommendations(siteUrl)
return {
content: [{ type: 'text', text: recommendations.markdown }],
}
},
)
server.tool(
'create_seo_task',
'Add a task to the HeySeo Kanban board',
{
siteUrl: z.string(),
title: z.string(),
description: z.string(),
impact: z.enum(['high', 'medium', 'low']),
},
async (params) => {
const task = await heyseoClient.createTask(params)
return {
content: [{ type: 'text', text: `Task created: ${task.id}` }],
}
},
)
const transport = new StdioServerTransport()
await server.connect(transport)Os usuários instalam o servidor MCP via npx heyseo-mcp e adicionam ao config do Claude/Cursor com sua API key. O onboarding leva cerca de 2 minutos.
Esta foi a funcionalidade com maior retenção que lancei. Usuários que configuraram a integração MCP têm uma taxa de churn 40% menor do que aqueles que usam apenas o app web. A fricção de "abrir navegador, navegar até a ferramenta, fazer pergunta" é real, e removê-la muda a frequência com que as pessoas realmente interagem com seus dados de SEO.
Estratégia de Precificação
Passei mais tempo na precificação do que em qualquer funcionalidade técnica individual. Aqui está no que cheguei depois de testar múltiplos modelos.
Plano gratuito: Um site, 30 dias de histórico, 20 mensagens de chat por mês, apenas resumo do relatório semanal. Suficiente para demonstrar valor sem dar o produto de graça.
Starter ($19/mês): Três sites, 12 meses de histórico, chat ilimitado, relatórios semanais automatizados, monitoramento de PageSpeed. Este é o plano para projetos pessoais / pequenas empresas.
Growth ($49/mês): Dez sites, histórico completo, relatórios automatizados em qualquer frequência, integração com Slack, acesso ao servidor MCP, gerenciamento de indexação. Este é o plano alvo para equipes de marketing e agências.
Agency ($149/mês): Sites ilimitados, relatórios white-label, assentos de equipe, suporte prioritário.
O insight chave foi que o servidor MCP e a integração com Slack precisavam ser funcionalidades pagas. São as funcionalidades de maior engajamento e servem usuários que estão claramente obtendo valor profissional recorrente da ferramenta. Colocá-las atrás de um paywall também cria um momento claro de upgrade: quando um usuário está usando ativamente o produto em seu ambiente de codificação, ele entende a proposta de valor concretamente.
Também ofereço um desconto anual de 20%, o que melhora o fluxo de caixa e reduz o churn simultaneamente. Aproximadamente 35% dos usuários pagos escolhem o plano anual.
Lançamento e Tração Inicial
Lancei o HeySeo no Product Hunt em janeiro de 2026 após cerca de 3 meses de construção. Os resultados foram melhores do que o esperado para uma ferramenta B2B de nicho:
- 847 upvotes, #3 produto do dia
- 312 cadastros nas primeiras 48 horas
- 23 conversões pagas na primeira semana
- $1.100 MRR no fim do mês de lançamento
O lançamento no Product Hunt impulsionou a consciência inicial, mas o crescimento sustentado veio de duas fontes:
Marketing de conteúdo. Publiquei guias detalhados sobre uso de IA para análise de SEO, integração do Search Console com ferramentas de IA e compreensão de Core Web Vitals. Esses conteúdos ranqueiam para palavras-chave long-tail de SEO e trazem cadastros de pessoas que estão ativamente procurando pelo problema exato que o HeySeo resolve.
Visibilidade no ecossistema MCP. Quando submeti o servidor MCP do HeySeo ao registro MCP do Claude.ai e à página de plugins do Cursor, a descoberta orgânica aumentou significativamente. Desenvolvedores procurando por ferramentas MCP encontram o HeySeo sem nenhuma promoção paga.
O que não funcionou: outreach frio para agências de marketing. O ciclo de compra é muito longo e o tomador de decisão raramente é a pessoa que avalia ferramentas técnicas. Deixei de lado o outreach para agências em favor de conteúdo inbound.
Lições Aprendidas
Custos de LLM são previsíveis com o caching certo. Eu estava preocupado com custos de API descontrolados antes do lançamento. Na prática, a combinação de caching agressivo de dados do GSC e objetos de contexto pré-computados significa que a chamada ao LLM é a única etapa cara, e ela só é acionada em mensagens reais de usuários. Meu custo atual de LLM é cerca de $0,08 por usuário ativo por mês em níveis típicos de uso.
Rate limits das APIs do Google exigem código defensivo desde o primeiro dia. Não apenas exponential backoff - você também precisa de circuit breakers, rastreamento de rate limit por usuário e degradação graceful quando a API está indisponível. Fui otimista demais sobre a confiabilidade da API no início e tive vários incidentes antes de adicionar resiliência adequada.
O quadro Kanban me surpreendeu. Construí como uma funcionalidade secundária para dar aos outputs do chat um lugar para pousar. Acabou sendo a principal razão pela qual muitos usuários permanecem assinantes - o quadro dá a eles uma lista de tarefas persistente que mantém o estado entre sessões e se torna mais valiosa quanto mais tempo usam.
Streaming importa mais do que a qualidade bruta da resposta. Usuários que veem tokens aparecendo em 500ms percebem o produto como rápido e responsivo, mesmo quando a resposta completa leva 8 segundos. Usuários que esperam por uma resposta completa percebem até respostas de 3 segundos como lentas. Invista em streaming antes de investir em otimização de latência.
Construa para seus melhores usuários primeiro. A integração MCP exigiu esforço significativo de engenharia e serve uma minoria de usuários. Mas esses usuários são power users que recomendam o produto ativamente, têm baixo churn e fazem upgrade para planos superiores. O ROI é muito melhor do que funcionalidades que melhoram a experiência mediana levemente.
O Que Vem a Seguir
O HeySeo está em $3.800 MRR em março de 2026 e crescendo de forma constante. O roadmap para o próximo trimestre:
- Rastreamento de concorrentes (compare seus rankings versus concorrentes identificados)
- Sugestões de meta title e description geradas por IA com suporte a testes A/B
- Alertas automatizados quando rankings caem significativamente
- Integração com GA4 para correlacionar tráfego de busca com dados de conversão
- Relatórios white-label para o plano Agency
O insight central, de que a maioria dos donos de sites tem dados que não consegue usar, e LLMs podem preencher essa lacuna, se sustenta em cada estágio do produto. A plataforma se torna mais valiosa à medida que o Google adiciona mais dados ao Search Console e os LLMs ficam melhores em raciocínio sobre dados estruturados.
Se você está construindo algo semelhante ou quer discutir a arquitetura, ficarei feliz em conversar.
Quer trabalhar juntos em um projeto como este? Eu construo produtos SaaS com IA e ferramentas orientadas por dados para fundadores e equipes de desenvolvimento. Se você tem um problema que vale a pena resolver, vamos conversar.