Server-side Rendering

Method One: Page-by-page useEffect

If you already have a successful and confirmed installation of Sovrn Commerce JavaScript (viglink-javascript)

<script
  src="//cdn.viglink.com/api/vglnk.js"
  async
  type="text/javascript"
></script>

you can call window.__commercejs.fetchProductRecommendations() when your page has rendered in the UI/fully hydrated.

// page.tsx
'use client'
import { useEffect } from 'react'

export default function MyPage() {
  useEffect(() => {
    window.__commercejs.fetchProductRecommendations()
  }, [])

  return (
    <main>
      <h1>My Page</h1>
    </main>
  )
}

or with JavaScript:

// page.js
'use client'
import { useEffect } from 'react'

export default function MyPage() {
  useEffect(() => {
    window.__commercejs.fetchProductRecommendations()
  }, [])

  return (
    <main>
      <h1>My Page</h1>
    </main>
  )
}

Method Two: Automatic on Route Change

This solution is designed for these specific dependency versions:

{
  "dependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "next": "15.3.1"
  }
}

If you don't want to manually add the useEffect example shown above to every page, follow
these steps to automatically fetch products when the app route path changes.

TypeScript

Add a type definition for the commerce-js API in a global.d.ts file:

// global.d.ts
interface Window {
  __commercejs: {
    fetchProductRecommendations: () => void
  }
}

Create a file called sovrn-commerce.tsx. Here we'll define two components, SovrnCommerce and SovrnCommerceShoppingGallery.

First add SovrnCommerce. This component is responsible for loading the Sovrn JavaScript and
fetching product recommendations when the app path changes. If we do not detect a Sovrn Commerce shopping gallery, the function exits safely.

// sovrn-commerce.tsx
'use client'
import { usePathname } from 'next/navigation'
import { useEffect, useRef } from 'react'

export function SovrnCommerce() {
  const pathname = usePathname()
  const pathnameRef = useRef(pathname)

  useEffect(() => {
    if (pathnameRef.current !== pathname) {
      pathnameRef.current = pathname

      // if the app path changes, check to see if a shopping gallery is present in the DOM
      // and fetch products for that page.
      window.__commercejs.fetchProductRecommendations()
    }
  }, [pathname])
  return (
    <>
      <script
        dangerouslySetInnerHTML={{
          __html: `
                var vglnk = { key: '<your_api_key>' };
            `,
        }}
      ></script>
      <script
        src="//cdn.viglink.com/api/vglnk.js"
        async
        type="text/javascript"
      ></script>
    </>
  )
}

Now add the SovrnCommerceShoppingGallery.

// sovrn-commerce.tsx

/**
 * @see [documentation](#) for configuration options
 */
export function SovrnCommerceShoppingGallery() {
  return <div className="sovrn-commerce-ai-shopping-gallery"></div>
}

Add SovrnCommerce to the app root or root layout or some root level component that doesn't
unmount when route path changes.

// layout.tsx
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en">
      <body>
        {children}
        <SovrnCommerce />
      </body>
    </html>
  )
}

Finally, add a shopping gallery to your page:

// page.tsx
export default function MyPage() {
  return (
    <main>
      <h1>My Page</h1>
      <SovrnCommerceShoppingGallery />
    </main>
  )
}

JavaScript

These steps are nearly identical. Follow the TypeScript Instructions
but skip the global.d.ts type definition step and use .js file extensions: sovrn-commerce.js.

// sovrn-commerce.js
'use client'
import { usePathname } from 'next/navigation'
import { useEffect, useRef } from 'react'

export function SovrnCommerce() {
  const pathname = usePathname()
  const pathnameRef = useRef(pathname)

  useEffect(() => {
    if (pathnameRef.current !== pathname) {
      pathnameRef.current = pathname
      window.__commercejs.fetchProductRecommendations()
    }
  }, [pathname])
  return (
    <>
      <script
        dangerouslySetInnerHTML={{
          __html: `
                var vglnk = { key: '<your_api_key>' };
            `,
        }}
      ></script>
      <script
        src="//cdn.viglink.com/api/vglnk.js"
        async
        type="text/javascript"
      ></script>
    </>
  )
}

export function SovrnCommerceShoppingGallery() {
  return <div className="sovrn-commerce-ai-shopping-gallery"></div>
}