Clione + Hydrogen (Remix) Integration Guide
Render Clione SEO signals in a Shopify Hydrogen storefront.
Install
npm install @clione/seo
Option A: Metafield Mode (recommended for Hydrogen)
Hydrogen already queries Shopify's Storefront API. Add the clione.jsonld metafield to your product query — zero extra API calls.
1. Update your product query
query Product($handle: String!) {
product(handle: $handle) {
id
title
description
# ... existing fields
metafields(identifiers: [
{ namespace: "clione", key: "jsonld" },
{ namespace: "global", key: "description_tag" },
{ namespace: "global", key: "title_tag" }
]) {
namespace
key
value
}
}
}
2. Extract and render in your loader
// routes/products.$handle.tsx
import { createClioneSeo } from '@clione/seo'
import { json, type LoaderFunctionArgs } from '@shopify/remix-oxygen'
export async function loader({ params, context }: LoaderFunctionArgs) {
const { product } = await context.storefront.query(PRODUCT_QUERY, {
variables: { handle: params.handle },
})
const clione = createClioneSeo({ source: 'metafield' })
const signals = clione.extractSignals({
id: product.id,
metafields: product.metafields.filter(Boolean).map(m => ({
namespace: m.namespace,
key: m.key,
value: m.value,
})),
})
return json({ product, seoSignals: signals })
}
export default function ProductPage() {
const { product, seoSignals } = useLoaderData<typeof loader>()
return (
<>
{seoSignals.jsonLd && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(seoSignals.jsonLd),
}}
/>
)}
{/* product page content */}
</>
)
}
// In root.tsx meta function:
export const meta: MetaFunction<typeof loader> = ({ data }) => {
const signals = data?.seoSignals
return [
{ title: signals?.metaTitle ?? data?.product?.title },
{ name: 'description', content: signals?.metaDescription ?? '' },
]
}
Option B: API Mode
If you prefer not to modify your Storefront API queries:
// routes/products.$handle.tsx
import { createClioneSeo } from '@clione/seo'
export async function loader({ params, context }: LoaderFunctionArgs) {
const clione = createClioneSeo({
source: 'api',
apiUrl: context.env.CLIONE_API_URL,
apiKey: context.env.CLIONE_API_KEY,
platform: 'shopify',
})
const [product, signals] = await Promise.all([
context.storefront.query(PRODUCT_QUERY, { variables: { handle: params.handle } }),
clione.getSignals('product', params.handle),
])
return json({
product: product.product,
seoHead: clione.renderHead(signals),
})
}
Environment Variables
# Only needed for API mode
CLIONE_API_URL=https://your-clione-instance.com
CLIONE_API_KEY=sk-...
Why Metafield Mode Is Better for Hydrogen
Hydrogen already makes a Storefront API call for every product page. Adding 3 metafield identifiers to that query costs zero extra latency. API mode adds a second network call during SSR — still fast (cached), but unnecessary when the data is already in Shopify.
Supported Entity Types
Works for products, collections, and pages — any entity with Clione metafields.