---
title: Grouping Requests
description: Learn how to group requests in your Headless Platform application for Faust.js
url: https://developers.wpengine.com/docs/headless-platform/platform-guides/grouping-requests/
image: https://developers.wpengine.com/og/docs/headless-platform/platform-guides/grouping-requests.png
---

# Grouping Requests

## Introduction

When building headless applications with Faust.js, you may want to group related GraphQL queries together for better debugging and monitoring. This is particularly useful when you need to trace requests that originate from a specific initial request, such as a server-side request that triggers subsequent client-side GraphQL queries.

When working with subsequent GraphQL queries in Faust.js (or any other framework), you may need to group queries together to help debug issues with your headless application. This is particularly useful for tracing related requests and understanding the flow of data through your application.

This example demonstrates how to capture the Cloudflare Ray ID from the initial response and pass it as a custom header for any subsequent GraphQL queries, enabling you to group these queries on the server side for better debugging and monitoring.

> **Note**
>
> This example passes the Cloudflare CF Ray ID; you can adapt it to capture other headers for grouping related requests.

## How does this work?

1. **Capture in middleware**: Next.js middleware captures the CF Ray value from the incoming request and stores it in a cookie for client-side and server-side access
2. **Custom Faust plugin**: A custom plugin retrieves the cookie value and adds it as a custom header to all GraphQL requests
3. **WordPress CORS setup**: WordPress actions allow the custom header through CORS policies

## Code

middleware.js

```js
import { NextResponse } from 'next/server';


export function middleware(request) {
  const response = NextResponse.next();


  // Get CF Ray ID from the incoming request
  const cfRayId = request.headers.get('cf-ray');


  if (!cfRayId) {
    return response;
  }


  // Set the cookie in the response so it can be accessed client-side and server-side
  response.cookies.set('custom-initial-cf-ray-id', cfRayId, {
    path: '/',
    sameSite: 'lax',
  });


  response.headers.set('X-CUSTOM-INITIAL-CF-RAY-ID', cfRayId);
  response.headers.set(
    'Access-Control-Expose-Headers',
    'x-custom-request-id, cf-ray, x-custom-initial-cf-ray-id',
  );


  return response;
}


export const config = {
  matcher: [
    // Match all paths except static files and API routes that don't need tracking
    '/((?!_next/static|_next/image|favicon.ico).*)',
  ],
};
```

faust.config.js

```js
import { setConfig } from '@faustwp/core';
import templates from './wp-templates';
import possibleTypes from './possibleTypes.json';
import AddCustomHeaderPlugin from './plugins/AddCustomHeaderPlugin';


const tracingPlugin = new AddCustomHeaderPlugin();


/**
 * @type {import('@faustwp/core').FaustConfig}
 **/
export default setConfig({
  templates,
  plugins: [tracingPlugin.getPlugin()],
  experimentalPlugins: [],
  possibleTypes,
});
```

plugins/AddCustomHeaderPlugin.js

```js
import { setContext } from '@apollo/client/link/context';


class AddCustomHeaderPlugin {
  constructor() {
    this.pluginName = 'add-custom-cf-ray-id-header-plugin';
  }


  /**
   * Creates a plugin to add custom tracing headers to Apollo Client requests.
   * @returns {Object} Plugin configuration object
   */
  getPlugin() {
    return {
      apply: (hooks) => {
        hooks.addFilter('apolloClientOptions', this.pluginName, (options) => {
          const headerLink = setContext((_, { headers }) => {
            let cfRayId = '';
            const isServer = typeof window === 'undefined';


            const cfRayIdCookiePatterns = [
              /(?:^|;\s*)custom-initial-cf-ray-id=([^;]*)/,
              /(?:^|;\s*)cf-ray=([^;]*)/,
            ];


            function extractCfRayId(cookieString) {
              for (const pattern of cfRayIdCookiePatterns) {
                const match = cookieString.match(pattern);
                if (match) {
                  return decodeURIComponent(match[1]);
                }
              }
              return '';
            }


            if (isServer) {
              if (headers && headers.cookie) {
                cfRayId = extractCfRayId(headers.cookie);
              }
            } else {
              cfRayId = extractCfRayId(document.cookie);
            }


            if (!cfRayId || cfRayId === '') {
              console.warn('No CF Ray ID found.');
              return { headers };
            }


            return {
              headers: {
                ...headers,
                'CUSTOM-PARENT-CF-RAY-ID': cfRayId,
              },
            };
          });


          return {
            ...options,
            link: headerLink.concat(options.link),
          };
        });
      },
    };
  }
}


export default AddCustomHeaderPlugin;
```

functions.php

```php
function add_cors_http_header() {
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
    header("Access-Control-Allow-Headers: Content-Type, Authorization, CUSTOM-PARENT-CF-RAY-ID");
    header("Access-Control-Allow-Credentials: true");
}
add_action('init','add_cors_http_header');


function handle_preflight() {
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
        header("Access-Control-Allow-Headers: Content-Type, Authorization, CUSTOM-PARENT-CF-RAY-ID");
        header("Access-Control-Max-Age: 86400");
        exit(0);
    }
}
add_action('init', 'handle_preflight');
```

## Screenshots

![Initial server request](https://developers.wpengine.com/_astro/initial-server-request.BInFuOMw_Z29aF6M.webp)

![Subsequent client request](https://developers.wpengine.com/_astro/subsequent-client-request.D58FLuTg_29z5Wq.webp)

## Was this helpful?

Thanks for the feedback!

```json
{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://developers.wpengine.com/#website","name":"WP Engine Product Documentation","url":"https://developers.wpengine.com/","description":"Resources for developing, deploying, and scaling on WP Engine.","inLanguage":"en-US","keywords":["API documentation","product documentation","headless WordPress","managed WordPress hosting"],"publisher":{"@id":"https://wpengine.com/#organization"}}]}
```
