🔍 Overview
The OTTO Pixel is a client-side script injection method that works well for traditional server-rendered or static sites. However, in Next.js and other React-based frameworks, the Pixel can cause React hydration errors and trigger repeated client-side API calls. This happens because the Pixel modifies the DOM after the initial server render, creating a mismatch between server-rendered HTML and what React expects on the client.
The recommended solution for Next.js sites is to use the OTTO API integration, which fetches SEO data server-side before the page is rendered, completely avoiding DOM conflicts.
⚠️ Why the OTTO Pixel Causes Issues in Next.js
React hydration works by attaching event listeners and state to a DOM that must exactly match what the server produced. When the OTTO Pixel injects meta tags or structured data into the DOM after hydration begins, React detects a mismatch and throws errors such as:
- Hydration failed because the initial UI does not match what was rendered on the server
- Repeated or duplicate API calls firing on every client-side navigation
- SEO tags flickering or appearing inconsistently in page source
Switching to the OTTO API integration resolves all of these issues by moving data-fetching to the server, so the HTML React receives on the client is already complete.
🚀 How the OTTO API Integration Works
Instead of injecting a script tag into your page, the OTTO API integration lets your Next.js app call the OTTO API directly during server-side rendering (SSR) or static site generation (SSG). The API returns the SEO metadata for each page, which you render into your <head> before the HTML is sent to the browser. React then hydrates a page that is already complete — no DOM conflicts, no duplicate calls.
⚙️ Step-by-Step: Implementing the OTTO API Integration in Next.js
- Remove the OTTO Pixel script tag from your
_app.js,_document.js, or any layout component where it is currently injected. Removing it first prevents any conflicts during the migration. - Locate your OTTO UUID by navigating to Left sidebar → OTTO SEO → Installation Guide in the Search Atlas platform. Your UUID is displayed on that page and is required for all API requests.
- Fetch SEO data server-side inside
getServerSideProps(for SSR) orgetStaticProps(for SSG) in each page file. Make a request to the OTTO API endpoint, passing your UUID and the current page path as parameters. The API response will contain the meta title, meta description, canonical URL, structured data, and any other SEO fields OTTO manages for that page. - Pass the API response as props to your page component. Keep the data shape flat and serialisable so Next.js can pass it through
propswithout issues. - Render the SEO data into your
<head>using Next.js's built-innext/headcomponent (or your preferred head-management library). Because this happens on the server, the rendered HTML will already contain the correct meta tags before React hydrates. - Verify the integration by viewing the page source (not the browser inspector) and confirming the OTTO-managed meta tags appear in the raw HTML. Also check your browser console for any remaining hydration warnings.
- Re-scan your site in Search Atlas by navigating to Left sidebar → OTTO SEO → Site Audit → Overview (Website Overview) and clicking Recrawl Site. This confirms OTTO can read the tags from your live pages and that the installation status updates correctly.
💡 Tips for a Smooth Migration
- Handle API errors gracefully. Wrap your OTTO API call in a try/catch block and fall back to default meta values if the request fails, so a temporary API issue never breaks your pages.
- Cache responses for SSG pages. If you use
getStaticPropswithrevalidate, the OTTO API is only called during build or revalidation — not on every visitor request — which keeps performance fast. - Use a shared fetch utility. Create a single helper function (e.g.,
fetchOttoSeo(uuid, path)) that all your page files import. This avoids duplicating fetch logic and makes future updates easier. - Do not include the Pixel and the API integration at the same time. Running both simultaneously will cause duplicate tags and may trigger the same hydration conflicts you are trying to fix.
- Dynamic routes (e.g.,
/blog/[slug]) should pass the resolved path string to the API — not the Next.js route pattern — so OTTO can match it to the correct page record.
✅ Confirming the Fix
After completing the integration, confirm the following:
- No hydration errors appear in the browser console on first load or client-side navigation.
- Meta tags are visible in the raw page source before JavaScript executes.
- The OTTO installation status in Left sidebar → OTTO SEO → Site Audit → Overview (Website Overview) shows as active and scanning correctly.
- Network requests show a single server-side call to the OTTO API per page render — not repeated client-side calls.
💬 Need More Help?
If you need further assistance, open the chat widget in the bottom-right corner of the platform and type human teammate to be connected with a member of our team.