woocommerce / google-listings-and-ads

Sync your store with Google to list products for free, run paid ads, and track performance straight from your store dashboard.
https://woo.com/products/google-listings-and-ads/
GNU General Public License v3.0
46 stars 21 forks source link

Improve Google Product Type Sync #2279

Open sukafia opened 7 months ago

sukafia commented 7 months ago

Google uses both product_type and product_categoryto match search queries with relevant products. While Google automatically assigns the product category, the product type is manually specified.

Google Listing & Ads syncs the selected Woo product categories as product types. However, the product types are synced randomly, meaning any category can be assigned as the primary product type, instead of the most relevant option.

Some things to note

One consideration raised internally in p1708081999866279/1706088275.307189-slack-C0410KV3YLW is adding a UI option for specifying the preferred category to sync as product type.

I'm creating this issue for further discussion, tracking, and prioritization.

How to reproduce the problem

  1. Create a product and assign multiple categories (parent and child)
  2. Duplicate the product or create other products with multiple categories
  3. Notice the product type is randomly assigned in Google Merchant Center

Describe the solution you'd like

An option to specify the suitable Google product type

Technical consideration

UI Idea

Epl4Ua.png

Ticket

Reported in 7600082-zen

sukafia commented 7 months ago

Per @mikkamp advice, the filter woocommerce_gla_product_attribute_values can be used to control how product types are synced. Merchants this is an urgent concern to can use the filter to control how attributes are synced by adding a custom code snippet.

There's a description of how to use the filter here - you'd need to return an array with the attribute you want to override.

mikkamp commented 7 months ago

Just wanted to clarify a few points for better tracking:

However, we're randomly syncing the values without specifying an order. (e.g.prioritizing the child categories)

Not specifying an order means the default order is by term name. So for example for a case where we have assigned the following categories, they'll initially be returned in alphabetical order:

We then include all parents with children, but don't change the order. So we'll end up with:

The only thing we can specify in this case is whether we select the parent category "Mens Clothing", which would place "T-shirts as the "first" category. However if the colour would have been "Blue" then it would have been returned as the first category. Which is why an option to specify that "T-shirts" would be the preferred category, is needed.

Assigning multiple product types is possible when syncing products. The place where it mentions it's a problem is:

If you use product type to organize your bidding and reporting in Google Ads, we recommend that you submit only 1 value. (If you submit more than one value, only the first value will be used.)

The Google Listings & Ads extension doesn't organize bidding or reporting by product type. So it would be through usage of these methods within the Google Merchant Center dashboard or through another linked system.

Aaronomary1 commented 7 months ago

I'm currently working on a code snippet to map WooCommerce product categories to Google product types in a more refined manner for our Google Listings and Ads integration (prioritizing the child category > parent category for my needs). To achieve this, I've drafted a code snippet that:

Here's the snippet (Intended for functions.php):

add_filter('woocommerce_gla_product_attribute_values', 'customize_product_types_for_gla', 10, 3);

function customize_product_types_for_gla($attributes, $wc_product, $gla_product) {
    // Fetch all term ids including parents and children for the product.
    $product_id = $wc_product->get_id();
    $category_ids = wc_get_product_term_ids($product_id, 'product_cat');

    // Prioritize child categories by sorting them based on their hierarchy.
    $sorted_category_ids = sort_categories_by_hierarchy($category_ids);

    // Convert sorted category IDs to Google product types format.
    $google_product_types = convert_product_types($sorted_category_ids);

    // Override the productTypes attribute for Google Listings and Ads.
    $attributes['productTypes'] = $google_product_types;

    return $attributes;
}

function sort_categories_by_hierarchy($category_ids) {
    $categories_with_depth = [];

    foreach ($category_ids as $category_id) {
        $term = get_term($category_id, 'product_cat');
        $depth = count(get_ancestors($category_id, 'product_cat', 'taxonomy'));
        $categories_with_depth[] = ['id' => $category_id, 'depth' => $depth, 'term' => $term];
    }

    // Sort categories by depth (child categories first).
    usort($categories_with_depth, function ($a, $b) {
        return $a['depth'] <=> $b['depth'];
    });

    // Return sorted category IDs.
    return array_map(function ($category) {
        return $category['id'];
    }, $categories_with_depth);
}

function convert_product_types($sorted_category_ids) {
    $product_types = [];
    foreach ($sorted_category_ids as $category_id) {
        $term = get_term($category_id, 'product_cat');
        if ($term && !is_wp_error($term)) {
            $product_types[] = $term->name;
        }
    }

    // Construct the product type string according to Google's guidelines.
    return implode(' > ', array_reverse($product_types));
}

Could someone on your team review this code to ensure it aligns with best practices and possibly suggest improvements? Specifically, I'm looking for feedback on:

mikkamp commented 7 months ago

We don't have the capacity to test/support custom code. But let me see if there are a few suggestions I can give.

Ideally in situations like this the WC Crud classes can be used fully, but since they don't allow sorting by depth count there needs to be a balance with switching to using WordPress functions.

Aaronomary1 commented 6 months ago

Is there any update on this issue?