Pass the page URL to Hypertune
Overview
Sometimes you need to pass the current page URL to Hypertune, e.g. to include it in analytics event payloads, or to use it to target features, experiments, or AI loops. A common use case is enabling a feature based on a URL parameter.
Setup
To pass the page URL to Hypertune, first add a url
field to your Context
input type:
input Context {
environment: Environment!
user: User!
url: String!
}
Create a helper function called addHeadersToRequest
:
import { NextRequest, NextResponse } from "next/server";
export function addHeadersToRequest(
request: NextRequest,
response: NextResponse,
headers: Record<string, string>,
): void {
mutateRequestHeaders(request, response, (newRequestHeaders) => {
Object.entries(headers).forEach(([key, value]) => {
newRequestHeaders.set(key, value);
});
});
}
const xMiddlewareOverrideHeadersHeaderName = "x-middleware-override-headers";
const xMiddlewareRequestHeaderNamePrefix = "x-middleware-request-";
function mutateRequestHeaders(
request: NextRequest,
response: NextResponse,
mutate: (newRequestHeaders: Headers) => void,
): void {
const newRequestHeaders = new Headers(request.headers);
// Add existing request header overrides to new request headers
response.headers.forEach((value, key) => {
if (key.toLowerCase().startsWith(xMiddlewareRequestHeaderNamePrefix)) {
const originalName = key.slice(xMiddlewareRequestHeaderNamePrefix.length);
newRequestHeaders.set(originalName, value);
}
});
mutate(newRequestHeaders);
const dummyResponse = NextResponse.next({
request: { headers: newRequestHeaders },
});
// Add request header overrides to response
dummyResponse.headers.forEach((value, key) => {
if (
key === xMiddlewareOverrideHeadersHeaderName ||
key.toLowerCase().startsWith(xMiddlewareRequestHeaderNamePrefix)
) {
response.headers.set(key, value);
}
});
}
Use it in middleware to store the page URL in a request header:
import { NextRequest, NextResponse } from "next/server";
import { addHeadersToRequest } from "@/lib/utils";
export const config = {
matcher: "/:path*",
};
export async function middleware(request: NextRequest) {
const response = NextResponse.next();
addHeadersToRequest(request, response, { "x-request-url": request.url });
return response;
}
Finally, get the page URL from the header and pass it to Hypertune:
import "server-only";
import { unstable_noStore as noStore } from "next/cache";
import { headers } from "next/headers";
import { createSource } from "@/generated/hypertune";
const hypertuneSource = createSource({
token: process.env.NEXT_PUBLIC_HYPERTUNE_TOKEN!,
});
export default async function getHypertune() {
noStore();
await hypertuneSource.initIfNeeded(); // Check for flag updates
const headersList = await headers();
const url = headersList.get("x-request-url") ?? "";
return hypertuneSource.root({
args: {
context: {
environment: process.env.NODE_ENV,
user: { id: "1", name: "Test", email: "[email protected]" },
url,
},
},
});
}
Now you can use the page URL in:
Analytics event payloads
Targeting for features, experiments, or AI loops
Last updated