title / cause / fix. * Wording explains the issue and shows what to edit; it makes no promise about review outcomes. * * @return array */ function feedfixer_issue_explanations(): array { $gtin = array( 'title' => 'Missing or invalid GTIN', 'cause' => 'Google could not find a valid barcode number (GTIN, such as UPC or EAN) for this product, or the number does not pass its check-digit test.', 'fix' => 'Enter the barcode from the packaging or the manufacturer in Product data > Inventory > GTIN, UPC, EAN, or ISBN (WooCommerce 9.2 and later; Google for WooCommerce reads it from version 2.9.0), then update the product. A product without a manufacturer barcode has no GTIN: leave the field blank.', ); $image = array( 'title' => 'Image problem', 'cause' => 'The main product image is too small, a single flat colour, or a generic placeholder, so Google may not be able to use it.', 'fix' => 'Replace the Product image in the right-hand sidebar of the product editor with a real photo of the product, with no text, logo or watermark: at least 500x500 px (the minimum Google sets for all products from 31 January 2027); Google recommends 1500x1500 px or larger.', ); $price = array( 'title' => 'Price does not match your website', 'cause' => 'The price sent to Google differs from the price shown on the product page, or it is outside a realistic range.', 'fix' => 'Check Product data > General > Regular price and Sale price, make sure they match what shoppers see, then re-sync the product.', ); $policy = array( 'title' => 'Policy issue', 'cause' => 'Google flagged this product as possibly breaking a Shopping policy, for example restricted or adult content.', 'fix' => 'Review the Product name, Product description and Product image in the product editor, remove restricted content, or exclude the product in Google for WooCommerce > Product feed. Read the linked Google policy page for details.', ); $landing = array( 'title' => 'Landing page problem', 'cause' => 'Google could not open the product page, or the page address does not belong to the website claimed in your Merchant Center account.', 'fix' => 'Open the product permalink in a private window and confirm it loads; check Settings > Permalinks and WooCommerce > Settings > General, and that your site URL matches the one in Merchant Center.', ); $gfw_tab = 'the Google for WooCommerce tab of the Product data box'; $apparel = function ( string $name, string $where ): array { return array( 'title' => "Missing $name", 'cause' => "Apparel products need a $name value so shoppers can filter and Google can classify them, and none was found.", 'fix' => "Set $name in $where, then update the product.", ); }; return array( 'missing_gtin' => $gtin, 'incorrect_identifier' => $gtin, 'reserved_gtin' => array( 'title' => 'Reserved or example GTIN', 'cause' => 'The barcode entered is reserved for internal or example use and is not a real product barcode.', 'fix' => 'Replace it with the real barcode from the manufacturer in Product data > Inventory > GTIN, UPC, EAN, or ISBN, or leave the field blank if the product has no barcode.', ), 'invalid_upc' => array( 'title' => 'Invalid UPC', 'cause' => 'The UPC has the wrong number of digits or fails the check-digit test.', 'fix' => 'Correct the 12-digit UPC in Product data > Inventory > GTIN, UPC, EAN, or ISBN, then update the product.', ), 'missing_brand' => array( 'title' => 'Missing brand', 'cause' => 'No brand name was found for this product, and Google expects one for most products.', 'fix' => 'Enter the brand in the Google for WooCommerce tab of the Product data box (for your own products, use your domain name), then update the product.', ), 'image_too_small' => $image, 'image_single_color' => $image, 'generic_image' => $image, 'price_mismatch' => $price, 'price_out_of_range' => $price, 'availability_mismatch' => array( 'title' => 'Availability does not match your website', 'cause' => 'The stock status sent to Google differs from what the product page shows, for example in stock in the feed but out of stock on the site.', 'fix' => 'Check Product data > Inventory > Stock status (and Manage stock / Stock quantity), then re-sync the product.', ), 'missing_shipping' => array( 'title' => 'Missing shipping information', 'cause' => 'Google could not find shipping costs or delivery rules for the country this product is sold in.', 'fix' => 'Add shipping zones and rates in WooCommerce > Settings > Shipping, and check the shipping options in Google for WooCommerce > Settings.', ), 'landing_page_error' => $landing, 'url_does_not_match_homepage' => $landing, 'title_too_long' => array( 'title' => 'Title too long', 'cause' => 'The product title is longer than the 150 characters Google accepts, so it may be cut off or rejected.', 'fix' => 'Shorten the name in the Product name field at the top of the product editor.', ), 'missing_title' => array( 'title' => 'Missing title', 'cause' => 'The product has no title to send to Google.', 'fix' => 'Fill in the Product name field at the top of the product editor.', ), 'description_too_short' => array( 'title' => 'Description too short', 'cause' => 'The product description has too little text for Google to understand what you sell.', 'fix' => 'Expand the Product description in the main editor box (and the Product short description) with real product details.', ), 'missing_description' => array( 'title' => 'Missing description', 'cause' => 'The product has no description to send to Google.', 'fix' => 'Write a Product description in the main editor box of the product page.', ), 'missing_google_product_category' => array( 'title' => 'Missing Google product category', 'cause' => 'No Google product category was set, so Google cannot place the product in its taxonomy.', 'fix' => 'Make the Product name, Product description and Product categories describe the product clearly so Google can place it, then update the product.', ), 'policy_violation' => $policy, 'restricted_adult_content' => $policy, 'missing_size' => $apparel( 'size', $gfw_tab ), 'missing_color' => $apparel( 'colour', $gfw_tab ), 'missing_gender' => $apparel( 'gender', $gfw_tab ), 'missing_age_group' => $apparel( 'age group', $gfw_tab ), 'incorrect_product_type' => array( 'title' => 'Incorrect product type', 'cause' => 'The product type or category sent to Google does not look like it matches the product.', 'fix' => 'Check the Product categories box in the product editor, and the category mapping in Google for WooCommerce > Product feed.', ), ); } /** * Explain one stored issue row. Returns raw (unescaped) strings. * * @param array $row Keys: id, product_id, issue, code, severity, product, action, action_url. * @return array{title:string, cause:string, fix:string, action_url:string, known:bool} */ function feedfixer_explain_issue( array $row ): array { $str = function ( string $key ) use ( $row ): string { return isset( $row[ $key ] ) && is_scalar( $row[ $key ] ) ? trim( (string) $row[ $key ] ) : ''; }; $code = strtolower( $str( 'code' ) ); $map = feedfixer_issue_explanations(); if ( '' !== $code && isset( $map[ $code ] ) ) { return array( 'title' => $map[ $code ]['title'], 'cause' => $map[ $code ]['cause'], 'fix' => $map[ $code ]['fix'], 'action_url' => $str( 'action_url' ), 'known' => true, ); } $issue = $str( 'issue' ); $action = $str( 'action' ); return array( 'title' => '' !== $issue ? $issue : 'Merchant Center reported an issue', 'cause' => '' !== $issue ? $issue : 'Google reported a problem with this product but did not give details FeedFixer can read.', 'fix' => '' !== $action ? $action : 'Open the product in Google Merchant Center to read the full issue description, then edit the matching product field.', 'action_url' => $str( 'action_url' ), 'known' => false, ); }