angularwoocommercefilterwoocommerce-rest-api

How to Get Attribute Term IDs for Filtering Products in WooCommerce API with Angular?


I’m using WooCommerce as a headless CMS with Angular. Currently, I’m working on implementing a product filter sidebar. The goal is to collect the attributes and their options (terms) for the products in the current category, and display them in the filter sidebar.

I’m calling the WooCommerce API with this endpoint:

/wp-json/wc/v3/products?category=62,4239&per_page=20&page=1&attribute=pa_brand&attribute_term=19

However, the response I’m getting for each product looks like this:

"attributes": [
  {
    "id": 3,
    "name": "Brand",
    "slug": "pa_brand",
    "position": 1,
    "visible": true,
    "variation": false,
    "options": [
      "Barebones"
    ]
  }
]

The issue is that the "options" (e.g., "Barebones") are returned as strings, but I need the term IDs for filtering purposes (i.e., attribute_term=19). So, I’m thinking of getting the term IDs separately, but when I do this, it significantly impacts the performance because I have to fetch the whole list of attributes and terms and then search for the corresponding term IDs.

Is there a better solution for gathering all attributes and their term IDs efficiently for the filter sidebar?

I tried to call the whole attributes and terms in a pagination, and compare the product's options and terms with this call, but the performance were too bad.


Solution

  • Thanks to @Rishard! I tried to customize the endpoint by adding this code in the WP snippet:

    add_filter('woocommerce_rest_prepare_product_object', function ($response, $product, $request) {
        if (!empty($response->data['attributes'])) {
            foreach ($response->data['attributes'] as &$attribute) {
                if (!empty($attribute['options'])) {
                    $options_with_ids = [];
                    foreach ($attribute['options'] as $option) {
                        $term = get_term_by('name', $option, $attribute['slug']);
                        if ($term) {
                            $options_with_ids[] = [
                                'id' => $term->term_id,
                                'name' => $term->name
                            ];
                        } else {
                            $options_with_ids[] = [
                                'id' => null,
                                'name' => $option
                            ];
                        }
                    }
                    $attribute['options'] = $options_with_ids;
                }
            }
        }
        return $response;
    }, 10, 3);
    

    Now the response is

    {
        "id": 7,
        "name": "Size",
        "slug": "pa_size",
        "position": 4,
        "visible": true,
        "variation": true,
        "options": [
            {
                "id": 123,
                "name": "L"
            },
            {
                "id": 138,
                "name": "XL"
            }
        ]
    }