{"id":257429,"date":"2025-11-25T10:39:46","date_gmt":"2025-11-25T10:39:46","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/mercantor\/"},"modified":"2026-08-26T13:21:24","modified_gmt":"2026-08-26T13:21:24","slug":"mercantor","status":"publish","type":"plugin","link":"https:\/\/br.wordpress.org\/plugins\/mercantor\/","author":23367450,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.0","stable_tag":"1.3.0","tested":"7.1","requires":"6.5","requires_php":"8.1","requires_plugins":null,"header_name":"Mercantor","header_author":"Mercantor Team","header_description":"Google Merchant Center integration for WooCommerce with hybrid sync, multilingual support, and diagnostic tooling.","assets_banners_color":"8a81c4","last_updated":"2026-08-26 13:21:24","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/jajasolutions.de\/mercantor","header_author_uri":"https:\/\/jajasolutions.de","rating":0,"author_block_rating":0,"active_installs":0,"downloads":557,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.0":{"tag":"1.1.0","author":"jajasolutions","date":"2025-12-18 15:09:19"},"1.2.0":{"tag":"1.2.0","author":"jajasolutions","date":"2026-05-20 08:25:31"},"1.3.0":{"tag":"1.3.0","author":"jajasolutions","date":"2026-08-26 13:21:24"}},"upgrade_notice":{"1.3.0":"<p>Important update. Google shut down the Merchant API v1beta endpoints in February 2026, so version 1.2.0 can no longer reach Merchant Center at all. This release migrates to the v1 API and fixes several failures that silently affected syncing, product deletion, multilingual content and the product feed. Update as soon as possible; reconnect your Google account if prompted.<\/p>","1.2.0":"<p>Performance and stability release: batch sync processing, N+1 query fix, improved encryption, accessible UI, PHPStan static analysis, and CI\/CD pipeline. Fixes several edge-case bugs including memory leaks, stale closures, and price validation.<\/p>","1.1.0":"<p>New features: Scheduled Sync, Product Identifier Manager with GTIN Bulk Import, Missing Identifiers tracking, and Inline Editing.<\/p>","1.0.0":"<p>Initial release of Mercantor.<\/p>"},"ratings":[],"assets_icons":{"icon-256x256.png":{"filename":"icon-256x256.png","revision":3402420,"resolution":"256x256","location":"assets","locale":"","width":1024,"height":1024}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3402416,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.1.0","1.2.0","1.3.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3402417,"resolution":"1","location":"assets","locale":"","width":1275,"height":696},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3402417,"resolution":"2","location":"assets","locale":"","width":1063,"height":648},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3402417,"resolution":"3","location":"assets","locale":"","width":1227,"height":273},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3402417,"resolution":"4","location":"assets","locale":"","width":1261,"height":740}},"screenshots":{"1":"Dashboard with sync statistics and real-time updates","2":"Setup wizard for easy configuration","3":"Manual sync with real-time progress tracking","4":"Product feed URL generation"}},"plugin_section":[],"plugin_tags":[985,51229,65424,5418,286],"plugin_category":[45],"plugin_contributors":[251157],"plugin_business_model":[],"class_list":["post-257429","plugin","type-plugin","status-publish","hentry","plugin_tags-google-ads","plugin_tags-google-shopping","plugin_tags-merchant-center","plugin_tags-product-feed","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-jajasolutions","plugin_committers-jajasolutions"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/mercantor\/assets\/icon-256x256.png?rev=3402420","icon_2x":"https:\/\/ps.w.org\/mercantor\/assets\/icon-256x256.png?rev=3402420","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/mercantor\/assets\/screenshot-1.png?rev=3402417","caption":"Dashboard with sync statistics and real-time updates"},{"src":"https:\/\/ps.w.org\/mercantor\/assets\/screenshot-2.png?rev=3402417","caption":"Setup wizard for easy configuration"},{"src":"https:\/\/ps.w.org\/mercantor\/assets\/screenshot-3.png?rev=3402417","caption":"Manual sync with real-time progress tracking"},{"src":"https:\/\/ps.w.org\/mercantor\/assets\/screenshot-4.png?rev=3402417","caption":"Product feed URL generation"}],"raw_content":"<!--section=description-->\n<p>Mercantor is a powerful WordPress plugin that automatically syncs your WooCommerce products to Google Merchant Center, making it easy to advertise on Google Shopping and Google Ads.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>Automatic Product Sync<\/strong> - Products are automatically synced to Google Merchant Center when created or updated<\/li>\n<li><strong>Real-time Change Detection<\/strong> - Hash-based diffing only syncs changed products, saving API quota<\/li>\n<li><strong>Multilingual &amp; Multi-currency Support<\/strong> - Full support for WPML, Polylang, TranslatePress, and WooCommerce Multilingual<\/li>\n<li><strong>Multiple Target Markets<\/strong> - Sell to multiple countries with different languages and currencies<\/li>\n<li><strong>Smart Error Handling<\/strong> - Diagnostics inbox with grouped Google issues and actionable messages<\/li>\n<li><strong>Transformation Rules<\/strong> - Map and transform attributes with a rule builder and presets<\/li>\n<li><strong>Product Feed Export<\/strong> - Generate tokenized XML and CSV feeds for external tools<\/li>\n<li><strong>Scheduled Sync<\/strong> - Configure automatic hourly, twice daily, daily, or weekly sync schedules<\/li>\n<li><strong>Product Identifier Management<\/strong> - Track GTIN, MPN, and Brand coverage with bulk import functionality<\/li>\n<li><strong>GTIN Bulk Import<\/strong> - Import product identifiers via CSV with SKU or product ID matching<\/li>\n<li><strong>Background Processing<\/strong> - All syncing happens in the background using WordPress Action Scheduler<\/li>\n<li><strong>OAuth 2.0 Integration<\/strong> - Secure Google account connection<\/li>\n<li><strong>Guided Setup Wizard<\/strong> - Step-by-step configuration to get you started quickly<\/li>\n<li><strong>WP-CLI Tools<\/strong> - Sync, validate, and fetch diagnostics from the command line<\/li>\n<\/ul>\n\n<h4>Perfect For<\/h4>\n\n<ul>\n<li>E-commerce stores using WooCommerce<\/li>\n<li>Multi-language and multi-currency stores<\/li>\n<li>International sellers with multiple target markets<\/li>\n<li>Stores that need reliable Google Shopping integration<\/li>\n<li>Merchants who want automated product feed management<\/li>\n<\/ul>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li>WordPress 6.5 or higher<\/li>\n<li>WooCommerce 8.5 or higher<\/li>\n<li>PHP 8.1 or higher<\/li>\n<li>Google Merchant Center account<\/li>\n<\/ul>\n\n<h4>Documentation &amp; Support<\/h4>\n\n<ul>\n<li><a href=\"https:\/\/jajasolutions.de\/mercantor\/\">Documentation<\/a><\/li>\n<li><a href=\"https:\/\/wordpress.org\/support\/plugin\/mercantor\/\">Support Forum<\/a><\/li>\n<\/ul>\n\n<h3>External Services<\/h3>\n\n<p>Mercantor connects to Google services that you explicitly authorize in order to publish and monitor your Merchant Center listings.<\/p>\n\n<h4>Google Merchant Center API<\/h4>\n\n<ul>\n<li><strong>Endpoint<\/strong>: https:\/\/merchantapi.googleapis.com<\/li>\n<li><strong>Purpose<\/strong>: Creates, updates, and inspects Google Merchant Center product listings on your behalf.<\/li>\n<li><strong>Data sent<\/strong>: Product identifiers, titles, descriptions, image URLs, pricing, availability, shipping settings, and other product attributes required by Google. Customer or order information is never transmitted.<\/li>\n<li><strong>When data is sent<\/strong>: During the guided connection flow and whenever automated or manual sync jobs run.<\/li>\n<li><strong>Authentication<\/strong>: OAuth 2.0 using the <code>https:\/\/www.googleapis.com\/auth\/content<\/code> scope. Access and refresh tokens are stored securely in your WordPress database and can be revoked from the Mercantor settings page.<\/li>\n<li><strong>Terms of Service<\/strong>: https:\/\/policies.google.com\/terms<\/li>\n<li><strong>Privacy Policy<\/strong>: https:\/\/policies.google.com\/privacy<\/li>\n<\/ul>\n\n<h3>Privacy Policy<\/h3>\n\n<p>Mercantor connects to the Google Merchant Center API only after you complete the OAuth consent flow inside the plugin. We transmit product catalog data (titles, descriptions, pricing, availability, images, and required attributes) so your listings stay in sync with Google. Customer, order, and analytics data are never sent. OAuth credentials are stored in the WordPress options table using secure WordPress APIs and can be revoked at any time through Mercantor \u2192 Settings \u2192 Disconnect Google.\nOn uninstall, Mercantor drops its custom database tables and deletes its options (including OAuth tokens, feed tokens, and setup data) so no plugin data is retained.<\/p>\n\n<h3>Roadmap \/ Upcoming<\/h3>\n\n<ul>\n<li>Stricter Content Security Policy (CSP) rollout for the admin app<\/li>\n<li>Opt-in telemetry with diagnostics export bundle (logs, payload samples, system info)<\/li>\n<li>Scheduled health checks and automated diagnostics refresh<\/li>\n<li>In-product fix recipes and support macros for top Merchant Center errors<\/li>\n<li>Optional GA4 tracking toggle with consent-mode compatibility<\/li>\n<\/ul>\n\n<h3>Credits<\/h3>\n\n<p>Built with \u2764\ufe0f for the WordPress and WooCommerce community.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>mercantor<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory<\/li>\n<li>Activate the plugin through the 'Plugins' menu in WordPress<\/li>\n<li>Navigate to 'Mercantor' in the WordPress admin menu<\/li>\n<li>Follow the setup wizard to connect your Google Merchant Center account<\/li>\n<li>Configure your target markets and languages<\/li>\n<li>Start syncing products!<\/li>\n<\/ol>\n\n<h4>From WordPress.org<\/h4>\n\n<ol>\n<li>Go to Plugins &gt; Add New<\/li>\n<li>Search for \"Mercantor\"<\/li>\n<li>Click \"Install Now\" and then \"Activate\"<\/li>\n<li>Follow the setup wizard<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20google%20merchant%20center%20account%3F\"><h3>Do I need a Google Merchant Center account?<\/h3><\/dt>\n<dd><p>Yes, you need an active Google Merchant Center account to use this plugin.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20variable%20products%3F\"><h3>Does this work with variable products?<\/h3><\/dt>\n<dd><p>Yes, Mercantor fully supports variable products and will sync all variations.<\/p><\/dd>\n<dt id=\"can%20i%20sync%20to%20multiple%20countries%3F\"><h3>Can I sync to multiple countries?<\/h3><\/dt>\n<dd><p>Yes, you can configure multiple target countries and languages in the settings.<\/p><\/dd>\n<dt id=\"is%20my%20google%20account%20secure%3F\"><h3>Is my Google account secure?<\/h3><\/dt>\n<dd><p>Yes, we use OAuth 2.0 for secure authentication. Your credentials are never stored.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20a%20product%20has%20errors%3F\"><h3>What happens if a product has errors?<\/h3><\/dt>\n<dd><p>Mercantor will show you detailed error messages with suggested fixes in the Issues Inbox.<\/p><\/dd>\n<dt id=\"can%20i%20export%20product%20feeds%3F\"><h3>Can I export product feeds?<\/h3><\/dt>\n<dd><p>Yes, you can generate tokenized XML and CSV feed URLs for external tools.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20multisite%3F\"><h3>Does this work with multisite?<\/h3><\/dt>\n<dd><p>Currently, Mercantor is designed for single-site installations.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.0<\/h4>\n\n<ul>\n<li><strong>BREAKING (Google): Migrated to Merchant API v1.<\/strong> Google sunset the v1beta endpoints on 2026-02-28, so every sync, diagnostics and connection call in 1.2.0 failed. Products are now uploaded as productInputs into a Merchant Center data source, which Mercantor creates automatically on first sync.<\/li>\n<li>NEW: Product deletions are now propagated to Merchant Center. Previously a delete job was queued but never executed a delete call, so removed products stayed in Google indefinitely.<\/li>\n<li>NEW: Variation edits trigger a sync. WooCommerce fires woocommerce_update_product_variation from a separate data store, which was not hooked, so price and stock changes on a single variation were never uploaded.<\/li>\n<li>NEW: Automatic retry with exponential backoff for rate limits and server errors, instead of marking the product as permanently failed.<\/li>\n<li>NEW: Sync and validation failures are written to the diagnostics inbox with their actual message, plus a last_error column on the items table.<\/li>\n<li>NEW: WooCommerce HPOS and Cart\/Checkout Blocks compatibility is now declared, so the plugin no longer shows as incompatible.<\/li>\n<li>NEW: Admin notice when Google revokes access, instead of silently failing every sync.<\/li>\n<li>FIX: Fatal error in the scheduled diagnostics job \u2014 DiagnosticsManager was constructed with four arguments in the wrong order.<\/li>\n<li>FIX: Fatal error when importing Google issues \u2014 DiagnosticsManager called ErrorsDAO::insert() and ::delete_by_item_id(), neither of which existed.<\/li>\n<li>FIX: Multilingual extraction never ran. ProductExtractor::extract_single() was private, so the MultilingualProductExtractor override was silently ignored and localized titles, descriptions, permalinks and images were dropped. Affected TranslatePress most severely.<\/li>\n<li>FIX: Product feed was always empty \u2014 the query selected three columns that do not exist in the schema.<\/li>\n<li>FIX: XML feed lost every \"g:\" prefix because addChild() was called without a namespace URI, producing a feed Merchant Center cannot read.<\/li>\n<li>FIX: A \"&amp;\" in the shop name produced an empty feed title and a PHP warning; channel values are now XML-escaped.<\/li>\n<li>FIX: Feed no longer reports the SKU as a GTIN. Identifiers come from GTINResolver, and identifier_exists is set when none is found.<\/li>\n<li>FIX: Feed now exports variations with their own price, stock and images instead of only the parent product.<\/li>\n<li>FIX: Concurrent Action Scheduler workers no longer refresh the OAuth token simultaneously; the refresh is locked and happens 120 seconds before expiry.<\/li>\n<li>FIX: Token encryption upgraded to authenticated AES-256-GCM with a format marker. Undecryptable values (for example after a salt rotation) now report \"not connected\" instead of sending a corrupted bearer token. Existing AES-256-CBC values are still readable.<\/li>\n<li>FIX: Encryption failure no longer falls back to storing the token in plain text.<\/li>\n<li>FIX: ItemsDAO::update_status() keyed on the numeric row id while every caller passed the item_id string, so status updates hit no row.<\/li>\n<li>FIX: ItemsDAO::upsert() reported failure on successful updates because insert_id is 0 on the ON DUPLICATE KEY UPDATE branch.<\/li>\n<li>FIX: SettingsManager::set() reported failure when the value was unchanged.<\/li>\n<li>FIX: Feed export token and OAuth state are compared with hash_equals(); the public feed endpoint is throttled.<\/li>\n<li>FIX: Diagnostics now paginates through the whole catalog instead of reading only the first page.<\/li>\n<li>FIX: Schema migrations run after a plugin update, not only on activation.<\/li>\n<li>FIX: JavaScript strings are translatable \u2014 wp_set_script_translations() was never called.<\/li>\n<li>IMPROVED: Action Scheduler tuning is opt-in and only raises the batch size. The previous filters changed concurrency and time limits globally for WooCommerce and every other plugin on the site.<\/li>\n<li>IMPROVED: Admin bundle uses createRoot from @wordpress\/element rather than window.ReactDOM, which React 19 will no longer provide.<\/li>\n<li>IMPROVED: Tested up to WordPress 7.1 and WooCommerce 11.0; declares Requires Plugins: woocommerce.<\/li>\n<li>IMPROVED: Namespace casing unified; test suite and static analysis now run against the shipped source and pass.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>IMPROVED: Batch processing for product sync - eliminates memory issues on large catalogs<\/li>\n<li>IMPROVED: Atomic batch upsert in ItemsDAO - resolves N+1 query performance bottleneck<\/li>\n<li>IMPROVED: Paginated product queries with configurable batch size<\/li>\n<li>IMPROVED: Extracted ContainerBuilder for cleaner plugin architecture<\/li>\n<li>IMPROVED: Refactored sync_single_product into smaller, testable methods<\/li>\n<li>IMPROVED: Immutable product transformation - prevents unintended DTO mutation<\/li>\n<li>IMPROVED: React admin UI uses Context API instead of prop drilling<\/li>\n<li>IMPROVED: Setup wizard fully typed - removed all unsafe <code>any<\/code> casts<\/li>\n<li>IMPROVED: Accessible UI - ARIA labels for progress bars, keyboard-navigable issues inbox, semantic wizard stepper<\/li>\n<li>IMPROVED: OAuth token encryption uses OPENSSL_RAW_DATA with graceful fallback<\/li>\n<li>FIX: Transient-based polling replaced with direct status reads in SyncOrchestrator<\/li>\n<li>FIX: get_pending_jobs_count() now correctly returns int instead of array<\/li>\n<li>FIX: JSON decode errors handled gracefully in MerchantApiClient<\/li>\n<li>FIX: PHP version requirement unified to 8.1 across all configuration files<\/li>\n<li>FIX: empty(0) bug in ProductValidator price check<\/li>\n<li>FIX: Memory leak from missing interval cleanup in IssuesInbox<\/li>\n<li>FIX: Stale closure in SyncProgress resolved with useRef<\/li>\n<li>FIX: Unsafe CSV parsing replaced with proper delimiter handling<\/li>\n<li>FIX: Raw SQL in SyncController replaced with DAO pattern<\/li>\n<li>FIX: Dead code removed from SyncOrchestrator<\/li>\n<li>NEW: Error boundaries for React admin UI with graceful recovery<\/li>\n<li>NEW: GitHub Actions CI\/CD pipeline (PHP 8.1-8.3 matrix, frontend lint &amp; build)<\/li>\n<li>NEW: Pre-commit hooks via Husky and lint-staged<\/li>\n<li>NEW: PHPStan level 6 static analysis with WordPress extension<\/li>\n<li>NEW: Integration tests for ProductTransformer and ProductValidator<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>NEW: Scheduled Sync - Configure automatic sync schedules (hourly, twice daily, daily, weekly)<\/li>\n<li>NEW: Product Identifier Manager - Dashboard widget showing GTIN, MPN, Brand coverage<\/li>\n<li>NEW: GTIN Bulk Import - Import product identifiers via CSV with SKU or product ID matching<\/li>\n<li>NEW: Missing Identifiers Tab - Quickly find and edit products missing GTINs, MPNs, or Brands<\/li>\n<li>NEW: Inline Identifier Editing - Edit product identifiers directly from the dashboard<\/li>\n<li>NEW: Identifier Export - Export all product identifiers to CSV<\/li>\n<li>IMPROVED: Action Scheduler integration for reliable background processing<\/li>\n<li>IMPROVED: Better error handling and user feedback<\/li>\n<li>FIX: SyncScheduler now correctly handles invalid interval values<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Automatic product sync to Google Merchant Center<\/li>\n<li>OAuth 2.0 Google account connection<\/li>\n<li>Multilingual and multi-currency support<\/li>\n<li>Real-time change detection<\/li>\n<li>Background job processing with Action Scheduler<\/li>\n<li>Comprehensive error diagnostics<\/li>\n<li>Manual sync with progress tracking<\/li>\n<li>Product feed export (XML\/CSV)<\/li>\n<li>Guided setup wizard<\/li>\n<\/ul>","raw_excerpt":"Seamlessly sync your WooCommerce products to Google Merchant Center with real-time updates, multilingual support, and automatic error handling.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/257429","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=257429"}],"author":[{"embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/jajasolutions"}],"wp:attachment":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=257429"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=257429"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=257429"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=257429"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=257429"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=257429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}