Clione + Next.js Integration Guide
Render Clione SEO signals (JSON-LD, meta title, meta description) in a Next.js headless storefront.
Install
npm install @clione/seo
API key
API mode calls Clione from your server, so it needs an API key of kind server with the products:read scope, created in Store Settings → API Keys. Keep it in a server-only environment variable — never in a NEXT_PUBLIC_* one. If the key has allowed domains, set storefrontHost to one of them; the SDK sends it as X-Clione-Storefront-Host. See Authentication.
Always pass platform: it defaults to 'bigcommerce', so a Shopify store queried without it is looked up on the wrong platform.
CLIONE_API_URL=https://api.clione.ai
CLIONE_API_KEY=sk_live_...
App Router (Next.js 13+)
// app/products/[id]/page.tsx
import { getClioneSeoMetadata, fetchClioneSeo, getJsonLdScriptProps } from '@clione/seo/react'
const clioneConfig = {
apiUrl: process.env.CLIONE_API_URL!,
apiKey: process.env.CLIONE_API_KEY!,
platform: 'bigcommerce' as const, // or 'shopify'
storefrontHost: 'shop.example.com',
}
export async function generateMetadata({ params }: { params: { id: string } }) {
// Returns { title, description } when Clione has them.
return getClioneSeoMetadata(params.id, clioneConfig, 'product')
}
export default async function ProductPage({ params }: { params: { id: string } }) {
const signals = await fetchClioneSeo('product', params.id, clioneConfig)
const jsonLdProps = getJsonLdScriptProps(signals)
return (
<>
{jsonLdProps && <script {...jsonLdProps} />}
{/* product page content */}
</>
)
}
fetchClioneSeo and getClioneSeoMetadata never throw on a network or HTTP error: they return empty signals and the page renders without them.
Pages Router
// pages/products/[id].tsx
import Head from 'next/head'
import { createClioneSeo } from '@clione/seo'
import { getJsonLdScriptProps } from '@clione/seo/react'
export async function getServerSideProps({ params }) {
const clione = createClioneSeo({
source: 'api',
apiUrl: process.env.CLIONE_API_URL,
apiKey: process.env.CLIONE_API_KEY,
platform: 'bigcommerce',
storefrontHost: 'shop.example.com',
})
const signals = await clione.getSignals('product', params.id)
return { props: { signals /* , ...other product data */ } }
}
export default function ProductPage({ signals }) {
const jsonLdProps = getJsonLdScriptProps(signals)
return (
<>
<Head>
{signals.metaTitle && <title>{signals.metaTitle}</title>}
{signals.metaDescription && <meta name="description" content={signals.metaDescription} />}
{jsonLdProps && <script {...jsonLdProps} />}
</Head>
{/* product page content */}
</>
)
}
Metafield mode (Shopify Storefront API)
If your Next.js store already queries Shopify's Storefront API, select seo { title description } and the clione.jsonld metafield on the entity, then read the signals from it:
import { createClioneSeo } from '@clione/seo'
const clione = createClioneSeo({ source: 'metafield' })
// In getServerSideProps or a server component:
const signals = clione.extractSignals(shopifyProduct)
const headHtml = clione.renderHead(signals)
No API call and no Clione API key needed. See metafield mode for the fields it reads.
Caching
The Clione API returns Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=86400. Use Next.js revalidate to cache:
// App Router
export const revalidate = 3600 // revalidate every hour
// Pages Router
export async function getStaticProps({ params }) {
// ... fetch Clione signals
return { props: { signals }, revalidate: 3600 }
}
Supported entity types
'product'— product pages'category'— category pages (BigCommerce)'collection'— collection pages (Shopify)'page'— CMS pages