diff --git a/retail/snippets/README.md b/retail/snippets/README.md
new file mode 100644
index 00000000000..9c44aecbfae
--- /dev/null
+++ b/retail/snippets/README.md
@@ -0,0 +1,26 @@
+# Vertex AI Search for commerce Samples
+
+This directory contains Java samples for [Vertex AI Search for commerce](https://cloud.google.com/retail/docs/search-basic#search).
+
+## Prerequisites
+
+To run these samples, you must have:
+
+1. **A Google Cloud Project** with the [Vertex AI Search for commerce API](https://console.cloud.google.com/apis/library/retail.googleapis.com) enabled.
+2. **Vertex AI Search for commerce** set up with a valid catalog and serving configuration (placement).
+3. **Authentication**: These samples use [Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/provide-credentials-adc).
+ - If running locally, you can set up ADC by running:
+ ```bash
+ gcloud auth application-default login
+ ```
+4. **IAM Roles**: The service account or user running the samples needs the `roles/retail.viewer` (Retail Viewer) role or higher.
+
+## Samples
+
+- **[Search.java](src/main/java/com/example/search/Search.java)**: Basic search request showing both text search and browse search (using categories).
+- **[SearchPagination.java](src/main/java/com/example/search/SearchPagination.java)**: Shows how to use `next_page_token` to paginate through search results.
+- **[SearchOffset.java](src/main/java/com/example/search/SearchOffset.java)**: Shows how to use `offset` to skip a specified number of results.
+
+## Documentation
+
+For more information, see the [Vertex AI Search for commerce documentation](https://docs.cloud.google.com/retail/docs/search-basic#search).
\ No newline at end of file
diff --git a/retail/snippets/pom.xml b/retail/snippets/pom.xml
new file mode 100644
index 00000000000..0066e78fb56
--- /dev/null
+++ b/retail/snippets/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ 4.0.0
+ com.example.retail
+ retail-samples
+ 1.0-SNAPSHOT
+
+
+
+ shared-configuration
+ com.google.cloud.samples
+ 1.2.2
+
+
+
+ 21
+ 21
+
+
+
+
+
+ libraries-bom
+ com.google.cloud
+ import
+ pom
+ 26.80.0
+
+
+
+
+
+
+ com.google.cloud
+ google-cloud-retail
+
+
+
+
+ truth
+ com.google.truth
+ test
+ 1.4.5
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.14.3
+ test
+
+
+
diff --git a/retail/snippets/src/main/java/com/example/search/Search.java b/retail/snippets/src/main/java/com/example/search/Search.java
new file mode 100644
index 00000000000..587eabc2da2
--- /dev/null
+++ b/retail/snippets/src/main/java/com/example/search/Search.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+// [START retail_v2_search_request]
+
+import com.google.cloud.retail.v2.BranchName;
+import com.google.cloud.retail.v2.Product;
+import com.google.cloud.retail.v2.SearchRequest;
+import com.google.cloud.retail.v2.SearchResponse;
+import com.google.cloud.retail.v2.SearchResponse.SearchResult;
+import com.google.cloud.retail.v2.SearchServiceClient;
+import com.google.cloud.retail.v2.SearchServiceClient.SearchPagedResponse;
+import com.google.cloud.retail.v2.ServingConfigName;
+import java.io.IOException;
+import java.util.List;
+
+public class Search {
+ public static void main(String[] args) throws IOException {
+ String projectId = "my-project-id";
+ String visitorId = "my-visitor-id";
+ String query = "my search query";
+ List categories = List.of("category");
+
+ search(projectId, visitorId, query, categories);
+ }
+
+ public static void search(
+ String projectId, String visitorId, String query, List categories)
+ throws IOException {
+ try (SearchServiceClient searchServiceClient = SearchServiceClient.create()) {
+ ServingConfigName servingConfigName =
+ ServingConfigName.of(projectId, "global", "default_catalog", "default_search");
+ BranchName branchName =
+ BranchName.of(projectId, "global", "default_catalog", "default_branch");
+ SearchRequest searchRequest =
+ SearchRequest.newBuilder()
+ .setPlacement(servingConfigName.toString())
+ .setBranch(branchName.toString())
+ .setVisitorId(visitorId)
+ .setQuery(query)
+ .addAllPageCategories(categories)
+ .setPageSize(10)
+ .build();
+ SearchPagedResponse response = searchServiceClient.search(searchRequest);
+
+ SearchResponse searchResponse = response.getPage().getResponse();
+
+ System.out.println("Found " + searchResponse.getResultsCount() + " results in current page");
+ for (SearchResult searchResult : searchResponse.getResultsList()) {
+ Product product = searchResult.getProduct();
+ System.out.println("---- Search Result ----");
+ System.out.println("Product Name: " + product.getName());
+ }
+ }
+ }
+}
+// [END retail_v2_search_request]
diff --git a/retail/snippets/src/main/java/com/example/search/SearchOffset.java b/retail/snippets/src/main/java/com/example/search/SearchOffset.java
new file mode 100644
index 00000000000..1a8edd681da
--- /dev/null
+++ b/retail/snippets/src/main/java/com/example/search/SearchOffset.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+// [START retail_v2_search_offset]
+
+import com.google.cloud.retail.v2.BranchName;
+import com.google.cloud.retail.v2.Product;
+import com.google.cloud.retail.v2.SearchRequest;
+import com.google.cloud.retail.v2.SearchResponse;
+import com.google.cloud.retail.v2.SearchResponse.SearchResult;
+import com.google.cloud.retail.v2.SearchServiceClient;
+import com.google.cloud.retail.v2.SearchServiceClient.SearchPagedResponse;
+import com.google.cloud.retail.v2.ServingConfigName;
+import java.io.IOException;
+
+public class SearchOffset {
+ public static void main(String[] args) throws IOException {
+ String projectId = "my-project-id";
+ String visitorId = "my-visitor-id";
+ String query = "my search query";
+ int offset = 10;
+
+ searchWithOffset(projectId, visitorId, query, offset);
+ }
+
+ public static void searchWithOffset(String projectId, String visitorId, String query, int offset)
+ throws IOException {
+ try (SearchServiceClient searchServiceClient = SearchServiceClient.create()) {
+ ServingConfigName servingConfigName =
+ ServingConfigName.of(projectId, "global", "default_catalog", "default_search");
+ BranchName branchName =
+ BranchName.of(projectId, "global", "default_catalog", "default_branch");
+ SearchRequest searchRequest =
+ SearchRequest.newBuilder()
+ .setPlacement(servingConfigName.toString())
+ .setBranch(branchName.toString())
+ .setVisitorId(visitorId)
+ .setQuery(query)
+ .setPageSize(10)
+ .setOffset(offset)
+ .build();
+ SearchPagedResponse response = searchServiceClient.search(searchRequest);
+
+ SearchResponse searchResponse = response.getPage().getResponse();
+
+ System.out.println("Found " + searchResponse.getResultsCount() + " results in current page");
+ for (SearchResult searchResult : searchResponse.getResultsList()) {
+ Product product = searchResult.getProduct();
+ System.out.println("---- Search Result ----");
+ System.out.println("Product Name: " + product.getName());
+ }
+ }
+ }
+}
+// [END retail_v2_search_offset]
diff --git a/retail/snippets/src/main/java/com/example/search/SearchPagination.java b/retail/snippets/src/main/java/com/example/search/SearchPagination.java
new file mode 100644
index 00000000000..ec69a83fd04
--- /dev/null
+++ b/retail/snippets/src/main/java/com/example/search/SearchPagination.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+// [START retail_v2_search_pagination]
+
+import com.google.cloud.retail.v2.BranchName;
+import com.google.cloud.retail.v2.Product;
+import com.google.cloud.retail.v2.SearchRequest;
+import com.google.cloud.retail.v2.SearchResponse.SearchResult;
+import com.google.cloud.retail.v2.SearchServiceClient;
+import com.google.cloud.retail.v2.SearchServiceClient.SearchPage;
+import com.google.cloud.retail.v2.SearchServiceClient.SearchPagedResponse;
+import com.google.cloud.retail.v2.ServingConfigName;
+import java.io.IOException;
+
+public class SearchPagination {
+ public static void main(String[] args) throws IOException {
+ String projectId = "my-project-id";
+ String visitorId = "my-visitor-id";
+ String query = "my search query";
+ int pageSize = 10;
+
+ searchWithPagination(projectId, visitorId, query, pageSize);
+ }
+
+ public static void searchWithPagination(
+ String projectId, String visitorId, String query, int pageSize) throws IOException {
+ try (SearchServiceClient searchServiceClient = SearchServiceClient.create()) {
+ ServingConfigName servingConfigName =
+ ServingConfigName.of(projectId, "global", "default_catalog", "default_search");
+ BranchName branchName =
+ BranchName.of(projectId, "global", "default_catalog", "default_branch");
+ SearchRequest request =
+ SearchRequest.newBuilder()
+ .setPlacement(servingConfigName.toString())
+ .setBranch(branchName.toString())
+ .setVisitorId(visitorId)
+ .setQuery(query)
+ .setPageSize(pageSize)
+ .build();
+ int currentPage = 0;
+ while (true) {
+ SearchPagedResponse response = searchServiceClient.search(request);
+
+ SearchPage page = response.getPage();
+ currentPage++;
+ System.out.println("\nResults of page number " + currentPage + ":");
+ System.out.println(
+ "Found " + page.getResponse().getResultsCount() + " results in current page");
+ for (SearchResult searchResult : page.getResponse().getResultsList()) {
+ Product product = searchResult.getProduct();
+ System.out.println("---- Search Result ----");
+ System.out.println("Product Name: " + product.getName());
+ }
+
+ if (page.hasNextPage()) {
+ request = request.toBuilder().setPageToken(page.getNextPageToken()).build();
+ } else {
+ System.out.println("\nNo more available pages.");
+ break;
+ }
+ }
+ }
+ }
+}
+// [END retail_v2_search_pagination]
diff --git a/retail/snippets/src/test/java/com/example/search/SearchIT.java b/retail/snippets/src/test/java/com/example/search/SearchIT.java
new file mode 100644
index 00000000000..d5c88d71c35
--- /dev/null
+++ b/retail/snippets/src/test/java/com/example/search/SearchIT.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.google.cloud.retail.v2.Product;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class SearchIT {
+ private static PrintStream origPrintStream;
+ private static ByteArrayOutputStream bout;
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static final String VISITOR_ID = "test_visitor";
+ private static final int NUM_PRODUCTS_TO_TEST = 2;
+ private static final String PRODUCT_TITLE = "Hot Java Testing";
+ private static final List CATEGORIES = List.of("Beverages");
+ private static List productsToTest;
+
+ private static void requireEnvVar(String varName) {
+ assertNotNull(
+ "Environment variable " + varName + " is required to perform these tests.",
+ System.getenv(varName));
+ }
+
+ @BeforeAll
+ public static void setUp() throws InterruptedException, IOException {
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ // Create products to be searched
+ productsToTest = Utils.createProductsToTest(NUM_PRODUCTS_TO_TEST, PROJECT_ID, PRODUCT_TITLE);
+ Utils.waitForProductsToBeIndexed(PROJECT_ID, productsToTest, PRODUCT_TITLE);
+
+ origPrintStream = System.out;
+ bout = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(bout));
+ }
+
+ @AfterAll
+ public static void tearDown() throws IOException {
+ // Clean up products created for testing
+ for (Product product : productsToTest) {
+ Utils.deleteProduct(product.getName());
+ }
+
+ System.setOut(origPrintStream);
+ }
+
+ @Test
+ public void testSearch() throws Exception {
+ Search.search(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, CATEGORIES);
+ String output = bout.toString();
+ assertThat(output).contains("Found " + NUM_PRODUCTS_TO_TEST + " results in current page");
+ assertThat(output).contains("Product Name:");
+ }
+
+ @Test
+ public void testSearchWithoutQueryString() throws Exception {
+ Search.search(PROJECT_ID, VISITOR_ID, "", CATEGORIES);
+ String output = bout.toString();
+ assertThat(output).contains("Product Name:");
+ }
+
+ @Test
+ public void testSearch_productsNotFound() throws Exception {
+ Search.search(PROJECT_ID, VISITOR_ID, "INVALID_QUERY_VALUE_FOR_TEST", CATEGORIES);
+ String output = bout.toString();
+ assertThat(output).contains("Found " + 0 + " results in current page");
+ }
+}
diff --git a/retail/snippets/src/test/java/com/example/search/SearchOffsetIT.java b/retail/snippets/src/test/java/com/example/search/SearchOffsetIT.java
new file mode 100644
index 00000000000..06d39c9793c
--- /dev/null
+++ b/retail/snippets/src/test/java/com/example/search/SearchOffsetIT.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.google.api.gax.rpc.InvalidArgumentException;
+import com.google.cloud.retail.v2.Product;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class SearchOffsetIT {
+ private static PrintStream origPrintStream;
+ private static ByteArrayOutputStream bout;
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static final String VISITOR_ID = "test_visitor";
+ private static final int NUM_PRODUCTS_TO_TEST = 2;
+ private static final String PRODUCT_TITLE = "Hot Java Testing";
+ private static List productsToTest;
+
+ private static void requireEnvVar(String varName) {
+ assertNotNull(
+ "Environment variable " + varName + " is required to perform these tests.",
+ System.getenv(varName));
+ }
+
+ @BeforeAll
+ public static void setUp() throws InterruptedException, IOException {
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ // Create products to be searched
+ productsToTest = Utils.createProductsToTest(NUM_PRODUCTS_TO_TEST, PROJECT_ID, PRODUCT_TITLE);
+ Utils.waitForProductsToBeIndexed(PROJECT_ID, productsToTest, PRODUCT_TITLE);
+
+ origPrintStream = System.out;
+ bout = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(bout));
+ }
+
+ @AfterAll
+ public static void tearDown() throws IOException {
+ // Clean up products created for testing
+ for (Product product : productsToTest) {
+ Utils.deleteProduct(product.getName());
+ }
+
+ System.setOut(origPrintStream);
+ }
+
+ @Test
+ public void testSearchWithOffset() throws Exception {
+ int offset = 1;
+ SearchOffset.searchWithOffset(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, offset);
+ String output = bout.toString();
+ assertThat(output)
+ .contains("Found " + (NUM_PRODUCTS_TO_TEST - offset) + " results in current page");
+ assertThat(output).contains("Product Name:");
+ }
+
+ @Test
+ public void testSearchWithOffset_offsetEqualsZero() throws Exception {
+ int offset = 0;
+ SearchOffset.searchWithOffset(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, offset);
+ String output = bout.toString();
+ assertThat(output).contains("Found " + NUM_PRODUCTS_TO_TEST + " results in current page");
+ assertThat(output).contains("Product Name:");
+ }
+
+ @Test
+ public void testSearchWithOffset_offsetTooLarge_foundZeroResults() throws Exception {
+ int offset = 5;
+ SearchOffset.searchWithOffset(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, offset);
+ String output = bout.toString();
+ assertThat(output).contains("Found 0 results in current page");
+ }
+
+ @Test
+ public void testSearchWithOffset_negativeOffset_throwsInvalidArgumentException()
+ throws Exception {
+ int offset = -1;
+ assertThrows(
+ InvalidArgumentException.class,
+ () -> SearchOffset.searchWithOffset(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, offset));
+ }
+}
diff --git a/retail/snippets/src/test/java/com/example/search/SearchPaginationIT.java b/retail/snippets/src/test/java/com/example/search/SearchPaginationIT.java
new file mode 100644
index 00000000000..5af535ee448
--- /dev/null
+++ b/retail/snippets/src/test/java/com/example/search/SearchPaginationIT.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.google.api.gax.rpc.InvalidArgumentException;
+import com.google.cloud.retail.v2.Product;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class SearchPaginationIT {
+ private static PrintStream origPrintStream;
+ private static ByteArrayOutputStream bout;
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static final String VISITOR_ID = "test_visitor";
+ private static final int NUM_PRODUCTS_TO_TEST = 2;
+ private static final String PRODUCT_TITLE = "Hot Java Testing";
+ private static List productsToTest;
+
+ private static void requireEnvVar(String varName) {
+ assertNotNull(
+ "Environment variable " + varName + " is required to perform these tests.",
+ System.getenv(varName));
+ }
+
+ @BeforeAll
+ public static void setUp() throws InterruptedException, IOException {
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ // Create products to be searched
+ productsToTest = Utils.createProductsToTest(NUM_PRODUCTS_TO_TEST, PROJECT_ID, PRODUCT_TITLE);
+ Utils.waitForProductsToBeIndexed(PROJECT_ID, productsToTest, PRODUCT_TITLE);
+
+ origPrintStream = System.out;
+ bout = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(bout));
+ }
+
+ @AfterAll
+ public static void tearDown() throws IOException {
+ // Clean up products created for testing
+ for (Product product : productsToTest) {
+ Utils.deleteProduct(product.getName());
+ }
+
+ System.setOut(origPrintStream);
+ }
+
+ @Test
+ public void testSearchWithPaginationAndMultiplePages() throws Exception {
+ SearchPagination.searchWithPagination(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, 1);
+ String output = bout.toString();
+ assertThat(output).contains("Results of page number 1:");
+ assertThat(output).contains("Found 1 results in current page");
+ assertThat(output).contains("Results of page number 2:");
+ assertThat(output).contains("Found 1 results in current page");
+ assertThat(output).contains("No more available pages.");
+ }
+
+ @Test
+ public void testSearchWithPaginationAndSinglePage() throws Exception {
+ SearchPagination.searchWithPagination(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, 10);
+ String output = bout.toString();
+ assertThat(output).contains("Results of page number 1:");
+ assertThat(output).contains("Found " + NUM_PRODUCTS_TO_TEST + " results in current page");
+ assertThat(output).contains("No more available pages.");
+ }
+
+ @Test
+ public void testSearchWithPagination_negativePageSize_throwsInvalidArgumentException()
+ throws Exception {
+ int pageSize = -1;
+ assertThrows(
+ InvalidArgumentException.class,
+ () ->
+ SearchPagination.searchWithPagination(PROJECT_ID, VISITOR_ID, PRODUCT_TITLE, pageSize));
+ }
+}
diff --git a/retail/snippets/src/test/java/com/example/search/Utils.java b/retail/snippets/src/test/java/com/example/search/Utils.java
new file mode 100644
index 00000000000..24f2fd9f5e6
--- /dev/null
+++ b/retail/snippets/src/test/java/com/example/search/Utils.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2026 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.
+ */
+
+package com.example.search;
+
+import com.google.cloud.retail.v2.BranchName;
+import com.google.cloud.retail.v2.CreateProductRequest;
+import com.google.cloud.retail.v2.DeleteProductRequest;
+import com.google.cloud.retail.v2.PriceInfo;
+import com.google.cloud.retail.v2.Product;
+import com.google.cloud.retail.v2.Product.Availability;
+import com.google.cloud.retail.v2.Product.Type;
+import com.google.cloud.retail.v2.ProductServiceClient;
+import com.google.cloud.retail.v2.SearchRequest;
+import com.google.cloud.retail.v2.SearchServiceClient;
+import com.google.cloud.retail.v2.SearchServiceClient.SearchPagedResponse;
+import com.google.cloud.retail.v2.ServingConfigName;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class Utils {
+
+ public static List createProductsToTest(
+ int amount, String projectId, String productTitle) throws IOException {
+ List productIds = new ArrayList<>();
+ for (int i = 0; i < amount; i++) {
+ productIds.add(UUID.randomUUID().toString());
+ }
+ return createProducts(projectId, productIds, productTitle);
+ }
+
+ public static List createProducts(
+ String projectId, List productIds, String productTitle) throws IOException {
+ BranchName branchName = BranchName.of(projectId, "global", "default_catalog", "default_branch");
+
+ float price = 8.0f;
+ float originalPrice = 12.0f;
+
+ PriceInfo priceInfo =
+ PriceInfo.newBuilder()
+ .setPrice(price)
+ .setOriginalPrice(originalPrice)
+ .setCurrencyCode("USD")
+ .build();
+
+ Product generatedProduct =
+ Product.newBuilder()
+ .setTitle(productTitle)
+ .setType(Type.PRIMARY)
+ .addCategories("Beverages")
+ .addBrands("Google")
+ .setPriceInfo(priceInfo)
+ .setAvailability(Availability.IN_STOCK)
+ .build();
+ List createdProducts = new ArrayList<>();
+ try (ProductServiceClient serviceClient = ProductServiceClient.create()) {
+ for (String productId : productIds) {
+ CreateProductRequest createProductRequest =
+ CreateProductRequest.newBuilder()
+ .setProduct(generatedProduct)
+ .setProductId(productId)
+ .setParent(branchName.toString())
+ .build();
+
+ createdProducts.add(serviceClient.createProduct(createProductRequest));
+ }
+ }
+ return createdProducts;
+ }
+
+ public static void deleteProduct(String productName) throws IOException {
+ DeleteProductRequest deleteProductRequest =
+ DeleteProductRequest.newBuilder().setName(productName).build();
+
+ try (ProductServiceClient serviceClient = ProductServiceClient.create()) {
+ serviceClient.deleteProduct(deleteProductRequest);
+ }
+ }
+
+ public static boolean areProductsReadyToTest(String projectId, String query, int amountOfProducts)
+ throws IOException {
+ try (SearchServiceClient searchServiceClient = SearchServiceClient.create()) {
+ ServingConfigName servingConfigName =
+ ServingConfigName.of(projectId, "global", "default_catalog", "default_search");
+ BranchName branchName =
+ BranchName.of(projectId, "global", "default_catalog", "default_branch");
+ SearchRequest searchRequest =
+ SearchRequest.newBuilder()
+ .setPlacement(servingConfigName.toString())
+ .setBranch(branchName.toString())
+ .setVisitorId("test_visitor")
+ .setQuery(query)
+ .setPageSize(amountOfProducts)
+ .build();
+ SearchPagedResponse response = searchServiceClient.search(searchRequest);
+
+ return response.getPage().getResponse().getResultsCount() >= amountOfProducts;
+ }
+ }
+
+ public static void waitForProductsToBeIndexed(
+ String projectId, List products, String productTitle)
+ throws InterruptedException, IOException {
+ for (int i = 0; i < 3; i++) {
+ Thread.sleep(10000);
+ if (areProductsReadyToTest(projectId, productTitle, products.size())) {
+ break;
+ }
+ }
+ }
+}