---
title: "Summarise Shopify Products with LangChain | EnConvert"
description: "How to extract structured Shopify product data into a LangChain pipeline with EnConvert Distill, returning schema-matched fields from product pages in one call"
canonical: "https://www.enconvert.com/solutions/summarise-shopify-products-with-langchain-enconvert"
locale: "en"
---

# How to Summarise Shopify Products with LangChain

A developer building a LangChain pipeline that reads Shopify product pages needs structured product data, including name, price, availability, and description, before passing it into an agent or retrieval layer. Shopify pages are JavaScript-rendered and their HTML structure changes with theme updates, so maintaining a custom scraper or CSS selector set is a recurring maintenance burden. Each theme change is another debugging session, and the extracted data still arrives as raw values before anything reaches LangChain. EnConvert’s Distill endpoint accepts up to 50 Shopify product URLs with a schema defining the fields you need and returns a results array with each URL’s extracted data normalized to exactly that schema in one synchronous call, with no HTML parsing or preprocessing required.

## Example

```python
import os

import requests
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

# Step 1: Define target Shopify product URLs and the extraction schema
product_urls = [url.strip() for url in os.environ["SHOPIFY_PRODUCT_URLS"].split(",")]  # public Shopify product page URLs

schema = {
    "name": "The product's display name",
    "price": "The current selling price, including currency if shown",
    "availability": "Whether the product is in stock, sold out, or otherwise unavailable",
    "description": "The product description in plain prose",
}

# Step 2: Call Distill — synchronous, no job_id, no polling, no download step
# Distill requires a paid plan; the free tier returns 402
response = requests.post(
    "https://api.enconvert.com/v2/distill",
    headers={
        "X-API-Key": os.environ["ENCONVERT_API_KEY"],
        "Content-Type": "application/json",
    },
    json={
        "urls": product_urls,
        "schema": schema,
    },
    timeout=120,  # increase for larger batches
)
if response.status_code == 402:
    raise RuntimeError("Distill requires a paid plan")
response.raise_for_status()

# Step 3: Parse results — failed pages arrive as rows, not as request errors
products = []
for result in response.json()["results"]:
    if result["status"] != "completed":
        print(f"Skipped {result['url']}: {result['status']}")
        continue
    if result.get("render_quality", 1.0) < 0.5:
        # Low render_quality flags anti-bot challenges or login walls
        print(f"Low render quality for {result['url']}: {result['render_quality']}")
        continue
    # result["data"] contains exactly the schema keys above
    products.append({"url": result["url"], **(result.get("data") or {})})

if not products:
    raise RuntimeError("No Shopify products were extracted successfully")

print(f"Extracted {len(products)} products")

# Step 4: Pass the structured product data into a LangChain chain
prompt = ChatPromptTemplate.from_messages([
    (
        "system",
        "Summarise Shopify product records for a merchandising review. "
        "Use only the supplied structured data. Do not invent availability, pricing, or product features.",
    ),
    ("human", "Summarise these products:\n\n{products}"),
])

chain = prompt | ChatOpenAI(model="gpt-4.1", api_key=os.environ["OPENAI_API_KEY"]) | StrOutputParser()

summary = chain.invoke({
    "products": "\n\n".join(str(p) for p in products)
})
print(summary)
```

## Output

The Distill endpoint returns a results array with one entry per URL, each containing a data object normalized to exactly the schema’s keys — name, price, availability, and description — regardless of the page’s underlying HTML structure or JavaScript rendering. Maintaining a custom CSS selector set or HTML parser for Shopify pages breaks with every theme update and requires a separate preprocessing step before any structured data reaches LangChain.

---

Distill runs on paid plans only, and the free tier returns a 402 for this endpoint, so the free key covers EnConvert’s other endpoints.

## Get started

[Get free API key — 500 ops per month, no card required.](https://www.enconvert.com/auth?mode=signup)

## Related solutions

- [How to Scrape Wikipedia with LlamaIndex](https://www.enconvert.com/solutions/scrape-wikipedia-with-llamaindex-enconvert.md)
- [How to Ingest Markdown into LangChain with EnConvert](https://www.enconvert.com/solutions/ingest-markdown-into-langchain-with-heading-context.md)
- [Best JigsawStack Alternative for Structured Data Extraction](https://www.enconvert.com/solutions/jigsawstack-alternative-for-structured-data-enconvert.md)
- [How to Ingest Audio Transcripts into Qdrant with EnConvert](https://www.enconvert.com/solutions/ingest-audio-transcripts-into-qdrant-enconvert-api.md)
- [How to Ingest a CSV into pgvector Without Losing Row Context](https://www.enconvert.com/solutions/ingest-csv-into-pgvector-with-row-context-enconvert-api.md)
- [How to Ingest CSV into CrewAI with EnConvert](https://www.enconvert.com/solutions/ingest-csv-into-crewai-with-enconvert.md)
