Skip to main content
Use this guide when your site runs on an Apache server that you or your host administer, and no CDN or platform connector applies. Apache writes AI crawler requests to a dedicated log file in the format Qwairy expects. A scheduled script then sends the closed files to the Generic HTTP collector. The dedicated file is added next to your existing access logs, which keep working when you follow the virtual host step. Qwairy receives only the method, path, hostname, User-Agent, time, and status of AI crawler requests.
If a CDN or full-page cache answers some requests before Apache, those requests never reach Apache logs. Collect at that layer instead, or accept partial counts.

Before you start

If you are not the server administrator, send this list to the person who manages the server. They need:
  • Apache 2.4 with mod_rewrite, mod_setenvif, and mod_log_config enabled, and the rotatelogs program installed with Apache;
  • permission to edit the Apache configuration and reload Apache;
  • a Linux shell with sh, curl, find, split, and sha256sum, and a way to run a command every five minutes, such as cron;
  • outbound HTTPS access from the server to https://www.qwairy.co;
  • the ServerName of the virtual host, which must be the hostname configured for the Qwairy brand or its apex or www equivalent;
  • a key created in Qwairy, as described below.
Only activate one Crawler Analytics delivery source for the brand.

Create and protect the key

  1. In Measure > Crawler Analytics > Settings, select Generic HTTP API.
  2. Select Create Key, then enter a descriptive name and the IANA time zone used for daily analytics.
  3. Copy the secret when it appears. Qwairy shows only its prefix later.
  4. On the server, store it in a file that only the user running the script can read:
Replace YOUR_CRAWLER_KEY with the secret. Do not commit it to source control or write it to logs.

Write a dedicated log file

The configuration below writes one JSON event per line, only for GET and HEAD requests from known AI crawlers. A new file starts every five minutes, so the sender only reads files that Apache has closed.
1

Create the log directory

Use the log directory of your distribution, for example /var/log/httpd on Red Hat-based systems, and keep the same path in every step.
2

Define the crawler filter and the log format

Add these lines to the main server configuration, outside any <VirtualHost> block:
The User-Agent list matches the recipes generated in Qwairy. Qwairy applies its maintained registry again on receipt, so an older list only misses identities added later.
3

Log AI crawler requests in the virtual host

Add these lines inside the <VirtualHost> that serves the site over HTTPS, before any other rewrite rule.If this virtual host has no CustomLog line yet, it writes to the main server access log. A CustomLog added inside a virtual host stops that inheritance, so first copy the main CustomLog line into the virtual host to keep your usual access log.
Run command -v rotatelogs and use the path it returns. If another virtual host also serves pages of the same site, add the same lines there with a different file prefix.
4

Check and reload Apache

Each choice in this configuration avoids a known error: A line looks like this:

Send closed files

Save this script as /usr/local/bin/qwairy-send-logs, then run sudo chmod 700 /usr/local/bin/qwairy-send-logs:
The script runs one instance at a time and first waits a random delay of up to four minutes, so that servers do not all send at the same minute. It then groups all closed files into batches of at most 1,000 lines and 1,900,000 bytes, so a site with little crawler traffic sends a single request per run. Each batch is sent with an Idempotency-Key derived from its content, and a staging directory lets an interrupted run resume with the same batches, so no line is counted twice. It handles responses as follows: Schedule the script every five minutes, for example in /etc/cron.d/qwairy:
If the log directory differs from /var/log/apache2/qwairy, add QWAIRY_LOG_DIR=/your/path before the script in the cron line. To run the script by hand without the random delay, set QWAIRY_MAX_DELAY=0:

Verify delivery

  1. Request a page as an AI crawler, replacing the hostname:
  2. Confirm that a line appears in the newest file of /var/log/apache2/qwairy with "request_path":"/", your ServerName, and a time with an offset.
  3. Wait at least six minutes, then run the script once by hand with the command above. It prints nothing when every batch was accepted, and failed/ stays empty.
  4. In Qwairy, wait for the connector to move from pending to connected, then open the current analytic day and look for the page.

Limits and behavior

  • Events reach Qwairy about 6 to 20 minutes after the request: up to five minutes until the file closes, six minutes before the script treats it as closed, up to five minutes until the next cron run, and up to four minutes of random delay.
  • Events are accepted until 72 hours after the end of their analytic day. If sending stops for longer, older events fall outside the late-arrival window and are rejected. Historical access logs cannot be imported.
  • Only GET and HEAD requests from the listed AI crawlers, with a printable ASCII request line and a printable ASCII User-Agent of at most 512 characters, are written. Human and other traffic never leaves the server.
  • One invalid line makes the whole batch return 400. The other lines of that batch are not counted until you correct it.
  • Requests answered by a CDN or cache before Apache are not observed.

Troubleshooting

Roll back

  1. Remove the Qwairy CustomLog and rewrite lines from the virtual host, keep your usual CustomLog, then run sudo apachectl graceful.
  2. Wait at least six minutes so the last file counts as closed, then run the script once more by hand with the command above.
  3. Check that the log directory only contains an empty failed/ directory. Handle any remaining batch before going further.
  4. Delete /etc/cron.d/qwairy, /usr/local/bin/qwairy-send-logs, /etc/qwairy/crawler.env, and the log directory.
  5. Revoke the key in Qwairy.
Stopping delivery creates a coverage gap. Check delivery-continuity warnings before comparing periods that cross it. Apache directives verified against the mod_log_config, mod_rewrite, mod_setenvif, and rotatelogs documentation on 30 October 2026, with Apache 2.4.