This guide describes common issues, and solutions when hand-rolling an API-based integration. You will need to adapt this advice to your particular application and frameworks.

We are unable to provide support for custom integrations through normal support channels since there are so many factors outside our control. Writing a custom integration is relatively straightforward - but you do need to be an experienced developer with a good grasp of HTTP essentials.

To see examples of real-world road-tested integrations that deal with all of the issues described below, you can review our integrations in GitHub:


URL Exclusion Issues

If your application has a front controller, you may be routing all requests to your application through an integration that checks in with CrowdHandler to allow or disallow individual URL requests. This can result in the two following issues:

1. Checking unnecessary URLs

When a user loads a page the browser will load all associated page assets on your domain, and it’s possible that these requests will route through your front-controller. This can cause unnecessary checks to be made, which will add load time, and ultimately server load to your application. You’ll want to exclude at least these common file extensions before checking a URL: 

.css. gif .ico .jpg .jpeg .js .json .mov .mp4 .mpeg .mpg .png .svg .ttf .otf .eot .woff .woff2

You should also exclude any other paths in your applications that relate to content that does not require waiting room protection. For example, if you store all static assets in a sub-directory called /static you can exclude that path from checks.

2. Blocking Third Party Services in the queue

If you are using a front controller as above, and have third-party services that call APIs on your protected domain, these services are likely to be caught in the queue, and will not progress as they are unlikely to accept cookies. Common third party services that may be blocked include:

  1. Services, Plugins or Applications that consume APIs on your domain (RPC, REST)
  2. Payment services that make server-side callbacks to your domain to confirm transactions.

If the services use a tightly-defined IP range, you may be able to allow them through by adding the IP range with a bypass rule. However, it is usually preferable to exclude these URLs from your checks in the first place.

3. Blocking your admin URLs

If you log into your backend application or CMS via urls such as /admin you may wish to exclude these urls too. It may be as effective to set your office or VPN IPs to bypass. 

Cookie Issues

Perhaps the biggest issue we see with custom integrations is the failure to successfully set a cookie to keep track of the user's CrowdHandler token.

You may be using cookies, or you may be using another form of browser or server-side session storage. Here we use cookies as a catch-all term for whatever storage method you use for tracking the users CrowdHandler token, but you must take care whatever medium you are using for tacking sessions.

1. Failing to set a readable Cookie

Your integration must store the user’s CrowdHandler token when they first get redirected to your site. You cannot rely on the token being in the URL after the first hit after redirection from the waiting room. You will need to make sure the cookie is set. Make sure you’re setting a cookie that your application can read from subsequent paths that the user may be visiting.

2. Failing to set Cookie because of a HTTP redirect

The most common reason an integration fails to set a cookie is because an HTTP redirect catches the user before your integration even runs, and redirects the user to a new route without passing the token in the URL. These redirect rules may be in your web server config, or may be executed early in your code path to deal with language or login redirects. So if you are dealing with a multi-language site, or protecting a path that involves user login then take special care. The solution is to ensure redirects include the query string with the token, or make sure you are not sending users directly from the waiting room to a url that will immediately redirect.

There is a dedicated Knowledge Base Article about this issue. Read it to understand it better. Whilst this article is mostly directed at users of the JavaScript integration, you could re-create this issue in your own integration.

3. Failing to update the Cookie

There are legitimate reasons that a user may find themselves going through the queue more than once, or may have their session expire and be issued with a new token. For this reason, it is important that whenever you do see a crowdhandler token in the URL, or when a new token comes back from the API you update the cookie to match. Otherwise your integration may use an expired token, sending the user back to the queue.

So in your integration code, look for a token in the URL. If you find one make the call with the token in the URL in favor of whatever token you may find in a cookie. Then, either way, trust the well-formed token that comes back from the API and set the cookie.

4. Deleting the cookie or setting a malformed value

When looking at the URL or parsing the API response to see if you should be updating the user’s cookie, be careful that you don’t allow a bug somewhere in your code to accidentally set a null, empty or false value. Some frameworks will interpret this as a cookie deletion, and in any case, if the user submits an invalid token on their next request they will be issued with a new token, which will result in them being sent to the back of the queue.

5. Failing to set a cookie when you redirect the user to the waiting room.

Strictly speaking, it is not necessary to set a cookie if you are going to redirect this user to the waiting room. However, your integration will be much more robust if you always set a cookie. This is because the user may find themselves back on the site somehow before completing their journey through the waiting room. If you still recognize them, they will be sent back to the waiting room, maintaining their original position. If you do not, they will be sent back to the waiting room with a new position at the back of the queue. If a user is in a waiting room for a long time, it is not unusual for them to try the site again, perhaps in a new tab. Especially if they've received an email link to the protected page.

6. Setting an inappropriate expiry date with your cookie, or relying on temporary session storage

Considering the scenario above, the typical 20 minute timeout associated with the in-built session storage provided by frameworks such as .Net or PHP may not be robust enough for this scenario. If in doubt, set a session cookie, or a permanent cookie. 

API Issues

Take time to understand the parameters you are sending and the responses you may receive. These are the main issues we see with API requests and responses:

1. Sending the wrong IP to the API

When you send the IP to the request resource, ensure you are sending the user’s IP, and not your server's IP, or the IP of an intermediary proxy server. If you send the same IP many times, that IP is likely to be identified and blocked. If you face this in a live setting, you can set that IP or range to ‘ignore’ which will prevent auto-blocking behavior, but you should test and fix your integration to identify the correct IP. Typically if your web server is behind a proxy, you can detect the real IP from the HTTP header X-Forwarded-For. You may find this guide helpful.

2. Presuming the API will respond

CrowdHandler’s raison d’être is to be available when you site isn’t. However there are many legitimate reasons why your server may be temporarily unable to connect to the CrowdHandler API, including general internet routing issues or data-centre problems. If your code presumes you will always receive a well-formed response, then you are likely to display an ugly error to the user if and when these situations occur. Solutions:

  • When making the API call specify a short timeout (2 seconds is optimal)
  • If the call times out, or the response is not well-formed, consider what you want to do. In the majority of cases you will want to trust this user and allow access to the url, because this means if the outage occurs whilst you are not running a queue the user will not be disrupted. In low-trust scenarios, you may wish to send the user to the waiting room — the CrowdHandler waiting room will attempt to establish an API connection and do the best it can with the user until it receives a well-formed response from the API.

3. Presuming the response format

In the majority of cases you will receive a detailed response, including waiting room messaging etc. Here is an example:

    "result": {
        "status": 1,
        "token": "tok_7pDi5dRB2nUi",
        "title": "The Herb Girls Reunited!",
        "position": 964,
        "promoted": 0,
        "urlRedirect": null,
        "onsale": "2021-12-06T12:20:00Z",
        "message": "Booking is very busy right now. We appreciate your patience and will forward you shortly.",
        "slug": "herb-girls",
        "priority": null,
        "priorityAvailable": 1,
        "logo": " Victoria Hall-logo-2.png",
        "responseID": "e0abd8dbb8d2810fad16855622dcd45f",
        "captchaRequired": 0,
        "rate": 50,
        "hash": null,
        "ttl": 55

However, some statuses provide a small amount of information.

For example, if you check a request for a URL which is not protected by any CrowdHandler waiting room.

    "result": {
        "status": 0,
        "token": null,
        "responseID": null,
        "promoted": 1

Other responses you may see is if your key is invalid (a 401 HTTP error), if the room is full (Status: 5), or if the IP you are sending has been placed on the blocked list (Status: 4).


  • Take some time to understand the meaning of the response codes that come back. These are situations you may need to consider.
  • For the purpose of knowing whether the user should be granted access, or sent to the waiting room, you only ever need to check the promoted boolean attribute, which, unless there is an error, will always be present and either 0 or 1. If your integration is very simple, and you just look at this attribute, you don't really need to understand the various responses and statuses, because if promoted is 0, you can send the user to the waiting room, and the waiting room will know what to do.
  • If you have built an application or use a framework that requires the response object to be consistent at all times for OO reasons, you should start with your own base object or class to represent the response, specifying sensible defaults, and then set only the values that come back from the api response.