Sign up

Proxy

Proxy with Vue or Nuxt

On this page

Nuxt has a server, so a server route does the job. A Vite-built Vue app is static: proxy it on your host, and use the dev server proxy locally.

Set it up

  1. Nuxt: add a server route

    server/routes/a/[kind].ts
    // server/routes/a/[kind].ts · Nuxt 3 or 4 (Nitro server)
    export default defineEventHandler(async (event) => {
      const kind = getRouterParam(event, "kind");
      const script = kind === "script" && event.method === "GET";
      const isEvent = kind === "event" && event.method === "POST";
      if (!script && !isEvent) throw createError({ statusCode: 404 });
      const headers = new Headers();
      for (const name of ["content-type", "origin", "user-agent"]) {
        const value = getRequestHeader(event, name);
        if (value) headers.set(name, value);
      }
      // Reads X-Forwarded-For: trust it only if your host overwrites it.
      const ip = getRequestIP(event, { xForwardedFor: true });
      if (ip) headers.set("x-visitor-ip", ip);
      const upstream = await fetch(script ? "https://metricraven.com/js/script.js" : "https://metricraven.com/api/v1/collect", {
        method: event.method,
        headers,
        body: isEvent ? await readRawBody(event, false) : undefined,
        signal: AbortSignal.timeout(15000),
      });
      return new Response(upstream.body, {
        status: upstream.status,
        headers: {
          "Content-Type": upstream.headers.get("content-type") || "application/octet-stream",
          "Cache-Control": script ? "public, max-age=3600" : "no-store",
        },
      });
    });

    Nuxt auto-imports the h3 helpers. Routes under server/routes have no /api prefix.

  2. Nuxt: update the script in nuxt.config.ts

    In app.head.script, set src: "/a/script" and add "data-api": "/a/event".

  3. Vue (Vite): proxy on your host in production

    vite build outputs static files, so the production proxy lives on your host: Netlify, Vercel, Cloudflare Workers, Nginx or Caddy.

  4. Vue (Vite), optional: the same paths in development

    So the proxied tag also works on npm run dev, add the dev server proxy. It only runs locally, and local visits are tracked only with data-allow-localhost.

    vite.config.ts
    // vite.config.ts · the Vite dev server only (vite build output has no server)
    import { defineConfig, type ProxyOptions } from "vite";
    
    const forwardVisitorIp: ProxyOptions["configure"] = (proxy) =>
      proxy.on("proxyReq", (proxyReq, req) => {
        proxyReq.setHeader("x-visitor-ip", (req.socket.remoteAddress || "").replace(/^::ffff:/, ""));
        proxyReq.removeHeader("cookie");
      });
    
    export default defineConfig({
      server: {
        proxy: {
          "/a/script": {
            target: "https://metricraven.com",
            changeOrigin: true,
            rewrite: () => "/js/script.js",
            configure: forwardVisitorIp,
          },
          "/a/event": {
            target: "https://metricraven.com",
            changeOrigin: true,
            rewrite: () => "/api/v1/collect",
            configure: forwardVisitorIp,
          },
        },
      },
    });
  5. Point your script tag at your own paths

    Replace your MetricRaven tag with this one. src loads the tracker from your domain and data-api sends its events there too.

    Your website's shared layout
    <script defer src="/a/script" data-api="/a/event" data-site-id="YOUR_SITE_ID"></script>

Verify it works

Open your live site. In the browser's Network panel, /a/script loads the tracker and /a/event answers with ok: true. Nothing goes to metricraven.com from the browser.

In Traffic, your own visit should show your real country and city. If every visit appears to come from your server's or host's location, the visitor IP isn't being forwarded.

Notes

  • Nuxt's routeRules proxy option can't add a per-visitor header, so it isn't enough on its own. Use the server route.

How the proxy works and which headers it must send: Use your own domain.

Details

  • The proxy forwards only Content-Type, Origin, User-Agent and the visitor's IP as x-visitor-ip. Your site's cookies and auth headers never leave your server.
  • Origin matters: MetricRaven checks it against your site's allowed domains. A missing or wrong origin is refused with domain_not_allowed.
  • MetricRaven allows about 120 events per minute per visitor IP. Without x-visitor-ip, all of your visitors share the proxy's IP, so busy sites lose events as well as locations.
  • A proxy doesn't guarantee that every blocker will allow tracking.