Table of contents :

What Happens When You Index a WooCommerce Product?

100-days-of-elasticsearch-woocommerce-003

Table of contents :

The indexing workflow

WooCommerce does not send a product to Elasticsearch by itself. An integration plugin, a custom WordPress process, or an external synchronization service must convert the WooCommerce product into an Elasticsearch document and write it to an index.

A typical workflow looks like this:

  1. A product is created or updated in WooCommerce.
  2. WordPress fires product-related hooks such as save_post_product or WooCommerce-specific product update actions.
  3. The integration loads the product, its variations, taxonomies, attributes, stock data, and metadata.
  4. It transforms those values into a search document.
  5. The document is indexed using the Elasticsearch API.
  6. Search requests query the resulting index rather than the WordPress database.

For large catalogs, the initial synchronization is usually performed with the Elasticsearch Bulk API. Incremental updates then keep individual documents synchronized as products change.

A product is transformed into a search document

The Elasticsearch document should represent the fields needed by the storefront and search experience, not necessarily every value stored in wp_posts, wp_postmeta, and taxonomy tables.

For example, a WooCommerce product might become:

{
  "_id": "8421",
  "product_id": 8421,
  "type": "variable",
  "name": "Trail Running Jacket",
  "slug": "trail-running-jacket",
  "description": "Lightweight waterproof jacket for trail running.",
  "short_description": "Waterproof shell with breathable fabric.",
  "categories": [
    { "id": 18, "name": "Running", "slug": "running" },
    { "id": 24, "name": "Jackets", "slug": "jackets" }
  ],
  "attributes": {
    "brand": ["North Ridge"],
    "size": ["S", "M", "L"],
    "color": ["Blue"]
  },
  "price": {
    "min": 129.99,
    "max": 149.99,
    "currency": "USD"
  },
  "stock_status": "instock",
  "catalog_visibility": "visible",
  "featured": false,
  "image": {
    "url": "https://store.example.com/uploads/trail-running-jacket.jpg",
    "alt": "Blue trail running jacket"
  },
  "updated_at": "2025-02-14T10:30:00Z"
}

The document ID is commonly the WooCommerce product ID. Using a stable ID makes updates deterministic: indexing the same product again replaces or updates its existing document instead of creating duplicates.

Parent products and variations require a deliberate model

Variable products are one of the most important design decisions in WooCommerce search. A parent product contains shared information and defines the available variation attributes, while each variation may have its own SKU, price, image, stock state, and downloadable or physical properties.

There are three common indexing models:

Index only the parent product

This is suitable when shoppers search for products and select a size or color on the product page. The parent document can store aggregated values such as the minimum price, maximum price, available sizes, and available colors.

{
  "product_id": 8421,
  "type": "variable",
  "available_sizes": ["S", "M", "L"],
  "available_colors": ["Blue"],
  "price_min": 129.99,
  "price_max": 149.99
}

This model keeps result pages simple, but variation-specific filtering must be handled carefully. A naive query could match a size from one variation and a color from another unless the variation data is modeled with nested fields or evaluated in application logic.

Index each variation as a separate document

This approach is useful when customers search directly by SKU, variation-level stock, or variation-specific attributes. Each variation receives its own document, usually with a reference to the parent product.

The storefront must then group matching variations so that one product does not appear repeatedly in the results.

Store variations as nested objects

A parent product can contain a nested array of variations. This preserves the relationship between attributes, price, and stock within the same variation.

{
  "product_id": 8421,
  "name": "Trail Running Jacket",
  "variations": [
    {
      "variation_id": 8422,
      "sku": "TRJ-BLU-M",
      "size": "M",
      "color": "Blue",
      "price": 129.99,
      "stock_status": "instock"
    },
    {
      "variation_id": 8423,
      "sku": "TRJ-BLU-L",
      "size": "L",
      "color": "Blue",
      "price": 149.99,
      "stock_status": "outofstock"
    }
  ]
}

With nested mappings, a query can require size: M and color: Blue on the same variation. Without nested, Elasticsearch may combine values from different array objects and produce incorrect matches.

Mapping fields correctly

WooCommerce data contains both text and structured values. Mapping every field as text makes filtering and sorting unreliable, while mapping every field as keyword prevents useful full-text search.

A practical mapping often includes:

  • text fields for product names and descriptions
  • keyword subfields for exact matching, aggregations, and sorting
  • numeric fields for prices, ratings, dimensions, and quantities
  • boolean fields for featured or purchasable states
  • date fields for publication and update timestamps
  • nested fields when object relationships must be preserved

Example mapping:

{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "keyword": { "type": "keyword", "ignore_above": 256 }
        }
      },
      "sku": { "type": "keyword" },
      "price": { "type": "scaled_float", "scaling_factor": 100 },
      "stock_status": { "type": "keyword" },
      "categories": { "type": "nested" },
      "updated_at": { "type": "date" }
    }
  }
}

Using scaled_float for currency avoids many floating-point issues. Another valid approach is to store prices as integer minor units, such as cents, and convert them for display.

Do not rely on Elasticsearch dynamic mapping for a production catalog without reviewing the resulting mappings. A field that is first indexed as a string may later receive a numeric value and create a mapping conflict. Explicit mappings are especially important for prices, dates, ratings, and variation data.

What triggers an update

A product must be reindexed when any field used by search or filtering changes. That includes more than the product title and description.

Common update events include:

  • product creation or deletion
  • title, description, slug, or status changes
  • price or sale price changes
  • stock quantity or stock status changes
  • SKU changes
  • category, tag, or attribute changes
  • variation updates
  • featured or catalog visibility changes
  • product image changes
  • changes to custom fields used in search

Stock changes deserve special attention. Inventory may be updated by checkout, refunds, order cancellation, scheduled imports, warehouse systems, or an ERP. If the integration listens only to product edits in the WordPress admin, the search index can show products as available after they have sold out.

Use idempotent update logic so that the same event can be processed more than once safely. For example, write the complete current document with an upsert rather than applying a sequence of fragile partial changes when the source data is inexpensive to rebuild.

Deletions and visibility rules

When a product is permanently deleted, its Elasticsearch document must also be deleted. WordPress trash operations and permanent deletions may use different hooks, so the integration should account for both the business workflow and the connector’s event behavior.

Many stores should not expose every product in the index. The synchronization layer can either exclude products before indexing or index them with fields that allow every query to enforce visibility rules.

Typical exclusion conditions include:

  • post_status is not publish
  • catalog visibility is hidden
  • the product is not purchasable and should not appear in search
  • the product is out of stock and the store hides out-of-stock items
  • the product belongs to a restricted customer group
  • the product is scheduled for
Trending posts
You might also like