External services
Load content from another system instead of copying it in by hand. Pages are built once, when you publish. Data that changes between publishes, like stock or availability, is better fetched in the browser from the service's own client-side API. A schema's pull requests an API and turns every item in the response into a document. Its map decides which fields the API owns, everything else stays for editors. push works the other way and sends documents out. See Schemas.
Do
- Map only the fields the other system owns, so edits to the rest survive every pull.
- Use a stable, unique value from the API as the
key, like a handle, slug or id. - Pull again before publishing, so the data is current.
- Put the JavaScript for a service that runs in the browser (e.g. a cart, analytics or a chat widget) in
/assets/integrations/, one file per service. It's served at/integrations/.
Don't
- Don't put keys or tokens in a component or a schema.
- Don't bind a secret field in a component. Everything a component shows ends up on the public site.
- Don't forget that a pull deletes documents the API no longer returns by default.
- Don't pull live data that frequently changes into documents. It may become out of date until the next publish.
FAQ
What should I pull, and what should I fetch in the browser?
Pull what the page needs to render and what search engines should see: names, descriptions, images, slugs. Fetch what has to be current when someone visits, like stock, a cart or availability, with a script in /assets/integrations/.
Where do API keys go?
In a field of a singleton without a page, like the site settings. The pull reads it through context.
How does a pull update documents instead of adding new ones?
The key matches each item to the document it pulled before.
How do I keep documents the API no longer returns?
Set prune: false.
Example
Products are pulled from Shopify, matched by their handle. Shopify owns the title, price and image, editors add the lesson a product is for. The price is pulled because it's part of the page's Product structured data and rarely changes between publishes. Stock is fetched in the browser.
# /schemas/Settings.yml
document: true
fields:
shop: { type: string, default: "" }
token: { type: string, default: "" }
# /schemas/Product.yml
document: true
path: /shop
key: handle
fields:
handle: { type: string, nullable: true, immutable: true, default: null }
title: { type: string, default: "" }
price: { type: number, default: 0 }
image: { type: image }
lesson: { type: reference, allow: [Lesson], nullable: true, default: null }
pull:
context: Settings
request:
url: https://{{shop}}.myshopify.com/api/2025-01/graphql.json
headers:
X-Shopify-Storefront-Access-Token: "{{token}}"
body:
query: |
query ($after: String) {
products(first: 100, after: $after) {
nodes { handle title featuredImage { url altText } priceRange { minVariantPrice { amount } } }
pageInfo { hasNextPage endCursor }
}
}
variables:
after: "{{after}}"
next:
after: "response.body.data.products.pageInfo.hasNextPage ? response.body.data.products.pageInfo.endCursor : null"
select: response.body.data.products.nodes
map:
handle: handle
title: title
price: +priceRange.minVariantPrice.amount
image.src: featuredImage.url
image.alt: featuredImage.altText ?? ''