O comércio eletrónico B2B contemporâneo coloca desafios técnicos de elevado rigor à engenharia de software. Os compradores empresariais exigem tabelas de preços contratuais negociadas, quantidades mínimas de encomenda (MOQ) e escalões de desconto transparentes em função do volume adquirido. Em paralelo, os motores de busca e os assistentes de compras baseados em inteligência artificial exigem dados estandardizados e legíveis por máquina relativos a custos unitários e patamares de encomenda. Qualquer discrepância entre os valores indicados nos feeds de produtos e os montantes calculados no carrinho de compras resulta na reprovação de produtos no Google Merchant Center.
Para construir um ecossistema de preços escalonados escalável e resiliente no WooCommerce, é fundamental abandonar padrões arcaicos de armazenamento em metadados genéricos. Torna-se imperativo conceber estruturas relacionais dedicadas, implementar processos de geração de feeds em fluxo contínuo (streaming) e assegurar uma anotação semântica minuciosa segundo os padrões do Schema.org.
Especificações técnicas do Google Merchant Center para preços unitários e grossistas
O Google Merchant Center aplica regras rigorosas a produtos comercializados ao peso, volume, comprimento ou em embalagens industriais agrupadas. Na UE, nos países da EFTA, no Reino Unido, na Austrália e na Nova Zelândia, a Google exige o preço unitário nos produtos que a regulamentação local obriga a apresentá-lo, para que os compradores profissionais e os consumidores disponham de mecanismos imediatos de comparação através do preço unitário de referência (por exemplo, custo por quilograma, litro ou metro quadrado).
Os principais atributos do feed de produtos incluem:
unit_pricing_measure: A dimensão ou volume líquido real contido na unidade de venda (como25kg,500mlou100ct). Este valor indica ao analisador sintático a quantidade física exata comercializada.unit_pricing_base_measure: A base métrica padrão de comparação (como1kg,100mlou1ct). A Google divide o preço total por este denominador para gerar automaticamente o indicativo de preço unitário.auto_pricing_min_price: O preço mais baixo para o qual a Google pode reduzir um produto em descontos automáticos e promoções dinâmicas.loyalty_program: Atributo de grupo para preços de membro, envio para membros e pontos de fidelização. É o único local para preços que dependem da adesão a um programa; não existe um atributo separado para escalões grossistas.
A indicação incorreta de unidades métricas ou discrepâncias cambiais provocam erros impeditivos na validação do catálogo. Por exemplo, no caso de um adesivo técnico industrial fornecido num recipiente de 20 litros comercializado por 240 EUR, o atributo unit_pricing_measure deve ser exatamente 20l e unit_pricing_base_measure deve registar 1l, permitindo ao motor de busca apresentar a menção correspondente de 12 EUR por litro.
Como enviar preços escalonados B2B num feed do Google Merchant Center
A especificação de dados de produto da Google não tem nenhum atributo para escalões de quantidade. Cada artigo do feed leva um único price, e as regras do atributo price definem que valor tem de ser. Se existir uma quantidade mínima de encomenda, o preço do feed é o preço dessa quantidade mínima: a Google indica que não se deve enviar o preço de uma só unidade quando o cliente não pode comprar apenas uma. Num multipack ou conjunto criado pelo comerciante, o preço é o total da embalagem completa.
Restam três formas viáveis de apresentar uma escala por volume:
- Produtos separados por formato. Cada tamanho de embalagem (balde, caixa, palete) passa a ser um artigo próprio com o seu
id, o seupricee o seuunit_pricing_measure, e todos partilham o mesmoitem_group_id. A documentação de unit_pricing_measure mostra este padrão com arroz em sacos de 5, 10 e 12 libras, cada um com uma medida base de 1 libra, para que o preço unitário mostre ao comprador qual o formato mais barato por unidade de peso. - O atributo
multipack. De acordo com a página de multipack, destina-se a embalagens que o comerciante montou com produtos idênticos e é obrigatório nas listagens gratuitas quando cria uma embalagem deste tipo. Numa embalagem definida pelo fabricante, não enviemultipacke indique a quantidade através deunit_pricing_measure. - A tabela de escalões fica no site. Os descontos acima do mínimo ficam no WooCommerce e na página do produto, enquanto o feed transmite o preço de entrada. Esta opção não multiplica as referências e mantém-se coerente desde que a página de destino mostre o mesmo preço de entrada.
Para o preço unitário, ambos os atributos têm de usar o mesmo tipo de unidade, e unit_pricing_base_measure aceita apenas valores específicos: 1, 2, 4, 8, 10 ou 100 de uma unidade, mais 75cl, 750ml, 50kg e 1000kg (unit_pricing_base_measure). A medida aceita no máximo duas casas decimais. Para o Reino Unido, a Google interpreta as unidades imperiais como unidades imperiais norte-americanas, por isso os valores métricos são a opção segura. Se um artigo tiver ao mesmo tempo unit_pricing_measure e uma classe de eficiência energética, a Google mostra apenas a classe energética.
Que regras da página de destino e do checkout levam à reprovação de produtos B2B no Merchant Center
A maioria das reprovações B2B resulta da diferença entre o feed e aquilo que o comprador vê. As regras do atributo price contêm as restrições que chocam com as configurações grossistas habituais:
- O preço do feed tem de coincidir com o preço da página de destino e do checkout, na moeda do país de destino, e não é permitido “ver preço no carrinho”.
- Qualquer utilizador do país de destino tem de poder comprar ao preço enviado. Pode exigir-se uma conta apenas se o registo for gratuito e simples, o que exclui feeds construídos com preços que só as contas profissionais aprovadas conseguem ver.
- Em países como a Alemanha, a França ou o Reino Unido o preço inclui IVA, e a Google aplica isto também às ofertas grossistas. Nos Estados Unidos e no Canadá os impostos ficam fora do preço.
- Um valor mínimo de encomenda não faz parte do preço. Configura-se nas definições de envio.
Os preços contratuais e de membro têm o seu próprio canal. A Google determina que os preços para membros não podem ir em price nem em sale_price; vão no atributo de grupo loyalty_program, com subatributos como program_label, tier_label, price, loyalty_points e member_price_effective_date. O programa tem de ser configurado primeiro no Merchant Center, os preços para membros têm de estar visíveis para eles no site, e a Google só mostra preços de membro nos anúncios quando o desconto atinge pelo menos 5 % ou 5 unidades da moeda. Os exemplos da Google são níveis de cliente como prata e ouro, não contas empresariais verificadas, por isso uma loja B2B tem de verificar se a sua tabela profissional encaixa nesse modelo.
Uma promoção temporária de um escalão pertence a sale_price, que tem de ser inferior a price. O preço completo continua a ser enviado em price, a página de destino mostra ambos os preços, o checkout mostra apenas o preço promocional e sale_price_effective_date limita o período; sem esse atributo, o preço promocional aplica-se de imediato. auto_pricing_min_price é outra ferramenta: o atributo de preço mínimo é obrigatório para descontos automáticos e promoções dinâmicas e tem de ficar entre o custo dos bens vendidos, se o enviar, e 95 % do preço normal.
Estrangulamentos na tabela wp_postmeta e uma tabela própria de escalões de preço
O modelo de dados predefinido do WordPress assenta na arquitetura Entity-Attribute-Value (EAV), concentrando todos os metadados de produtos e variantes na tabela genérica wp_postmeta. Numa loja de retalho de pequena dimensão, este padrão funciona de modo aceitável. Todavia, no comércio B2B de grande escala, onde um artigo dispõe de 5 patamares de quantidade para 8 grupos distintos de clientes empresariais, a quantidade de registos cresce de forma descontrolada.
O registo de 40 regras de preços para um único artigo traduz-se em 40 linhas na tabela wp_postmeta. Num catálogo com 30 000 produtos e 100 000 variantes, a tabela de metadados ultrapassa rapidamente as dezenas de milhões de registos. Cada consulta nas páginas de catálogo desencadeia múltiplas junções LEFT JOIN, gerando bloqueios de escrita e sobrecarga severa no InnoDB Buffer Pool do MySQL.
O High-Performance Order Storage (HPOS) não resolve isto por si só. Segundo a documentação do HPOS do WooCommerce, move as encomendas e os respetivos endereços para quatro tabelas próprias (wc_orders, wc_order_addresses, wc_order_operational_data e wc_orders_meta), enquanto os produtos ficam nas tabelas de publicações. O que o HPOS oferece é o padrão: dados com uma forma conhecida recebem uma tabela própria com índices adequados às consultas. Para os escalões de preço, isso significa uma tabela separada com índices compostos:
-- Tabela relacional dedicada para gestao de escaloes de preco b2b
CREATE TABLE IF NOT EXISTS wp_wc_b2b_price_tiers (
tier_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
product_id BIGINT UNSIGNED NOT NULL,
customer_group VARCHAR(32) NOT NULL DEFAULT 'all',
min_quantity INT UNSIGNED NOT NULL DEFAULT 1,
max_quantity INT UNSIGNED DEFAULT NULL,
price_cents BIGINT NOT NULL,
currency CHAR(3) NOT NULL DEFAULT 'EUR',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_product_lookup (product_id, customer_group, min_quantity),
INDEX idx_pricing_search (min_quantity, max_quantity)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;Com o índice composto (product_id, customer_group, min_quantity), a pesquisa de um produto, um grupo de clientes e uma quantidade passa a ser uma única leitura de intervalo no índice, em vez de uma cadeia de junções sobre a wp_postmeta. A eliminação das pesquisas exaustivas na wp_postmeta liberta a memória do servidor e confere estabilidade às transações concorrentes.
Para analisar metodologias de sincronização entre catálogos complexos e sistemas de gestão empresarial, consulte a nossa análise técnica sobre integração woocommerce erp.
Geração de feeds de produtos XML e NDJSON em fluxo contínuo
A transmissão periódica de largas dezenas de milhares de produtos com matrizes completas de preços escalonados para o Google Merchant Center requer processos de exportação altamente eficientes. Carregar a totalidade do inventário para memória num único array em PHP através de funções convencionais como wc_get_products() esgota inevitavelmente o limite de memória do sistema (memory_limit).
Um sistema de exportação profissional tira partido de cursores de base de dados associados a geradores sequenciais em PHP (yield). Este método grava os registos XML por blocos controlados diretamente no armazenamento físico ou encaminha pacotes NDJSON para serviços na nuvem:
<?php
/**
* Gerador de feed de produtos em fluxo continuo para o Google Merchant Center
*/
declare(strict_types=1);
namespace WPPoland\B2BFeedsPT;
use Generator;
use wpdb;
class StreamedProductFeedGenerator
{
private wpdb $db;
public function __construct(wpdb $db)
{
$this->db = $db;
}
public function streamCatalogBatch(int $batchSize = 500): Generator
{
$offset = 0;
while (true) {
$query = $this->db->prepare(
"SELECT p.ID, p.post_title, t.min_quantity, t.price_cents, t.currency
FROM {$this->db->posts} p
INNER JOIN wp_wc_b2b_price_tiers t ON p.ID = t.product_id
WHERE p.post_type IN ('product', 'product_variation')
AND p.post_status = 'publish'
AND t.customer_group = 'wholesale_tier_1'
ORDER BY p.ID ASC
LIMIT %d OFFSET %d",
$batchSize,
$offset
);
$rows = $this->db->get_results($query, ARRAY_A);
if (empty($rows)) {
break;
}
foreach ($rows as $row) {
yield $this->formatGoogleXmlNode($row);
}
$offset += $batchSize;
}
}
private function formatGoogleXmlNode(array $product): string
{
$price = number_format($product['price_cents'] / 100, 2, '.', '');
return sprintf(
"<item>\n <g:id>%d</g:id>\n <g:title><![CDATA[%s]]></g:title>\n <g:price>%s %s</g:price>\n <g:min_handling_time>1</g:min_handling_time>\n</item>\n",
$product['ID'],
htmlspecialchars($product['post_title'], ENT_QUOTES, 'UTF-8'),
$price,
$product['currency']
);
}
}Como só existe em memória um lote de 500 linhas de cada vez, o consumo depende do tamanho do lote e não do tamanho do catálogo. O agendamento via rotinas de linha de comando no WP-CLI garante que a compilação do feed não interfere com as encomendas dos utilizadores em tempo real.
Para certificar que os pontos de acesso das APIs de exportação se encontram resguardados contra scraping não autorizado, realize regularmente uma auditoria de segurança em wordpress.
Marcação semântica schema.org com PriceSpecification e unitCode
A correta identificação semântica das matrizes de preços no código HTML das páginas de produto é um fator determinante para a visibilidade nos motores de busca e assistentes de compras de IA. O Schema.org descreve preços unitários através de UnitPriceSpecification aninhado numa oferta.
Recomenda-se a integração explícita dos códigos internacionais de unidades de medida da UN/CEFACT (tais como KGM para quilogramas, LTR para litros, MTK para metros quadrados e C62 para unidades individuais):
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Adesivo estrutural de poliuretano, balde de 5 kg",
"sku": "ADH-IND-500",
"offers": {
"@type": "Offer",
"price": "220.00",
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "220.00",
"priceCurrency": "EUR",
"referenceQuantity": {
"@type": "QuantitativeValue",
"value": 5,
"unitCode": "KGM",
"valueReference": {
"@type": "QuantitativeValue",
"value": 1,
"unitCode": "KGM"
}
}
}
}
}A documentação das listagens de comerciante da Google restringe o que o Schema.org permite. As listagens de comerciante precisam de um Offer, porque o comerciante tem de ser o vendedor; AggregateOffer só é aceite em fragmentos de produto. O preço unitário vai em priceSpecification como UnitPriceSpecification, em que referenceQuantity é a quantidade vendida por esse preço e valueReference a quantidade base, os equivalentes em dados estruturados de unit_pricing_measure e unit_pricing_base_measure. No exemplo, o balde contém 5 kg, pelo que o preço de 220 EUR corresponde a 44 EUR por quilograma. O único priceType que a Google suporta é StrikethroughPrice, os preços de membro usam validForMemberTier juntamente com um preço normal, e uma especificação que combine ambos é ignorada. A página não menciona eligibleQuantity, por isso não se deve esperar que os escalões acima do preço de entrada apareçam nos resultados da Google; a marcação transmite o preço de entrada, o mesmo que o feed.
Arquitetura de cache na borda para tabelas de preços grossistas
A utilização de soluções tradicionais de cache de página completa (como Nginx FastCGI ou Redis Full Page Cache) falha em lojas B2B quando os utilizadores autenticados têm cotações personalizadas. Desativar a cache para todos os utilizadores autenticados sobrecarrega severamente os servidores e agrava o Time to First Byte (TTFB).
A arquitetura contemporânea adota uma estratégia híbrida na borda da rede:
- Cache global do invólucro do produto: O conteúdo estático, descrições técnicas, manuais em PDF e imagens são guardados em cache nos nós periféricos da CDN.
- Hidratação assíncrona de dados de faturação: Ao carregar a página, o navegador do cliente corporativo efetua uma chamada autenticada e leve para recuperar a tabela de preços contratada.
- Injeção direta no DOM: Um script modular de JavaScript substitui os valores e recalcula o custo em tempo real, preservando a eficiência da cache global.
Em plataformas empresariais de grande envergadura, a separação de camadas mediante arquiteturas modernas oferece vantagens de estabilidade sem paralelo. Descubra os nossos métodos de implementação na área de headless wordpress.
Sincronização com ERP e consistência transacional de dados
A integridade dos preços entre a loja online e o Google Merchant Center depende estritamente do intervalo de sincronização com o sistema de gestão central (ERP). Sempre que as tabelas de matérias-primas ou custos operacionais são ajustadas no ERP, essa alteração deve ser refletida de imediato no portal de compras e nos feeds de marketing.
A integração deve estruturar-se em torno de filas de processamento assíncrono no Action Scheduler e webhooks orientados a eventos. Cada atualização pontual de preço aciona a alteração na tabela wp_wc_b2b_price_tiers e remete imediatamente a nova cotação através da Merchant API da Google, prescindindo da espera pela rotina diária global.
A utilização de transações com buffers bidirecionais salvaguarda o MySQL contra conflitos de escrita nos períodos de pico de encomendas grossistas, registando anomalias no sistema de monitorização para resolução imediata.
O que o Google for WooCommerce mapeia e o que exige um feed próprio
A extensão oficial Google for WooCommerce cobre parte desta configuração. O seu mapeamento de atributos suporta 15 atributos da Google, entre eles Multipack, Is Bundle, GTIN, MPN e Brand. Uma regra pode aplicar-se a todas as categorias, a todas exceto as selecionadas ou a uma única categoria. As regras só preenchem atributos vazios, e os valores definidos no separador Google de cada produto prevalecem. As regras leem apenas atributos globais, pelo que os atributos criados na página de um único produto têm de ser convertidos em globais primeiro.
A medida de preço unitário não consta dessa lista. Uma loja que vende ao peso, ao volume ou à área precisa de valores por produto ou de uma integração própria, por feed ou por API, para unit_pricing_measure e unit_pricing_base_measure. O mesmo vale para os produtos por formato gerados a partir de uma tabela de escalões própria, que a extensão desconhece.
A camada de transporte mudou em 2026. A Google indica que a Content API for Shopping foi descontinuada a 18 de agosto de 2026, que os pedidos começam a falhar de forma progressiva a partir de 1 de setembro de 2026, e remete para a Merchant API. O Google for WooCommerce fez a mudança na versão 3.8.1. Uma integração própria escreve produtos através de recursos ProductInput com insert, patch e delete, lê os recursos Product já processados e só pode escrever em fontes de dados do tipo API, como explica o guia de produtos da Merchant API.
Testes unitários e validação automática das regras de cálculo
No comércio empresarial, desvios no cálculo de preços escalonados provocam impactos financeiros e legais de monta. Cobrar valores discrepantes relativamente ao anunciado no Google Merchant Center viola as regras de correspondência de preços citadas acima e pode levar à reprovação de produtos ou à suspensão da conta.
Uma infraestrutura de qualidade exige baterias de testes automatizados executadas em cada ciclo de integração contínua (CI):
<?php
/**
* Testes de integracao para escaloes de precos e metricas unitarias b2b
*/
declare(strict_types=1);
namespace WPPoland\Tests\PricingPT;
use PHPUnit\Framework\TestCase;
class TieredPricingCalculationTest extends TestCase
{
public function testPrecoEscalonadoPorVolume(): void
{
$calculador = new \WPPoland\Pricing\TieredPriceCalculator();
// Artigo com preco base de 44 EUR e patamar de 31 EUR para 10 unidades
$precoIndividual = $calculador->resolveEffectivePrice(
productId: 4096,
quantity: 4,
customerGroup: 'wholesale_tier_1'
);
$this->assertEquals(4400, $precoIndividual, 'Quantidades inferiores ao patamar devem liquidar o valor base.');
$precoVolume = $calculador->resolveEffectivePrice(
productId: 4096,
quantity: 12,
customerGroup: 'wholesale_tier_1'
);
$this->assertEquals(3100, $precoVolume, 'Quantidades a partir de 10 unidades devem receber desconto de lote.');
}
public function testValidacaoAtributosMetricos(): void
{
$validador = new \WPPoland\B2BFeedsPT\FeedAttributeValidator();
$medidaValida = $validador->validateUnitPricingAttributes(
measure: '25kg',
baseMeasure: '1kg'
);
$this->assertTrue($medidaValida, 'Unidades da lista suportada pela Google devem ser aceites.');
$medidaInvalida = $validador->validateUnitPricingAttributes(
measure: '25caixas',
baseMeasure: 'palete'
);
$this->assertFalse($medidaInvalida, 'Designacoes genericas nao normalizadas devem ser recusadas.');
}
}Esta camada de verificação previne erros de arredondamento em divisas internacionais antes do envio dos feeds aos motores de pesquisa.
Lista de verificação técnica antes da ativação no Google Shopping B2B
Conclua a verificação dos seguintes parâmetros antes de submeter os feeds de produtos:
- Conformidade de unidades de medida: Valide se
unit_pricing_measureeunit_pricing_base_measureusam apenas unidades da lista suportada pela Google e um valor base permitido. - Recálculo no processo de checkout: Certifique-se de que a introdução de quantidades abrangidas por escalões superiores reflete o custo unitário correto no carrinho.
- Integridade de GTIN e MPN: Garanta que todas as referências de embalagens e lotes possuem códigos de barras GS1 oficiais.
- Testes de stress na base de dados: Execute simulações com múltiplos acessos concorrentes às tabelas de preços escalonados.
- Verificação semântica Schema.org: Inspecione as páginas na ferramenta de testes de dados estruturados da Google para despistar falhas em
UnitPriceSpecification. - Teto de consumo de memória: Confirme que o pico de memória PHP na compilação dos ficheiros XML se mantém estável à medida que o catálogo cresce.
- Alertas automáticos de rejeição: Configure alertas para as reprovações indicadas pelo diagnóstico do Merchant Center ou pela Merchant API.
- Protocolos de segurança e cifra: Imponha TLS 1.3 e verificação estrita de credenciais em todos os pontos de acesso das APIs de faturação.
- Políticas de envio e expedição B2B: Estabeleça no Merchant Center diretrizes específicas para o transporte de cargas industriais e encomendas em paletes.
- Mecanismo de contingência (Kill Switch): Implemente um protocolo de emergência que exiba preços estáticos padrão caso as ligações externas de sincronização sofram interrupções temporárias.
A implementação bem-sucedida de tabelas de preços B2B exige uma integração perfeita entre base de dados e os requisitos dos motores de busca. Caso necessite de apoio técnico especializado para a sua loja online, entre em contacto através da nossa página de contacto.







