A useful WooCommerce search experience starts with a deliberate product model. Before importing products into Weaviate, decide which product facts should be searchable, which should be filterable, which should be returned to the storefront, and which should remain in WooCommerce as the source of truth.
Define the search contract first
A product collection should support the queries your storefront and merchandising tools actually perform. Typical requirements include:
- Semantic search such as waterproof commuter backpack for a laptop.
- Keyword matching for product names, SKUs, brands, and technical specifications.
- Structured filters for price, stock status, category, brand, attributes, and ratings.
- Catalog scoping by language, channel, customer group, or store.
- Stable identifiers that let the application retrieve the authoritative WooCommerce product.
Write these requirements down before choosing properties. A field that is useful for a filter should not be represented only inside one large description string, and a field that is only needed for display does not necessarily need its own vectorized representation.
Choose the document granularity
WooCommerce products can include simple products, variable products, and variations. The right collection design depends on how customers search.
One object per parent product
This is usually the simplest starting point. A parent product contains the title, description, category information, shared attributes, price range, and availability summary. It works well when variations do not have substantially different names, descriptions, or searchable use cases.
One object per purchasable variation
Use variation-level objects when size, color, capacity, compatibility, or other options materially affect search results. For example, a red waterproof jacket in size medium may need a different price, stock state, SKU, or image from the parent product.
When indexing variations, include the parent product title and context in the variation’s searchable text. A document that contains only Blue, Large will produce poor semantic matches because it lacks the product concept.
A separate collection for products and variations
This approach is useful for large catalogs or applications that need both product-level discovery and precise purchasable-option lookup. Store a stable parent identifier on variation objects and decide whether the application searches both collections or searches products first and expands variations afterward.
Separate searchable text from filterable properties
Do not put every value into a single concatenated description. Store structured values separately so Weaviate can apply filters efficiently and predictably.
- Searchable text: name, short description, long description, brand, category names, and selected attributes.
- Exact or filterable values: WooCommerce product ID, variation ID, SKU, brand key, category keys, stock state, purchasable state, and visibility.
- Numeric values: current price, regular price, sale price, rating, review count, weight, and dimensions where relevant.
- Operational values: permalink, image URL, tax class, currency, and an index version. These are generally returned to the application rather than used for semantic matching.
Keep both display labels and stable keys when taxonomy terms can change. For example, store category_ids for filtering and category_names for search context. A renamed category should not require rewriting business logic that depends on its identifier.
A practical collection shape
The following conceptual model is suitable for a product-level collection. Property names are illustrative; align them with the naming conventions used by your integration.
ProductSearchDocument
- woo_product_id: UUID or TEXT
- parent_product_id: UUID or TEXT
- sku: TEXT
- name: TEXT
- searchable_text: TEXT
- brand_key: TEXT
- brand_name: TEXT
- category_keys: TEXT_ARRAY
- category_names: TEXT_ARRAY
- attribute_text: TEXT
- price: NUMBER
- regular_price: NUMBER
- on_sale: BOOLEAN
- in_stock: BOOLEAN
- purchasable: BOOLEAN
- catalog_visibility: TEXT
- rating: NUMBER
- review_count: INT
- permalink: TEXT
- image_url: TEXT
- currency: TEXT
- language: TEXT
- updated_at: DATE
- source_version: TEXT
The exact data types should follow the values you send. A price should be numeric rather than formatted currency text. A stock flag should be Boolean rather than the string 'instock' if your filter only needs to know whether the item can be purchased.
Build a deliberate searchable representation
The vector should represent the information customers use to describe a product. A practical input can combine selected fields into a readable document:
Waterproof Commuter Backpack
Brand: Northline
Categories: Backpacks, Travel
Features: waterproof laptop compartment, padded straps, recycled nylon
Fits laptops up to 16 inches
Do not automatically concatenate every metadata field. Internal IDs, URLs, timestamps, stock flags, and prices usually add noise to semantic search. Keep those values as properties for filtering, ranking, or response construction.
Descriptions may contain HTML from WooCommerce. Strip tags, decode entities, normalize whitespace, and remove shortcodes before creating the searchable text. Preserve meaningful headings and list content where possible, because technical specifications often carry more retrieval value than marketing copy.
Model categories and attributes for WooCommerce
WooCommerce attributes can be global taxonomies or custom product attributes. Normalize them before indexing. For example, represent a color attribute as a stable key such as color:red and retain a display value such as Red. This avoids ambiguity when labels are translated or formatted differently between products.
For attributes that customers commonly filter, consider dedicated properties or a predictable key-value representation. A dedicated numeric property such as screen_size_inches is easier to filter than a text value such as Screen size: 16-inch. For less important attributes, an array of normalized tokens can be sufficient.
Use references only when the relationship matters
Weaviate references can connect products to brands, categories, or related objects, but references are not always the best first design for a catalog search index. If every search result needs category names and brand labels, denormalizing those values onto the product object reduces query complexity and makes the search response easier to assemble.
Use references when the related entity has its own lifecycle or is queried independently. For example, a separate brand collection may make sense when brands have descriptions, logos, landing pages, and their own recommendation logic. Keep the product’s stable brand key as well so filtering does not depend entirely on a graph traversal.
Choose vectorization and indexing settings intentionally
Use a vectorizer that matches your deployment and embedding pipeline. If embeddings are generated outside Weaviate, configure the collection for self-provided vectors and send the vector with each object. If Weaviate generates vectors, ensure the configured model handles the language and content type used by the catalog.
Not every property needs to contribute to the vector. Exclude operational fields and identifiers from vectorization where the configured client supports per-property settings. Keep inverted indexes available for fields used in exact filters, range filters, sorting, or keyword lookup.
For a WooCommerce catalog, the most important filter behavior usually includes:
- Exact matching for product and taxonomy keys.
- Boolean filtering for stock and purchasability.
- Range filtering for prices, ratings, and measurements.
- Text matching for SKUs and selected technical fields.
- Date filtering for incremental synchronization.
Keep WooCommerce as the source of truth
Weaviate should normally be treated as a search projection, not the authoritative commerce database. Store enough denormalized data to render a useful result, but retrieve current pricing, inventory, purchasing rules, and variation details from WooCommerce or the service responsible for those values when accuracy is critical.
Every indexed object should have a deterministic identifier derived from the WooCommerce product or variation ID. Include an updated_at value and a source version so synchronization jobs can detect stale documents. When a product is deleted, unpublished, or excluded from catalog visibility, remove it or mark it unavailable according to the behavior required by your application.
Example synchronization payload
A normalized object sent to the collection might look like this:
{
'woo_product_id': 'product-1842',
'parent_product_id': 'product-1842',
'sku': 'NL-BAG-16-BLK',
'name': 'Waterproof Commuter Backpack',
'searchable_text': 'Waterproof Commuter Backpack. Brand: Northline. Categories: Backpacks, Travel. Features: waterproof laptop compartment, padded straps, recycled nylon. Fits laptops up to 16 inches.',
'brand_key': 'northline',
'category_keys': ['backpacks', 'travel'],
'category_names': ['Backpacks', 'Travel'],
'attribute_text': 'color:black capacity:24l laptop_size:16',
'price': 129.0,
'on_sale': True,
'in_stock': True,
'purchasable': True,
'catalog_visibility': 'visible',
'currency': 'USD',
'updated_at': '2025-01-15T10:30:00Z',
'source_version': 'woocommerce-2025-01-15-10-30-00'
}
In a real JSON request, Boolean values must be lowercase true and false. The example uses Python-style literals only to keep the object readable; your integration should serialize data with its normal JSON library.
Test the schema with real agency use cases
Before committing to the collection, test representative queries rather than only checking whether objects import successfully. Include broad natural-language searches, exact SKU lookups, filters combined with semantic queries, products with many variations, translated content, missing prices, and out-of-stock products.
Measure whether the returned objects contain enough information to build the result card, whether filters exclude the correct products, and whether variation-level results create duplicate parent products. If duplicate parents are a problem, group results in the application or change the indexing granularity.
A strong initial design is usually small: one searchable text property, explicit filter properties, deterministic WooCommerce identifiers, and only the denormalized display data the storefront needs. Expand the schema when a tested requirement justifies it, rather than mirroring every WooCommerce field into the vector database.