The v1beta version was discontinued on February 28, 2026, causing all
API calls to return HTTP 409 errors. Updated all three endpoint paths
(products list, test connection, reports search) to use v1.
Also updated product attribute access to match v1 schema changes:
- Product.attributes → Product.productAttributes
- attributes.gtin / attributes.gtins → productAttributes.gtins
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All prices now shown with VAT included:
- Cost: converted using wc_get_price_including_tax()
- Your Price: already tax-inclusive
- Suggested: from Google, always tax-inclusive
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed from $product->get_meta() to get_post_meta()
- get_post_meta() is more reliable for custom meta fields
- Fixed cost decimal places to 2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Brand column (from _brand meta) before SKU
- Cost column (from _cost meta) before Your Price
- Helps evaluate suggested prices against actual product cost
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added SKU column as second column after checkbox
- SKU displayed in monospace font for readability
- Slightly reduced product name truncation to fit table
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Removed margin check from manual update display
- Update button now shows for ALL products that have Google price suggestions
- Margin setting only applies to automatic updates (protection against auto price drops)
- Full manual control: user decides whether to accept each suggestion
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Added "% Diff" column showing percentage difference between your price and suggested
- Changed minimum price logic: uses "Current Price - Margin%" instead of cost-based
- Updated settings description to explain the new logic
- Example: With 10% margin, €100 product won't be suggested below €90
This works better for stores without cost data - protects against excessive price drops.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
eCommerce priority: conversions drive revenue
- Products with highest predicted conversion increase shown first
- Products without Google insight data moved to end of list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major rewrite using correct Google Merchant API:
- Use price_insights_product_view table (correct API endpoint)
- Fetch suggested_price and predicted performance changes
- Show predicted impact on impressions, clicks, conversions
New features:
- Individual "Update" button per product
- Bulk update with checkbox selection
- Pagination (50 products per page)
- Sort by potential gain (highest first)
Price handling:
- Always use tax-inclusive prices for comparison with Google
- Convert back to store format when saving (handles tax-exclusive stores)
- Set as sale price when updating
UI improvements:
- Color-coded gain/loss values
- Color-coded predicted changes
- Summary stats showing products that can increase/decrease
- Total potential gain calculation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Simplified query to only select essential fields:
- product_view.offer_id
- product_view.gtin
- product_view.title
- benchmark_price
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Merchant API Reports require product fields to be prefixed:
- product_view.offer_id instead of offer_id
- product_view.gtin instead of gtin
- product_view.title, product_view.price, etc.
- benchmark_price remains without prefix (it's a report-level field)
Also update response parsing to extract from nested productView object.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The new Merchant API uses snake_case table names:
- Changed from 'PriceCompetitivenessProductView' to 'price_competitiveness_product_view'
- Updated field names in SELECT query
- Added debug logging to see actual API response structure
- Handle both camelCase and snake_case field names in response
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Features:
- Fetch competitor benchmark prices from Google Price Competitiveness Report
- New get_all_benchmark_prices() method in Google API class
- Display competitor price instead of own Google price
- Calculate recommended price (slightly below competitor)
- Show potential gain/loss per product if price is optimized
- Color-coded status:
- Green: Your price is cheaper (opportunity to increase)
- Blue: Competitive (within 2% of competitor)
- Red: Expensive (above competitor)
- Summary statistics showing:
- Products with benchmark data
- Count by status (cheaper/competitive/expensive)
- Total potential gain if all prices optimized
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Google Merchant Center prices are always tax-inclusive, so now
the local WooCommerce price is also displayed with tax included
using wc_get_price_including_tax() for a fair comparison.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Based on actual API response analysis:
- offerId is at top level (e.g., "220216" = WooCommerce product ID)
- gtin is nested in attributes.gtin as an ARRAY (e.g., ["850018802833"])
- price is nested in attributes.price.amountMicros
Changes:
- Index Google products by each GTIN in the attributes.gtin array
- Also check attributes.gtins (alternative field name)
- Index by MPN if available
- Update find_product_by_identifier to check array GTINs with in_array()
- Fix price extraction to check attributes.price first, then top-level
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Log sample Google product structure to help debug matching
- Expand matching to check nested 'attributes' field (new API format)
- Extract offerId from productId field (channel:lang:country:id format)
- Extract offerId from name field (resource path format)
- Return debug info in AJAX response (sample keys, sample product)
- Log debug info in browser console
- Remove alert popup since button is now working
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added console.log at script load, IIFE execution, init, and bindEvents
- Added check for button element existence in console
- Added alert on button click for immediate visual feedback
- Added logging before AJAX request with URL and nonce
- Added beforeSend callback for AJAX request
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Load Product Comparison" button in admin
- Display WooCommerce products with local price (sale/regular)
- Show Google Merchant Center price for each product
- Show match type (offerId vs gtin) and match status
- Helps debug product matching issues
- Limited to 50 in-stock products for performance
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Match products where WooCommerce SKU is stored as GTIN in Google
- Also search Reports API by GTIN when SKU looks like a barcode
- Supports stores that use barcodes (UPC/EAN) as their SKU
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace service account authentication with OAuth 2.0 user flow
- Add "Authorize with Google" button in admin settings
- Handle OAuth callback and token exchange
- Store refresh token for automatic access token renewal
- Add revoke authorization functionality
- Update admin UI to show authorization status
- Update price updater to use new OAuth credentials
- Add CSRF protection with state parameter
This change supports organizations that have disabled service account
key creation via iam.disableServiceAccountKeyCreation policy.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix ISE 500 error on plugin activation:
- Defer wc_get_logger() call in Logger class (lazy initialization)
- Move plugin init to plugins_loaded hook with priority 20
- Remove invalid Google_Service_ShoppingContent_Reports instantiation
- Migrate from deprecated Content API to new Merchant API:
- Rewrite Google API class with direct REST calls
- Implement JWT authentication using PHP OpenSSL
- Use WordPress wp_remote_* functions for HTTP requests
- Support Price Competitiveness reports for competitor pricing
- Remove all Composer dependencies:
- Delete vendor/ directory (~50 packages)
- Delete composer.json and composer.lock
- Remove setup scripts and related documentation
- Plugin is now fully self-contained with no external dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>