WP Manifestindependent plugin directory
manifest / seo / wp-banners-og

Banners OG WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA

Open Graph banners (1200x630) built in the WordPress admin and published as og:image. No external service, no GD or Imagick.

★ 1stars
36release downloads
v2.4.0latest · 1mo ago

Install

Download banners-og-2.4.0.zip From the v2.4.0 release on GitHub, Aug 25, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/jeffersonrucu/wp-banners-og/releases/download/v2.4.0/banners-og-2.4.0.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Plugin WordPress que gera banners Open Graph 1200 × 630 dentro do próprio admin e publica a imagem como og:image do site — sem serviço externo, sem GD/Imagick.

O banner é montado em HTML/CSS, rasterizado no navegador com html2canvas e enviado como upload multipart. O PHP só valida e grava o arquivo.

O plugin não tem marca embutida: paleta, tipografia, logo e símbolo vêm das configurações; layouts, campos e textos padrão são filtráveis; e um layout novo pode ser registrado de fora, sem tocar no plugin.

Com WooCommerce ativo, cada produto ganha o próprio banner, com a foto, o preço e a categoria do produto — veja WooCommerce. E quando um plugin de SEO cuida das meta tags, o banner é entregue a ele em vez de ficar sem uso — veja Meta tags.

Banners OG — um card por layout, com preview ao vivo e o arquivo em uso:

Tela Banners OG com os quatro layouts

Aparência — paleta, par tipográfico e imagens da marca:

Tela de aparência: paleta, par tipográfico e imagens da marca

Metabox — cada post ganha o próprio banner, gerado ao salvar:

Metabox de banner no editor de post


Requisitos

  • WordPress 5.9+
  • PHP 7.4+
  • Navegador moderno no admin (a geração acontece no cliente)

Instalação

Via Git

cd wp-content/plugins
git clone git@github.com:jeffersonrucu/wp-banners-og.git

Via Composer (repositório VCS)

{
    "repositories": [
        { "type": "vcs", "url": "git@github.com:jeffersonrucu/wp-banners-og.git" }
    ],
    "require": {
        "jeffersonrucu/banners-og": "^2.0"
    }
}

O type é wordpress-plugin; com composer/installers no projeto ele cai em wp-content/plugins/banners-og.

Depois de ativar:

  1. Banners OG → Aparência: paleta, font stacks, nome da marca, logo e símbolo.
  2. Banners OG: revise os textos de cada layout e clique em Generate and save banner.
  3. Posts e páginas passam a gerar o próprio banner ao salvar.

Como funciona

Camada Papel
Banners_OG_Plugin Bootstrap, chaves de storage, config do JS e enqueue dos assets.
Banners_OG_Theme Paleta, tipografia e imagens da marca; imprime as CSS custom properties.
Banners_OG_Templates Registro de layouts, campos, textos padrão e resolução de layout por contexto.
Banners_OG_Admin Tela Banners OG: um card por layout.
Banners_OG_Settings Tela Aparência (Settings API).
Banners_OG_Metabox Metabox por conteúdo.
Banners_OG_Ajax Recebe o upload, valida permissão e grava.
Banners_OG_Storage uploads/banners-og/: grava via wp_handle_upload() e apaga o anterior.
Banners_OG_Meta Meta tags og:* / twitter:* no wp_head.
assets/js/banner.js Registro de layouts, preview ao vivo, captura e upload.

Onde o banner aparece

Todo post type público e com tela de edição ganha o metabox, e toda taxonomia pública ganha o editor no termo. Isso inclui os CPTs e as taxonomias que o site registra por conta própria: nada precisa ser declarado no plugin. Ficam de fora os anexos e os formatos de post, cuja página não é algo que se compartilhe.

Para restringir, os filtros banners_og_post_types e banners_og_taxonomies recebem essa lista:

add_filter( 'banners_og_post_types', function ( array $types ): array {
    return array_diff( $types, [ 'cachorro' ] );
} );

Fluxo por conteúdo

  1. Todo post/página dos post types suportados ganha um banner automático: título do banner = título do post, resto = textos padrão do layout do tipo.
  2. O checkbox "Customize the layout and the copy of this banner" libera os campos.
  3. Ao salvar o post (Gutenberg ou editor clássico), o JS gera o banner e substitui o arquivo anterior — o botão "Generate banner now" faz o mesmo sob demanda.

Fluxo por termo

Categorias e tags têm o próprio banner, editado na tela de edição do termo. Sem customização, o banner usa o nome e a descrição do termo, e é regerado a cada Atualizar. Vale para toda taxonomia pública com tela de edição — inclusive as criadas por você ou por um plugin de CPT —, menos os formatos de post. Para restringir, use banners_og_taxonomies.

A descrição do termo também vira a og:description do arquivo.

A criação pela coluna da esquerda da tela de categorias é AJAX e não comporta o gerador: o banner nasce no primeiro Atualizar da categoria já criada.

Armazenamento

Fora de sites com offload (veja abaixo), os banners não entram na biblioteca de mídia: ficam em wp-content/uploads/banners-og/, com um index.php para bloquear autoindex. Cada regeração apaga o arquivo antigo e usa um nome com timestamp (og-post-42-20260825120000.jpg) para furar o cache das redes sociais.

Consequência: trocar de ambiente sem levar uploads/ derruba os banners — é só regerar.

Site com offload de uploads (S3, Spaces, GCS). Nesses sites a pasta de uploads é publicada por outro host, e só attachment faz essa viagem: um arquivo solto seria publicado a partir de um bucket que nunca o recebeu — daí o AccessDenied. Quando o plugin detecta que a URL de uploads está em outro host, o banner passa a ser gravado como attachment, e o plugin de offload cuida de subir e servir, como faz com qualquer imagem da biblioteca. Sem tamanhos intermediários: o banner é publicado inteiro.

A detecção não se contenta com "a URL de uploads está em outro host": um CDN pull também reescreve essa URL, e nele o arquivo solto funciona, porque o CDN busca no servidor de origem. O modo attachment só entra quando há rastro de offload de verdade — uploads num stream (s3://), upload_url_path fixado nas opções, ou um plugin conhecido (S3 Uploads, WP Offload Media, WP-Stateless).

Os filtros mandam mais que a detecção:

Filtro Para quê
banners_og_use_attachments Força (ou proíbe) o modo attachment.
banners_og_uploads_url Muda de onde os arquivos soltos são servidos.

Banners OG › Diagnóstico mostra qual modo está em uso.

Meta tags

Banners_OG_Meta se cala automaticamente se detectar Yoast, Rank Math, AIOSEO ou SEOPress. Para forçar o comportamento, use o filtro banners_og_output_tags.

Calar não basta: sem as tags do plugin, o banner gerado não chegaria a lugar nenhum. Por isso Banners_OG_Seo entrega a imagem para quem estiver imprimindo as tags, pelos filtros públicos de cada plugin:

Plugin Filtros usados
Yoast SEO wpseo_opengraph_image, wpseo_twitter_image, wpseo_opengraph_image_width/height/type
Rank Math rank_math/opengraph/facebook/image, rank_math/opengraph/twitter/image
SEOPress seopress_social_og_thumb, seopress_social_twitter_card_thumb
All in One SEO aioseo_facebook_tags, aioseo_twitter_tags

Duas ressalvas:

  • No Yoast, os filtros só rodam quando ele já escolheu uma imagem. Post sem imagem destacada e sem fallback social continua sem og:image.
  • O formato do array do AIOSEO não é contrato público, então a ponte só troca tags que já venham como string. Se a estrutura mudar, ela não faz nada — não quebra.

Para desligar a ponte e manter a escolha do plugin de SEO, use banners_og_seo_bridge.


Layouts que vêm no plugin

Kind Layout
cover Centralizado em fundo claro, com símbolo, moldura e assinatura no rodapé.
feature Fundo escuro, conteúdo à esquerda, símbolo em marca d'água.
article Painel escuro à esquerda com símbolo e marca, conteúdo à direita.
profile Centralizado em fundo alternativo, com logo horizontal.
product Conteúdo à esquerda com preço, foto do produto à direita. Só com WooCommerce ativo.

Exemplo do arquivo final, no layout cover:

Banner Cover gerado, 1200 × 630

Todos leem as mesmas custom properties, então seguem a paleta configurada:

--bog-bg  --bog-bg-alt  --bog-dark  --bog-accent  --bog-text  --bog-muted
--bog-rule  --bog-font-heading  --bog-font-body

Nenhum layout usa o logo como arte de fundo — símbolo repetido só funciona com marca desenhada para isso, e aqui a marca é a que o site subiu. O detalhe geométrico vem de .bog-corner (brackets de canto desenhados com a paleta). Ainda assim, --bog-mark-url é exposta para quem quiser usar a marca como background-image num layout próprio.


WooCommerce

Com o WooCommerce ativo, Banners_OG_Woocommerce entra sozinho e acrescenta:

  • o layout product: conteúdo à esquerda (categoria, nome, preço, resumo) e a foto do produto no painel à direita;
  • os campos Mostrar o preço, Mostrar a foto e Foto (media picker), que só aparecem no layout product. O preço nunca é digitado: é sempre o preço atual do produto, e o campo só diz se ele é impresso;
  • o layout product como padrão do post type product e das taxonomias product_cat / product_tag, que também ganham banner por termo — com a imagem da categoria e sem o preço, que ali não teria de qual produto falar.

Exemplo do arquivo final, no layout product:

Banner Product gerado, 1200 × 630

Os placeholders do metabox saem do próprio produto: categoria (primeiro termo de product_cat), resumo (descrição curta, 24 palavras), preço (get_price_html(), sem o preço riscado das promoções) e a imagem destacada. Digitar qualquer campo sobrescreve; deixar vazio mantém o valor do produto.

O card Product na tela Banners OG é a configuração geral: vale para os arquivos da loja e define o padrão dos toggles. Ali não existe produto, então o preview sai sem preço e sem foto — o painel cai no símbolo da marca, que já é o fallback de qualquer produto sem imagem própria. Por isso o campo Foto só aparece no editor do produto.

Limitações conhecidas:

  • Preço desatualizado. O banner é regerado quando o produto é salvo. Mudança de preço fora do editor (promoção agendada, edição em massa, importação) não dispara nova geração — o banner continua com o preço antigo até o próximo save. Para não correr o risco, apague o campo Preço no layout.
  • Imagem em CDN. O html2canvas não desenha imagem de outro domínio: ela aparece no preview e some do arquivo gerado. Vale para a foto do produto e também para o logo e o símbolo da marca. O plugin resolve a URL para a cópia local em uploads/ e, quando ela não existe (offload que apaga o arquivo local), serve a imagem pelo próprio site, por admin-ajax.php. Esse endpoint aceita ID de anexo, nunca URL, e exige edit_posts mais nonce. Banners OG › Diagnóstico mostra em brand logo drawable o caminho em uso. banners_og_product_image_url força outra URL para a foto do produto.
  • Editor novo de produtos (o experimental, em blocos) não renderiza metaboxes clássicos. O banner segue funcionando no editor padrão de produtos.
  • Catálogo existente não é gerado em lote: hoje o banner nasce ao salvar o produto, um a um.

Diagnóstico

Banners OG › Diagnóstico mostra onde os banners são gravados, qual URL eles publicam e — no botão Request the banner URLs now — o status HTTP que essa URL devolve de verdade. O relatório no fim da tela é texto puro, para colar num issue. É por onde começar quando o og:image não abre.


Extensão (nível dev)

Filtros e actions

Hook Tipo Default Uso
banners_og_post_types filtro post types públicos Onde o metabox aparece.
banners_og_taxonomies filtro taxonomias públicas Taxonomias com banner por termo.
banners_og_kinds filtro 4 layouts Adiciona/remove layouts (kind => rótulo).
banners_og_fields filtro eyebrow, title, sub, foot Campos de texto dos layouts.
banners_og_font_presets filtro 4 pares tipográficos Pares oferecidos na tela de Aparência.
banners_og_template_defaults filtro por layout Textos padrão de um layout ($defaults, $kind).
banners_og_default_kind_for_post_type filtro mapa interno Layout padrão de um post type.
banners_og_default_kind_for_context filtro por contexto Layout usado em arquivos e listagens.
banners_og_post_defaults filtro defaults dos layouts Placeholders de um post, derivados do conteúdo ($defaults, $post).
banners_og_term_defaults filtro defaults dos layouts O mesmo para um termo ($defaults, $term).
banners_og_default_kind_for_taxonomy filtro mapa interno Layout padrão de uma taxonomia.
banners_og_output_tags filtro true (sem plugin de SEO) Liga/desliga a saída das meta tags.
banners_og_meta_data filtro array montado Ajusta título, descrição, URL, tipo e imagem.
banners_og_seo_bridge filtro true Liga/desliga a entrega do banner ao plugin de SEO.
banners_og_product_image_url filtro foto do produto Imagem usada pelo layout product ($url, $product).
banners_og_uploads_url filtro URL de uploads/ De onde os banners gerados são servidos.
banners_og_use_attachments filtro detecção de offload Grava o banner como attachment em vez de arquivo solto.
banners_og_enqueue_assets action — Enfileira CSS/JS de layouts próprios.

API JavaScript

Disponível em window.BannersOG depois que banners-og-banner carrega:

Membro Descrição
registerTemplate(kind, renderer) Registra (ou substitui) o renderer de um layout.
templates Mapa kind => renderer.
helpers.esc(value) Escapa texto para HTML.
helpers.image(url, className) Devolve <img> — ou string vazia se não houver URL.
helpers.clamp(texto, max) Corta na palavra e fecha com ….
helpers.titleSize(texto, mid, small) Modificador bog-title--sm / --xs conforme o tamanho do texto.
boot() Reescaneia a página em busca de editores.

O renderer recebe (fields, ctx) e devolve o HTML de um canvas 1200 × 630:

  • fields — valores por chave de campo (fields.title, fields.sub, …).
  • ctx — { esc, image, corners, clamp, titleSize, kind, brand, images: { logo, mark }, width, height }.

O canvas é fixo em 1200 × 630 e o texto que cresce não tem para onde ir: os layouts do plugin passam título e subtítulo por clamp() e descem um degrau de corpo (--sm, --xs) quando o texto é longo. Um layout próprio faz o mesmo.

ctx.brand é a marca da tela de Aparência, e serve de fallback do campo brand: os layouts que assinam o banner imprimem fields.brand || ctx.brand.

Criando um layout do zero

1. Registre o layout, seus textos padrão e (se quiser) campos extras

add_filter( 'banners_og_kinds', function ( array $kinds ): array {
    $kinds['podcast'] = __( 'Podcast', 'meu-tema' );

    return $kinds;
} );

add_filter( 'banners_og_template_defaults', function ( array $defaults, string $kind ): array {
    if ( 'podcast' === $kind ) {
        $defaults['eyebrow'] = __( 'Episódio', 'meu-tema' );
        $defaults['sub']     = get_bloginfo( 'description' );
        $defaults['episode'] = '#01';
    }

    return $defaults;
}, 10, 2 );

add_filter( 'banners_og_fields', function ( array $fields ): array {
    $fields['episode'] = [
        'label'       => __( 'Número do episódio', 'meu-tema' ),
        'type'        => 'text',        // text | textarea | image | toggle
        'description' => '',
        'placeholder' => '#01',         // usado quando o layout não tem default
        'kinds'       => [ 'podcast' ], // vazio = aparece em todos os layouts
    ];

    return $fields;
} );

Os tipos:

Tipo Controle Valor gravado
text input de texto texto
textarea textarea texto com quebras
image media picker, com preview URL da imagem
toggle checkbox 1 ou string vazia

kinds é o que evita poluir os outros layouts: o campo só aparece nos layouts listados, e o formulário do metabox troca de campos junto com o select de layout. Os textos padrão continuam vindo de banners_og_template_defaults.

2. Enfileire o CSS e o JS do layout

add_action( 'banners_og_enqueue_assets', function (): void {
    $base = get_stylesheet_directory_uri() . '/og-podcast';

    wp_enqueue_style( 'og-podcast', $base . '/podcast.css', [ 'banners-og-admin' ], '1.0.0' );
    wp_enqueue_script( 'og-podcast', $base . '/podcast.js', [ 'banners-og-banner' ], '1.0.0', true );
} );

3. Escreva o renderer

// podcast.js
window.BannersOG.registerTemplate('podcast', function (fields, ctx) {
  return '' +
    '<div class="bog-canvas bog-canvas--podcast">' +
      '<div class="bog-texture"></div>' +
      '<div class="pod-episode">' + ctx.esc(fields.episode) + '</div>' +
      ctx.image(ctx.images.mark, 'bog-mark') +
      '<div class="bog-eyebrow">' + ctx.esc(fields.eyebrow) + '</div>' +
      '<div class="bog-title">' + ctx.esc(fields.title) + '</div>' +
      '<div class="bog-sub">' + ctx.esc(fields.sub) + '</div>' +
      '<div class="bog-foot">' + ctx.esc(fields.foot) + '</div>' +
    '</div>';
});

4. Estilize dentro de 1200 × 630, reaproveitando as custom properties

/* podcast.css */
.bog-canvas--podcast {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 90px;
  background: var(--bog-dark);
}

.bog-canvas--podcast .bog-title { font-size: 88px; color: #fff; }

.pod-episode {
  font: 600 14px/1 var(--bog-font-body);
  letter-spacing: .3em;
  color: var(--bog-muted);
}

Regras do renderer:

  • Escape tudo que vem de fields com ctx.esc() — o HTML é injetado via innerHTML.
  • Use ctx.image() para imagens: ele omite a tag quando não há URL configurada.
  • O nó raiz precisa medir exatamente 1200 × 630; a captura rejeita outras medidas.
  • Evite filter, mask e sombras exóticas: o html2canvas não renderiza tudo. Para logo em fundo escuro, prefira uma placa clara atrás da imagem (veja .bog-mark-plate) em vez de inverter a cor por CSS.

Estrutura

banners-og/
├── banners-og.php                # header do plugin, requires e hooks
├── config.php                    # constantes
├── uninstall.php                 # limpeza de options, meta e arquivos
├── readme.txt                    # metadados do WordPress.org
├── includes/
│   ├── class-banners-og-plugin.php
│   ├── class-banners-og-theme.php
│   ├── class-banners-og-templates.php
│   ├── class-banners-og-storage.php
│   ├── class-banners-og-activator.php
│   ├── class-banners-og-admin.php
│   ├── class-banners-og-settings.php
│   ├── class-banners-og-status.php    # tela de diagnóstico
│   ├── class-banners-og-metabox.php
│   ├── class-banners-og-termbox.php   # banner por categoria/tag
│   ├── class-banners-og-ajax.php
│   ├── class-banners-og-meta.php
│   ├── class-banners-og-seo.php       # entrega o banner ao plugin de SEO ativo
│   └── class-banners-og-woocommerce.php
├── assets/
│   ├── css/admin.css             # UI do admin + os 4 layouts
│   ├── css/woocommerce.css       # layout product
│   ├── js/banner.js              # registro de layouts, preview, captura, upload
│   ├── js/woocommerce.js         # renderer do layout product
│   ├── js/settings.js            # media picker e color inputs
│   └── vendor/html2canvas/       # 1.4.1 (MIT), versionado de propósito
├── languages/                    # .pot, e pt-BR em .po/.mo/.l10n.php
├── bin/
│   ├── build-dist.sh             # monta dist/banners-og
│   └── check-version.php         # versão consistente entre header, config e readme
├── phpcs.xml.dist
└── phpstan.neon.dist

Traduções

O plugin vem com pt-BR (languages/banners-og-pt_BR.po, .mo e .l10n.php) e com o template languages/banners-og.pot para outros idiomas.

Regerar o template depois de mexer nas strings, e recompilar a tradução:

wp i18n make-pot . languages/banners-og.pot --domain=banners-og --exclude=index.php
wp i18n update-po languages/banners-og.pot languages/banners-og-pt_BR.po
wp i18n make-mo languages/banners-og-pt_BR.po languages/
wp i18n make-php languages/banners-og-pt_BR.po languages/

O .l10n.php é o formato que o WordPress 6.5+ carrega no lugar do .mo, mais rápido; os dois ficam versionados.

Desenvolvimento

composer install
composer phpcs          # WordPress Coding Standards + PHPCompatibility
composer phpcbf         # corrige o que é automático
composer phpstan        # análise estática (nível 6)
composer check-version  # header × config.php × readme.txt
composer dist           # monta dist/banners-og

plugin-check

O bin/build-dist.sh monta em dist/banners-og só o que é plugin — o .distignore deixa fora tooling de desenvolvimento (bin/, tests/, composer.*, configs de lint, .github/). É esse pacote que vai para o WordPress.org e é nele que o Plugin Check deve rodar:

composer dist
wp plugin check dist/banners-og

Rodar o checker direto no clone acusa bin/ e tests/ por não terem guarda de acesso direto — são arquivos de CLI, que não fazem parte do pacote.

Contribuindo

Veja CONTRIBUTING.md. Vulnerabilidade: SECURITY.md.

Licença

GPL-2.0-or-later. assets/vendor/html2canvas/ é de terceiros (html2canvas 1.4.1, MIT).

Releases

5 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v2.4.0 latest
Aug 25, 2026 1mo ago
banners-og-2.4.0.zip
35
Aug 25, 2026 1mo ago
banners-og-2.3.0.zip
0
Aug 25, 2026 1mo ago
banners-og-2.2.0.zip
0
Aug 25, 2026 1mo ago
banners-og-2.1.0.zip
0
Aug 25, 2026 1mo ago
banners-og-2.0.0.zip
1
A grade

Security

Banners OG 2.4.0 · audited by WP Registry

No security issues found.

Audited release
2.4.0
Findings
none
Worst severity
—
Content hash
a9dcb99ce6b5d35f5ef5e333…

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.