SERA integration on Node

Kindly follow the below examples to setup the routing of bot traffic to SERA.

Prerequisites#

  • All your page requests must get intercepted by below SERA routing rule
    • Please check your routing, caching and cache-variation policies for that
  • If caching is enabled, Users and Bots should have a separate cache-variations configured. This is to not serve the SERA’s bot-optimized-content to users.

Steps#

  • Change SERA_ENDPOINT to the SERA endpoint shared with you
  • Change YOUR_TOKEN to the SERA token shared with you
  • Keep the relevant bot user-agent regex condition mentioned below - to control the traffic being sent to SERA

const express = require('express');
const app = express();
const port = 3000;


const seraEndpoint = 'SERA_ENDPOINT';
const seraToken = 'YOUR_TOKEN';
const n7AccessKey = 'N7_ACCESS_KEY';
//USE THIS - DURING POC PHASE for bot User-Agent regex :
const seraUserAgentPattern = /(n7TestUserAgent|google page speed|chrome-lighthouse|google-inspectiontool|PTST|GTmetrix|n7ua)/i;
//USE THIS - ON GOING LIVE ON SERA for bot User-Agent regex :
//const seraUserAgentPattern = /(n7TestUserAgent|google page speed|chrome-lighthouse|google-inspectiontool|PTST|GTmetrix|n7ua|googlebot|facebookexternalhit|bingbot)/i;
//USE THIS - ON GOING LIVE ON SERA for AI bots for bot User-Agent regex :
//const seraUserAgentPattern = /(openai|gptbot|claudebot|claude-user|perplexity-user|perplexity-bot|google-extended|google-cloudvertexbot|google-notebooklm|amazonbot|duckassistbot|metaai|metabotic|meta-externalagent|copilot|baiduspider)/i;
const seraAllowedExtnPattern = /^(|.+\.html|.+\.aspx|.+\.php)($|\?.*)/i;
const seraExludeQryPrmPattern = /\?(.*&)*(nsbp)=.*/i;
const seraExludePagePattern = /.*(\/static/|\/_next\/|\/api\/|\/login|\/logout|\/account\/|\/wishlist\/|\/cart\/|\/checkout\/|\/payment\/).*/i;

const sera = async (req, res, next) => {
	const { "user-agent": userAgent, "accept-encoding": acceptEncoding, accept, referer } = req.headers;

	if (req.method === "GET"
		&& seraUserAgentPattern.test(userAgent) 
		&& seraAllowedExtnPattern.test(req.url)
		&& !seraExludeQryPrmPattern.test(req.url)
		&& !seraExludePagePattern.test(req.url)
		&& !req.headers['x-nv-app']
		&& !req.headers['x-nv-sera-bypass']) {
		
		const headers = {
			'x-nv-sera-token': seraToken,
			'x-nv-access-key': n7AccessKey,
			'user-agent': userAgent || '',
			'accept-encoding': acceptEncoding || '',
			'accept': accept || '',
			'referer': referer || '',
		};

		const remoteUrl = `${seraEndpoint}${req.url.pathname}`; //USE THIS IF YOUR SITEMAP PAGE URLS DO NOT HAVE QUERYSTRING
		const remoteUrl = `${seraEndpoint}${req.url}`; //USE THIS IF YOUR SITEMAP PAGE URLS HAVE QUERYSTRING

		try {
			const response = await fetch(remoteUrl, { headers });
			if ((response.status === 200 || response.status === 410) && response.data) {
				res.status(response.status).send(response.data);
			}
			else {
				next();
			}
		} catch (error) {
			console.error('error downloading page:', error.message);
			next();
		}
	}
	else {
		next();
	}
}

app.use(sera);

app.get('/', (req, res) => {
	res.send('Hello World!')
})

app.listen(port, () => {
	console.log(`example app listening on port ${port}`)
})

x-nv-app and x-nv-sera-bypass headers mentioned in logic are added on request when SERA connects to your server to fetch page content for optimizing and caching, and also when it bypasses the requests to origin on failover scenario.
These requests are bypassed to your server.

Changes needed at GMC end#

GMC requests should always be served with fresh content, else Google flags them with content-mismatch.
So, make sure all the product URLs in your GMC feed file have nsbp query parameter.
Above condition will bypass SERA for such requests, and route them to your origin.

Testing and Refinement#

  • Keep refining the logic by adjusting user-agent list, and SERA exclusion-patterns as needed.

  • Test thoroughly:

    • WPT and GTMetrix will automatically receive the response from SERA due to the routing rule set above.

      • Steps to validate page using WPT
    • To check the SERA rendered page on browser, you can use DevTools > Network conditions facility , or some browser extension (like Simple modify headers ) to manipulate the browser user-agent.
      If in testing phase, use these user-agent values:
      For desktop:

      n7TestUserAgent

      For mobile:

      n7TestUserAgent; Android

      If SERA is live, you can use these actual bot user-agent values:
      For desktop:

      Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +<http://www.google.com/bot.html)> Chrome/W.X.Y.Z Safari/537.36

      For mobile:

      Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z Mobile Safari/537.36 (compatible; Googlebot/2.1; +<http://www.google.com/bot.html)>
  • On go-live day, set the user-agent condition regex to actual bot user-agent values. Additionally, ensure that your condition is case-insensitive.

  • Whitelist SERA requests at your origin to avoid any issues with indexing. Details are here

  • After go-live, in any dashboards created for monitoring the “actual user traffic” e.g. Google analytics, exclude the requests with user-agent string containing word “Nitrogen SERA” to get correct understanding about user-traffic.

Notes#

  • Go through the different scenarios mentioned here
  • Also Refer the Frequently Asked Questions about SERA here