Desenvolver blocos Gutenberg otimizados para SEO local em Curitiba pequenas empresas
Aprenda a criar blocos Gutenberg personalizados que impulsionam o SEO local para pequenos negócios em Curitiba com performance e dados estruturados.
Imagine uma padaria no bairro Batel que precisa aparecer no “pão francês perto de mim” quando alguém pesquisa pelo celular às 6h da manhã. O site roda WordPress, mas o tema genérico não expõe horários, endereço estruturado nem área de entrega nos bairros vizinhos. O desenvolvedor decide criar um bloco Gutenberg sob medida: um componente “Local Business Card” que injeta schema LocalBusiness completo, carrega CSS só na página onde existe e permite à dona da padaria editar endereço e horários direto no editor visual.
Esse cenário real ilustra por que blocos personalizados superam plugins genéricos de SEO local. Plugins injetam markup em todo o site, carregam scripts desnecessários e limitam a granularidade do schema. Um bloco bem arquitetado resolve os três problemas de uma vez: performance, precisão semântica e autonomia do cliente final.
Vamos detalhar a arquitetura, o registro, a renderização híbrida e os cuidados de manutenção para que sua equipe entregue blocos que escalam de uma padaria no Batel para uma rede de clínicas odontológicas em Santa Felicidade.
Arquitetura do bloco: separação de responsabilidades
Divida o plugin em três camadas: registro PHP (init, assets, render callback), build React (edit/save) e template PHP server-side. O registro PHP usa register_block_type apontando render_callback para uma função que carrega template-parts/blocks/local-business-card.php. Assim, o frontend nunca depende de JavaScript para exibir o schema — crucial para rastreadores e LCP.
No lado React, edit.js monta o painel lateral com InspectorControls para campos NAP, seletor de subtipo (Restaurant, Dentist, Physiotherapist) e repeater de bairros atendidos. save.js retorna null porque a marcação final vem do PHP. Essa estratégia evita mismatch entre editor e frontend e garante que atualizações de schema não quebrem blocos já publicados.
Schema markup dinâmico e validado
O template PHP recebe $attributes e monta um array $schema seguindo a especificação LocalBusiness do Schema.org. Campos obrigatórios: @type, name, address (PostalAddress com streetAddress, addressLocality: "Curitiba", addressRegion: "PR", postalCode, addressCountry: "BR"), telephone, openingHoursSpecification (array de dias/horários), areaServed (array de Place com name dos bairros).
function dwp_render_local_business_card( $attributes ) {
$schema = [
'@context' => 'https://schema.org',
'@type' => $attributes['businessSubtype'] ?? 'LocalBusiness',
'name' => esc_html( $attributes['businessName'] ),
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => esc_html( $attributes['streetAddress'] ),
'addressLocality' => 'Curitiba',
'addressRegion' => 'PR',
'postalCode' => esc_html( $attributes['postalCode'] ),
'addressCountry' => 'BR',
],
'telephone' => esc_html( $attributes['phone'] ),
'openingHoursSpecification' => array_map( fn($h) => [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => $h['day'],
'opens' => $h['open'],
'closes' => $h['close'],
], $attributes['hours'] ?? [] ),
'areaServed' => array_map( fn($b) => [
'@type' => 'Place',
'name' => $b,
], $attributes['neighborhoods'] ?? [] ),
];
printf( '<script type="application/ld+json">%s</script>', wp_json_encode( $schema ) );
// HTML visível aqui...
}
Valide a saída no Rich Results Test antes de ir para produção.
Performance: assets condicionais e zero dependências
Enfileire CSS e JS apenas quando o bloco estiver presente na página. No PHP:
function dwp_enqueue_local_business_assets() {
if ( has_block( 'dwp/local-business-card' ) ) {
wp_enqueue_style( 'dwp-local-business', plugin_dir_url( __FILE__ ) . 'assets/frontend.css', [], '1.0.0' );
wp_enqueue_script( 'dwp-local-business', plugin_dir_url( __FILE__ ) . 'assets/frontend.js', [], '1.0.0', true );
}
}
add_action( 'wp_enqueue_scripts', 'dwp_enqueue_local_business_assets' );
O frontend.js tem menos de 2 KB (apenas interatividade leve como accordion de horários). O React do editor já vem do core — não adicione react nem react-dom como dependência. Use @wordpress/element, @wordpress/components, @wordpress/block-editor via wp-scripts.
Acessibilidade e usabilidade no editor
No edit.js, cada input recebe label explícito ligado via htmlFor/id. Use SelectControl para subtipo com opções traduzidas. Para bairros, implemente TextControl com addFilter( 'blocks.registerBlockType', ... ) que sugere lista pré-carregada dos 75 bairros oficiais de Curitiba via wp_localize_script. Contraste mínimo 4.5:1, foco visível, navegação por Tab testada com NVDA.
Versionamento, testes e deploy contínuo
Estruture o plugin como pacote Composer privado ("type": "wordpress-plugin"). composer.json exige wp-scripts como dev dependency. Pipeline GitHub Actions:
npm run lint(ESLint + Stylelint + PHP_CodeSniffer WPCS)npm run test(Jest + @wordpress/scripts test-unit)npm run build(produzbuild/sem source maps)- Publica artifact como release GitHub; servidor de staging puxa via
composer update
Changelog gerado por standard-version a partir de commits convencionais (feat:, fix:, chore:).
Escalando para múltiplas localidades
Quando o cliente abrir filial em Londrina, não duplique o bloco. Adicione atributo city (default “Curitiba”) e state (default “PR”) no block.json. O template PHP lê esses valores e ajusta addressLocality/addressRegion dinamicamente. O painel lateral ganha SelectControl com capitais do Paraná. Mesmo bloco, schema correto para cada endereço.
Para equipes que gerenciam dezenas de sites de pequenos negócios, a padronização via bloco interno reduz retrabalho e garante consistência técnica. A gestão de tráfego na região de Santos segue princípio idêntico: componente reutilizável, schema preciso, performance blindada.
Blocos Gutenberg bem feitos viram ativos de produto, não dívida técnica. Invista na arquitetura certa na primeira padaria do Batel e colha escala na rede de clínicas de Santa Felicidade — com schema válido, LCP verde e cliente editando horários sem abrir ticket.
Checklist prático
Perguntas frequentes
Por que criar blocos Gutenberg próprios para SEO local em vez de usar plugins prontos?
Blocos personalizados eliminam código desnecessário, permitem schema markup preciso para cada tipo de negócio em Curitiba e garantem performance superior ao evitar dependências pesadas de plugins genéricos.
Quais dados estruturados são essenciais para pequenos negócios curitibanos?
LocalBusiness com subtipo específico (Restaurant, Store, ProfessionalService), endereço completo com bairros como Batel ou Água Verde, horários de funcionamento, área de atuação e avaliações são fundamentais para aparecer no mapa local.
Como garantir que o bloco não prejudique o Core Web Vitals?
Carregue assets apenas quando o bloco for usado no editor ou frontend, use CSS-in-JS ou estilos enfileirados condicionalmente, e evite bibliotecas externas — React nativo do WordPress já supre a necessidade.
É possível reaproveitar o bloco para outras cidades além de Curitiba?
Sim, torne campos como cidade, estado, CEP e bairros configuráveis via atributos do bloco ou painel lateral, permitindo que o mesmo componente atenda múltiplas localidades sem duplicação de código.
Como testar se o schema markup do bloco está válido?
Use a Ferramenta de Teste de Dados Estruturados do Google e o Validador de Schema.org; insira a URL da página renderizada e verifique se LocalBusiness aparece sem erros nem avisos críticos.
Qual a melhor forma de versionar e manter blocos Gutenberg em produção?
Publique como plugin privado no repositório da empresa ou use GitHub Packages; adote SemVer, gere changelog automático e rode testes de regressão visual no Storybook antes de cada deploy.