Merchant API code sample to filter disapproved products.

### C#

    // Copyright 2025 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.


    using System;
    using Google.Api.Gax;
    using Google.Apis.Auth.OAuth2;
    using Google.Shopping.Merchant.Products.V1;
    using Google.Shopping.Merchant.Reports.V1;
    using Newtonsoft.Json;
    using static MerchantApi.Authenticator;

    namespace MerchantApi
    {
        public class FilterDisapprovedProductsSample
        {
            // Filters disapproved products using the Reporting API and then fetches
            // full product details for each.
            public void FilterDisapprovedProducts(string merchantId)
            {
                Console.WriteLine("=================================================================");
                Console.WriteLine("Filtering for Disapproved Products");
                Console.WriteLine("=================================================================");

                // Authenticate using either oAuth or service account
                ICredential auth = Authenticator.Authenticate(
                    MerchantConfig.Load(),
                    ProductsServiceClient.DefaultScopes[0]);

                // Create a client for the Reports API.
                ReportServiceClient reportClient = new ReportServiceClientBuilder
                {
                    Credential = auth
                }.Build();

                // Create a client for the Products API.
                ProductsServiceClient productsClient = new ProductsServiceClientBuilder
                {
                    Credential = auth
                }.Build();

                // The parent has the format: accounts/{accountId}
                string parent = $"accounts/{merchantId}";

                // The query to select disapproved products from the product_view.
                string query =
                    "SELECT offer_id, id, title, price " +
                    "FROM product_view " +
                    "WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'";

                // Create the search request for the Reports API.
                SearchRequest request = new SearchRequest
                {
                    Parent = parent,
                    Query = query,
                    PageSize = 1000 // Optional: specify the page size.
                };

                try
                {
                    Console.WriteLine("Sending search report request for disapproved products...");
                    // Call the Reports.Search API method.
                    PagedEnumerable<SearchResponse, ReportRow> response = reportClient.Search(request);
                    Console.WriteLine("Received search reports response.");

                    // Iterate over all report rows. This handles pagination automatically.
                    foreach (ReportRow row in response)
                    {
                        Console.WriteLine("---");
                        Console.WriteLine("Found disapproved product from Product View:");
                        Console.WriteLine(JsonConvert.SerializeObject(row.ProductView, Formatting.Indented));

                        // Construct the full product name for the GetProduct request.
                        // Format: accounts/{account}/products/{product}
                        string productName = ProductName.FromAccountProduct(merchantId, row.ProductView.Id).ToString();

                        Console.WriteLine("\nFetching full product details with GetProduct method...");

                        // Get the full product details by calling the GetProduct method.
                        GetProductRequest getRequest = new GetProductRequest { Name = productName };
                        Product product = productsClient.GetProduct(getRequest);

                        Console.WriteLine(JsonConvert.SerializeObject(product, Formatting.Indented));
                    }
                    Console.WriteLine("---");
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Failed to search reports for disapproved products: {e.Message}");
                }
            }

            public static void Main(string[] args)
            {
                // Load configuration settings.
                var config = MerchantConfig.Load();
                string merchantId = config.MerchantId.Value.ToString();

                if (string.IsNullOrEmpty(merchantId))
                {
                    Console.WriteLine("MerchantId is not set in the MerchantConfig.json file.");
                    return;
                }

                // Create an instance of the sample and run it.
                var sample = new FilterDisapprovedProductsSample();
                sample.FilterDisapprovedProducts(merchantId);
            }
        }
    }

### AppsScript

    // Copyright 2025 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.


    /**
     * Demonstrates how to filter disapproved products using the Merchant API Reports service.
     */
    function filterDisapprovedProducts() {
      // IMPORTANT:
      // Enable the Merchant API Reports sub-API Advanced Service and call it
      // "MerchantApiReports"
      // Enable the Merchant API Products sub-API Advanced Service and call it
      // "MerchantApiProducts"

      // Replace this with your Merchant Center ID.
      const accountId = '<INSERT_MERCHANT_CENTER_ID>';

      // Construct the parent name
      const parent = 'accounts/' + accountId;

      try {
        console.log('Sending search Report request');
        // Set pageSize to the maximum value (default: 1000)
        const pageSize = 1000;
        let pageToken;
        // The query below is an example of a query for the productView that gets product informations
        // for all disapproved products.
        const query = 'SELECT offer_id,' +
            'id,' +
            'price,' +
            'title' +
            ' FROM product_view' +
            ' WHERE aggregated_reporting_context_status = "NOT_ELIGIBLE_OR_DISAPPROVED"';


        // Call the Reports.search API method. Use the pageToken to iterate through
        // all pages of results.
        do {
          const response =
              MerchantApiReports.Accounts.Reports.search({query, pageSize, pageToken}, parent);
          for (const reportRow of response.results) {
            console.log('Printing data from Product View:');
            console.log(reportRow);

            // OPTIONALLY, you can get the full product details by calling the GetProduct method.
            const productName = parent + '/products/' + reportRow.getProductView().getId();
            const product = MerchantApiProducts.Accounts.Products.get(productName);
            console.log(product);
          }
          pageToken = response.nextPageToken;
        } while (pageToken); // Exits when there is no next page token.
      } catch (e) {
        console.log('ERROR!');
        console.log('Error message:' + e.message);
      }
    }


### Java

    // Copyright 2025 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.

    package shopping.merchant.samples.products.v1;

    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.shopping.merchant.products.v1.GetProductRequest;
    import com.google.shopping.merchant.products.v1.Product;
    import com.google.shopping.merchant.products.v1.ProductsServiceClient;
    import com.google.shopping.merchant.products.v1.ProductsServiceSettings;
    import com.google.shopping.merchant.reports.v1.ReportRow;
    import com.google.shopping.merchant.reports.v1.ReportServiceClient;
    import com.google.shopping.merchant.reports.v1.ReportServiceClient.SearchPagedResponse;
    import com.google.shopping.merchant.reports.v1.ReportServiceSettings;
    import com.google.shopping.merchant.reports.v1.SearchRequest;
    import shopping.merchant.samples.utils.Authenticator;
    import shopping.merchant.samples.utils.Config;

    /**
     * This class demonstrates how to get the list of all the disapproved products for a given merchant
     * center account.
     */
    public class FilterDisapprovedProductsSample {

      // Gets the product details for a given product using the GetProduct method.
      public static void getProduct(GoogleCredentials credential, Config config, String productName)
          throws Exception {

        // Creates service settings using the credentials retrieved above.
        ProductsServiceSettings productsServiceSettings =
            ProductsServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();

        // Calls the API and catches and prints any network failures/errors.
        try (ProductsServiceClient productsServiceClient =
            ProductsServiceClient.create(productsServiceSettings)) {

          // The name has the format: accounts/{account}/products/{productId}
          GetProductRequest request = GetProductRequest.newBuilder().setName(productName).build();
          Product response = productsServiceClient.getProduct(request);
          System.out.println(response);
        } catch (Exception e) {
          System.out.println(e);
        }
      }

      // Filters the disapproved products for a given Merchant Center account using the Reporting API.
      // Then, it prints the product details for each disapproved product.
      public static void filterDisapprovedProducts(Config config) throws Exception {
        GoogleCredentials credential = new Authenticator().authenticate();

        ReportServiceSettings reportServiceSettings =
            ReportServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();

        try (ReportServiceClient reportServiceClient =
            ReportServiceClient.create(reportServiceSettings)) {

          // The parent has the format: accounts/{accountId}
          String parent = String.format("accounts/%s", config.getAccountId().toString());
          // The query below is an example of a query for the productView that gets product informations
          // for all disapproved products.
          String query =
              "SELECT offer_id,"
                  + "id,"
                  + "title,"
                  + "price"
                  + " FROM product_view"
                  // aggregated_reporting_context_status can be one of the following values:
                  // NOT_ELIGIBLE_OR_DISAPPROVED, ELIGIBLE, PENDING, ELIGIBLE_LIMITED,
                  // AGGREGATED_REPORTING_CONTEXT_STATUS_UNSPECIFIED
                  + " WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'";

          // Create the search report request.
          SearchRequest request = SearchRequest.newBuilder().setParent(parent).setQuery(query).build();

          System.out.println("Sending search report request for Product View.");
          // Calls the Reports.search API method.
          SearchPagedResponse response = reportServiceClient.search(request);
          System.out.println("Received search reports response: ");
          // Iterates over all report rows in all pages and prints each report row in separate line.
          // Automatically uses the `nextPageToken` if returned to fetch all pages of data.
          for (ReportRow row : response.iterateAll()) {
            System.out.println("Printing data from Product View:");
            System.out.println(row);
            // Optionally, you can get the full product details by calling the GetProduct method.
            String productName =
                "accounts/"
                    + config.getAccountId().toString()
                    + "/products/"
                    + row.getProductView().getId();
            System.out.println("Getting full product details by calling GetProduct method:");
            getProduct(credential, config, productName);
          }

        } catch (Exception e) {
          System.out.println("Failed to search reports for Product View.");
          System.out.println(e);
        }
      }

      public static void main(String[] args) throws Exception {
        Config config = Config.load();
        filterDisapprovedProducts(config);
      }
    }

### Node.js

    // Copyright 2025 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.

    'use strict';
    const fs = require('fs');
    const authUtils = require('../../authentication/authenticate.js');
    const {ProductsServiceClient} = require('@google-shopping/products').v1;
    const {ReportServiceClient} = require('@google-shopping/reports').v1;

    /**
     * Gets the product details for a given product using the GetProduct method.
     * @param {!Object} authClient - The authenticated Google API client.
     * @param {string} productName - The name of the product to retrieve, in the
     *   format: accounts/{account}/products/{productId}.
     */
    async function getProduct(authClient, productName) {
      // Create options object for the client, including authentication.
      const productOptions = {authClient: authClient};

      // Create the Products API client.
      const productsClient = new ProductsServiceClient(productOptions);

      try {
        // Construct the request object.
        const request = {name: productName};
        // Call the API to get the product.
        // getProduct returns a Promise that resolves to an array.
        // The first element is the product resource.
        const response = await productsClient.getProduct(request);
        console.log(response);
      } catch (error) {
        // Log any errors that occur during the API call.
        console.log(error);
      }
    }

    /**
     * Filters disapproved products for a given Merchant Center account using the
     * Reporting API. Then, it prints the product details for each disapproved
     * product.
     * @param {!Object} authClient - The authenticated Google API client.
     * @param {string} merchantId - The Merchant Center account ID.
     */
    async function filterDisapprovedProducts(authClient, merchantId) {
      // Create options object for the client, including authentication.
      const reportOptions = {authClient: authClient};

      // Create the Report API client.
      const reportServiceClient = new ReportServiceClient(reportOptions);

      try {
        // Construct the parent resource name for the report query.
        const parent = `accounts/${merchantId}`;

        // Define the query to select disapproved products.
        // aggregated_reporting_context_status can be one of the following values:
        // NOT_ELIGIBLE_OR_DISAPPROVED, ELIGIBLE, PENDING, ELIGIBLE_LIMITED,
        // AGGREGATED_REPORTING_CONTEXT_STATUS_UNSPECIFIED
        const query = `SELECT offer_id, id, title, price
          FROM product_view
          WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'`;

        // Construct the search request.
        const searchRequest = {
          parent: parent,
          query: query,
        };

        console.log('Sending search report request for Product View.');
        // Call the Reports.search API method. This returns an async iterable.
        const iterable = reportServiceClient.searchAsync(searchRequest);
        console.log('Received search reports response: ');

        // Iterate over all report rows in the response.
        for await (const row of iterable) {
          console.log('Printing data from Product View:');
          console.log(row.productView);

          // Construct the full product resource name from the report row.
          // Assumes row.productView and row.productView.id are populated,
          // which should be the case based on the query.
          const productName = `accounts/${merchantId}/products/${row.productView.id}`;

          // OPTIONAL: Get and print the full product details using GetProduct.
          console.log('Getting full product details by calling GetProduct method:');
          // Get and print the full product details.
          await getProduct(authClient, productName);
        }
      } catch (error) {
        console.log('Failed to search reports for Product View.');
        // Log any errors that occur during the report search or processing.
        console.log(error);
      }
    }

    /**
     * Main function to execute the sample.
     */
    async function main() {
      try {
        // Retrieve application configuration.
        const config = authUtils.getConfig();

        // Read merchant ID from the merchant-info.json file.
        const merchantInfo = JSON.parse(
          fs.readFileSync(config.merchantInfoFile, 'utf8'),
        );
        const merchantId = merchantInfo.merchantId;

        // Authenticate and get the OAuth2 client.
        const authClient = await authUtils.getOrGenerateUserCredentials();

        // Call the function to filter disapproved products and get their details.
        await filterDisapprovedProducts(authClient, merchantId);
      } catch (error) {
        // Log any errors that occur during setup or authentication.
        console.error(error.message);
        process.exitCode = 1;
      }
    }

    main();

### PHP

    <?php
    /**
     * Copyright 2025 Google LLC
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     https://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    require_once __DIR__ . '/../../../vendor/autoload.php';
    require_once __DIR__ . '/../../Authentication/Authentication.php';
    require_once __DIR__ . '/../../Authentication/Config.php';
    use Google\ApiCore\ApiException;
    use Google\Shopping\Merchant\Products\V1\Client\ProductsServiceClient;
    use Google\Shopping\Merchant\Products\V1\GetProductRequest;
    use Google\Shopping\Merchant\Reports\V1\Client\ReportServiceClient;
    use Google\Shopping\Merchant\Reports\V1\SearchRequest;

    /**
     * This class demonstrates how to get the list of all the disapproved products for a given merchant
     * center account.
     */
    class FilterDisapprovedProducts
    {
        /**
         * Gets the product details for a given product using the GetProduct method.
         *
         * @param mixed $credentials The OAuth credentials.
         * @param array $config The configuration data, including 'accountId'.
         * @param string $productName The full resource name of the product to retrieve.
         *      Format: accounts/{account}/products/{product}
         */
        private static function getProduct(
            $credentials,
            array $config,
            string $productName
        ): void {
            // Creates options config containing credentials for the client to use.
            $options = ['credentials' => $credentials];

            // Creates a ProductsServiceClient.
            $productsServiceClient = new ProductsServiceClient($options);

            // Calls the API and catches and prints any network failures/errors.
            try {
                // Construct the GetProductRequest.
                // The name has the format: accounts/{account}/products/{productId}
                $request = new GetProductRequest(['name' => $productName]);

                // Make the API call.
                $response = $productsServiceClient->getProduct($request);

                // Prints the retrieved product.
                // Protobuf messages are printed as JSON strings for readability.
                print $response->serializeToJsonString() . "\n";
            } catch (ApiException $e) {
                // Prints any errors that occur during the API call.
                printf("ApiException was thrown: %s\n", $e->getMessage());
            }
        }

        /**
         * Filters disapproved products for a given Merchant Center account using the Reporting API,
         * then prints the details for each disapproved product.
         *
         * @param array $config The configuration data used for authentication and
         *      getting the account ID.
         */
        public static function filterDisapprovedProductsSample(array $config): void
        {
            // Gets the OAuth credentials to make the request.
            $credentials = Authentication::useServiceAccountOrTokenFile();

            // Creates options config containing credentials for the Report client to use.
            $reportClientOptions = ['credentials' => $credentials];

            // Creates a ReportServiceClient.
            $reportServiceClient = new ReportServiceClient($reportClientOptions);

            // The parent resource name for the report.
            // Format: accounts/{accountId}
            $parent = sprintf("accounts/%s", $config['accountId']);

            // The query to select disapproved products from the product_view.
            // This query retrieves offer_id, id, title, and price for products
            // that are 'NOT_ELIGIBLE_OR_DISAPPROVED'.
            $query = "SELECT offer_id, id, title, price FROM product_view"
                . " WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'";

            // Create the search report request.
            $request = new SearchRequest([
                'parent' => $parent,
                'query' => $query
            ]);

            print "Sending search report request for Product View.\n";
            // Calls the Reports.search API method.
            try {
                $response = $reportServiceClient->search($request);
                print "Received search reports response: \n";

                // Iterates over all report rows in all pages.
                // The client library automatically handles pagination.
                foreach ($response->iterateAllElements() as $row) {
                    print "Printing data from Product View:\n";
                    // Prints the ReportRow object as a JSON string.
                    print $row->serializeToJsonString() . "\n";

                    // Get the full product resource name from the report row.
                    // The `id` field in ProductView is the product's full resource name.
                    // Format: `accounts/{account}/products/{product}`
                    $productName = $parent . "/products/" . $row->getProductView()->getId();
                    // OPTIONAL: Call getProduct to retrieve and print full product details.
                    // Pass the original credentials and config.
                    print "Getting full product details by calling GetProduct method:\n";
                    self::getProduct($credentials, $config, $productName);
                }
            } catch (ApiException $e) {
                // Prints any errors that occur during the API call.
                printf("ApiException was thrown: %s\n", $e->getMessage());
            }
        }

        /**
         * Helper to execute the sample.
         */
        public function callSample(): void
        {
            $config = Config::generateConfig();
            self::filterDisapprovedProductsSample($config);
        }
    }

    // Run the script
    $sample = new FilterDisapprovedProducts();
    $sample->callSample();

### Python

    # -*- coding: utf-8 -*-
    # Copyright 2025 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    """A module to filter disapproved products."""

    from examples.authentication import configuration
    from examples.authentication import generate_user_credentials
    from google.shopping.merchant_products_v1 import GetProductRequest
    from google.shopping.merchant_products_v1 import ProductsServiceClient
    from google.shopping.merchant_reports_v1 import ReportServiceClient
    from google.shopping.merchant_reports_v1 import SearchRequest

    # Read the merchant account ID from the configuration file.
    # This is a global variable used by the functions below.
    _ACCOUNT_ID = configuration.Configuration().read_merchant_info()


    def get_product(credentials, product_name: str):
      """Gets the product details for a given product name.

      Args:
        credentials: The OAuth2 credentials.
        product_name: The full resource name of the product, e.g.,
          "accounts/{account}/products/{product}".
      """
      # Create a Products API client.
      products_service_client = ProductsServiceClient(credentials=credentials)

      # Prepare the GetProduct request.
      # The name has the format: accounts/{account}/products/{productId}
      request = GetProductRequest(name=product_name)

      # Call the API and print the response or any errors.
      try:
        response = products_service_client.get_product(request=request)
        print(response)
      except RuntimeError as e:
        print(f"Failed to get product {product_name}:")
        print(e)


    def filter_disapproved_products():
      """Filters disapproved products and prints their details."""
      # Get OAuth2 credentials.
      credentials = generate_user_credentials.main()

      # Create a Report API client.
      report_service_client = ReportServiceClient(credentials=credentials)

      # Construct the parent resource name for the account.
      # The parent has the format: accounts/{accountId}
      parent = f"accounts/{_ACCOUNT_ID}"

      # Define the query to select disapproved products.
      # This query retrieves product information for all disapproved products.
      # aggregated_reporting_context_status can be one of the following values:
      # NOT_ELIGIBLE_OR_DISAPPROVED, ELIGIBLE, PENDING, ELIGIBLE_LIMITED,
      # AGGREGATED_REPORTING_CONTEXT_STATUS_UNSPECIFIED
      query = (
          "SELECT offer_id, id, title, price "
          "FROM product_view "
          "WHERE aggregated_reporting_context_status ="
          "'NOT_ELIGIBLE_OR_DISAPPROVED'"
      )

      # Create the search report request.
      request = SearchRequest(parent=parent, query=query)

      print("Sending search report request for Product View.")
      try:
        # Call the Reports.search API method.
        response = report_service_client.search(request=request)
        print("Received search reports response: ")

        # Iterate over all report rows.
        # The client library automatically handles pagination.
        for row in response:
          print("Printing data from Product View:")
          print(row)

          # Construct the full product resource name using the product_view.id
          # (which is the REST ID like "en~GB~123") from the report.
          # The product_view.id from the report is the {product_id} part.
          product_name = (
              f"accounts/{_ACCOUNT_ID}/products/{row.product_view.id}"
          )

          # OPTIONAL, get full product details by calling the GetProduct method.
          print("Getting full product details by calling GetProduct method:")
          get_product(credentials, product_name)

      except RuntimeError as e:
        print(e)


    if __name__ == "__main__":
      filter_disapproved_products()