> [!TIP]
> **Tip:** The recommended deployment option is [Cloud Run](https://developers.google.com/tag-platform/tag-manager/server-side/cloud-run-setup-guide?provisioning=automatic).

This guide explains how to:

- Provision a tagging server on Google Cloud Platform (GCP) App Engine.
- Upgrade the tagging server to handle live traffic.
- Increase or decrease the number of servers that are running your Google Tag Manager container.
- Keep your tagging server version updated after provisioning the server.

## Prerequisites

1. You need a GCP account. If you don't have one, [create a new GCP account](https://console.cloud.google.com).
2. You need a GCP billing account. If you don't have one, [create a GCP billing account](https://console.cloud.google.com/billing/create) (requires the Billing Account Creator role).
3. You need the Project Creator and the Billing Account User role. Learn more about [adding roles](https://cloud.google.com/resource-manager/docs/default-access-control#adding_a_billing_account_creator_and_project_creator).

> [!NOTE]
> **Note:** The [project owner](https://cloud.google.com/appengine/docs/standard/nodejs/testing-and-deploying-your-app#before_deploying_your_application) must first enable App Engine, otherwise you will see a permission error when deploying the tagging server. Learn more about [predefined App Engine roles](https://cloud.google.com/appengine/docs/standard/nodejs/roles#predefined_roles).

## 1. Provision a server

To create a new tagging server on an App Engine instance, you need to:

- Create a new server container in Tag Manager
- Create a new Google Cloud Project (GCP)
- Provision a new App Engine tagging server
- Add the new tagging server's URL to the Tag Manager server container

### Create a Google Tag Manager server container

1. Open [Google Tag
   Manager.](https://tagmanager.google.com/)

2. In the account row, click on the overflow menu \> **Create Container**.

3. Create a new server container.

4. Click the "Manually provision tagging server" radio button. Note the
   container config. You'll need it to provision your server.

### Create a new GCP project

To create a new GCP project for your tagging server:

1. Open [Google Cloud Console](https://console.cloud.google.com/).

2. [Create a new GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).

3. Name your project. We recommend using your container ID for convenience.
   This name is used only within GCP.

4. Note the
   [GCP project ID](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects),
   because you will need it to create your tagging server.

### Provision a new tagging server

To create your tagging server:

1. Open the [Cloud Shell](https://ssh.cloud.google.com/cloudshell).

2. Set the GCP project in the Cloud Shell. Replace `project ID` with the GCP project ID that you noted earlier:

       gcloud config set project project ID

3. Create your tagging server by following the shell script. Set the deployment
   type to `testing`.

   > [!TIP]
   > **Tip:** If you are not sure what to enter at any of the prompts, enter `?` to get help.

       bash -c "$(curl -fsSL https://googletagmanager.com/static/serverjs/setup.sh)"

### Add the tagging server URL to Tag Manager

1. Open [Google Tag
   Manager.](https://tagmanager.google.com/)

2. In **Admin** \> **Container Settings** , click **Add URL** . If you don't know
   your server's URL, run the following command in the
   [Cloud Shell](https://ssh.cloud.google.com/cloudshell):

       gcloud app browse

   **Result** : You've set up a tagging server and provisioned it with a
   `testing` configuration. You can now test server-side tagging.

### Initial server configuration (`testing`)

The testing configuration is appropriate for exploring the product by sending
small amounts of test traffic and using the Preview feature in Tag Manager. This
configuration is an App Engine
[F1 instance class](https://cloud.google.com/appengine/pricing) in the Standard
environment and in most cases, you will not incur any costs.

## 2. Using App Engine in production

In `production` configuration, each server costs approximately $40 / month
(USD). Each server is an App Engine instance with
[1 vCPU, 0.5 GB memory, 10 GB disk](https://cloud.google.com/appengine/pricing)
in the Flexible environment.
> See
> [Managing App Engine costs](https://cloud.google.com/appengine/docs/managing-costs#understanding_billing)
> to understand App Engine billing and how to configure billing alerts. We
> strongly recommend setting up a
> [billing alert](https://cloud.google.com/billing/docs/how-to/budgets).

#### Recommended production settings

We recommend running a minimum of 3 servers to reduce the risk of data loss in
case of a server outage. However, you may choose to run fewer (or more) servers.
We expect that autoscaling 3-6 servers (the default) will handle 50-200 requests
per second. The performance depends on the number of tags, and what those tags
do.

> [!CAUTION]
> **Caution:** By default, App Engine logs every request. If your server container handles a lot of requests per month (e.g. greater than 1 million), we recommend [disabling the App Engine request logging](https://developers.google.com/tag-platform/tag-manager/server-side/app-engine-setup#optional_disable_logging).

To configure your tagging server:

1. Open the Google Cloud Platform [Cloud Shell](https://ssh.cloud.google.com/cloudshell).
2. Set the Cloud Platform project in the Cloud Shell. Replace `project
   ID` with the GCP project ID that you noted earlier:

   ```
   gcloud config set project project ID
   ```
3. To reconfigure the tagging server for a production environment, run the setup script below. Perform the following tasks:

   ```
   bash -c "$(curl -fsSL https://googletagmanager.com/static/serverjs/setup.sh)"
   ```
   1. Change the deployment type to `production`.
   2. Set up additional servers to serve production traffic. We recommend a minimum of three servers.

### Optional: Disable logging

### Request logging

By default, App Engine logs information about every single request (e.g.
request path, query parameters, etc) that it receives. If your tagging
server handles a lot of requests per month (e.g. greater than 1 million),
those log messages may incur significant
[logging charges](https://cloud.google.com/logging). To reduce or eliminate
the logging charges, we recommend disabling the App Engine request logging.

To disable App Engine request logging:

1. In Google Cloud platform, open the **[Logs Router](https://console.cloud.google.com/logs/router)** . Make sure you're in the project that matches your container ID:   
   ![screenshot of GCP project selector, showing a sample Tag Manager container
   ID.](https://developers.google.com/static/tag-platform/tag-manager/server-side/img/gtmaaa1010.png)
2. For the **Type** : *Cloud Logging bucket* , **Name** : *_Default* line, select the overflow menu, then click **Edit Sink**.
3. Under **Sink destination** , select logs bucket **_Default**.
4. Under **Choose logs to include in sink**, add a new line. Enter the
   following rule to the existing inclusion filter:

       NOT LOG_ID("appengine.googleapis.com/nginx.request") AND NOT
       LOG_ID("appengine.googleapis.com/request_log")

5. To also disable logging from the load balancer, add a new line and enter
   the following rule to the existing inclusion filter:

       NOT LOG_ID("requests")

   > [!NOTE]
   > **Note:** This will disable all logging from the load balancer, including requests that are not sent to the server container.

6. **Update Sink** to apply the changes. Now the App Engine requests will
   be excluded from logging.

7. Verify that no new requests are appearing in the
   **[Logs Explorer](https://console.cloud.google.com/logs/query)** logs.

### Console logging

The tagging server, clients, or tags in a container can log messages to
console that may incur [logging charges](https://cloud.google.com/logging).
To reduce or eliminate the logging charges, you can disable unwanted console
log messages.

Identify unwanted console logs:

1. In GCP, open the [Logs Explorer](https://console.cloud.google.com/logs/query).
2. Look for any unwanted log messages that originate from your tags. For
   example:

   A tag might send the following logs:

       const logToConsole = require('logToConsole');

       logToConsole('Custom message: ' + data.param1);
       logToConsole('An important message to keep around!');
       data.gtmOnSuccess()

   Look for the corresponding log messages in the
   `textPayload` field:  

   ![screenshot of GCP Logs Explorer, showing sample
   logs.](https://developers.google.com/static/tag-platform/tag-manager/server-side/img/gcp-custom-console-example.png)

To disable console log message:

1. In Google Cloud platform, open the **[Logs Router](https://console.cloud.google.com/logs/router)** . Make sure you're in the project that matches your container ID:   
   ![screenshot of GCP project selector, showing a sample Tag Manager container
   ID.](https://developers.google.com/static/tag-platform/tag-manager/server-side/img/gtmaaa1010.png)
2. For the **Type** : *Cloud Logging bucket* , **Name** : *_Default* line, select the overflow menu, then click **Edit Sink**.
3. Under **Sink destination** , select logs bucket **_Default**.
4. Under **Choose logs to include in sink**, add a new line. Enter the
   following rule to the existing inclusion filter:

       NOT textPayload:"Custom message:"

   For your console logs, replace the
   <var label="Custom message" translate="no">Custom message:</var> text
   with a substring from console log you wish to disable. For more
   elaborate filters, utilize the
   [logging query language](https://cloud.google.com/logging/docs/view/logging-query-language).
5. **Update Sink** to apply the changes. The matching `logToConsole`
   message should be excluded from logging.

6. Verify that no new console log messages are appearing in the
   **[Logs Explorer](https://console.cloud.google.com/logs/query)**.

## 3. Map the deployment to your custom domain

The default server-side tagging deployment is hosted on an App Engine domain. We
recommend that you modify the deployment to use a subdomain of your website.

[Map your website subdomain to your tagging server](https://developers.google.com/tag-platform/tag-manager/server-side/custom-domain).

## 4. Add the server URL to Google Tag Manager

Now that you have a server, you need to make sure that Google Tag Manager knows
it should use your server.

1. Open [Google Tag
   Manager.](https://tagmanager.google.com/)

2. Click on the server container you want to point to your tagging server.

3. Open your server container settings in the **Admin** tab \> **Container
   Settings**.

4. Click **Add URL** and paste your server URL.

5. **Save** and go back to your workspace.

## 5. Validation

Now that you've set up your tagging server, make sure that it works as intended.

### UI verification

In your Tag Manager workspace, click the **Preview** button. If the preview page
loads, then everything is set up correctly.

### API verification

You can also verify that the server is responding to health checks using its
API:

1. Copy your **Server container URL** from **Admin \> Container Settings**.
2. Open a new browser tab.
3. Paste the URL and append `/healthy` to the path. For example: `https://www.example.com/metrics/healthy`
4. If your service works, you should see the text `ok` on the page.

If requests for a specific product are missing, verify that an event is being
triggered. The `config` command initializes the product, but data is usually
only transmitted when an `event` is called.

> [!NOTE]
> **Note:** Google Analytics is an exception; it automatically sends a `page_view` event when initialized using `config`, unless `send_page_view` is set to `false`.

For more information on best practices for server side tagging verification,
see [Custom domain configuration](https://developers.google.com/tag-platform/tag-manager/server-side/custom-domain?option=same-origin.).

### Preview multiple URLs

If you have mapped multiple domains to a single tagging server, make sure each
URL is added to the container settings.

If you provided multiple URLs, all paths (the string after the domain name) must
match.

| Works | Does not work |
|---|---|
| URL 1: `example.com/abc` URL 2: `example2.com/abc` | URL 1: `example.com/abc` URL 2: `example2.com/def` |

If multiple URLs are added, you will see an icon next to the **Preview** button
that lets you select the URL to preview.

## Update the tagging server version

> [!NOTE]
> **Note:** If you provisioned your tagging servers using the [Manual setup guide](https://developers.google.com/tag-platform/tag-manager/server-side/manual-setup-guide#update_the_tagging_server_version) or [Cloud Run setup guide](https://developers.google.com/tag-platform/tag-manager/server-side/cloud-run-setup-guide#update_the_tagging_server_version), please follow the instructions listed there.

New tagging server updates contain security vulnerability fixes and new
features. We recommend at least updating your tagging server for each major
version release (e.g. upgrading from version 1.x.x to 2.x.x) when Tag Manager
notifies you to update.

To update your tagging server, re-run the setup script using the same settings
you used previously. The existing settings are set by default.

To update your tagging server:

1. Open the Google Cloud Platform [Cloud Shell](https://ssh.cloud.google.com/cloudshell).
2. Set the Cloud Platform project in the Cloud Shell. Replace `project
   ID` with the GCP project ID that you noted earlier:

   ```
   gcloud config set project project ID
   ```
3. Run the setup script using the same settings you used previously. The existing settings are set by default.

   ```
   bash -c "$(curl -fsSL https://googletagmanager.com/static/serverjs/setup.sh)"
   ```

To verify that the update was successful:

1. In your server container, click the **Preview** button to start a new [debug](https://developers.google.com/tag-platform/tag-manager/server-side/debug) session and send a request on a separate tab.
2. In the Summary, select the **Console** tab and make sure there are no messages asking you to update the tagging server.

> Tag Manager may show messages asking you to update your tagging server for
> up to a day after the server has been updated successfully. However, the preview
> page will show an up to date message about the tagging server version.

## Troubleshoot production deployment timeouts

When you run the [setup script](https://developers.google.com/tag-platform/tag-manager/server-side/app-engine-setup#shell-script) to create or reconfigure the
tagging server, the script may time out. There are several reasons this could
happen. The two most common are:

1. **Service accounts have incorrect permissions** - The Compute Engine and App
   Engine service accounts are responsible for deploying and maintaining the
   production deployment. By default, they are preconfigured with the
   appropriate permissions. However, in some cases, an organization's policy
   may cause them to be incorrect.

   1. Navigate to the **IAM \& Admin** page in the left-hand navigation bar in the Google Cloud console.
   2. Find the Compute Engine service account `<project_number>-compute@developer.gserviceaccount.com` and the App Engine service account `<project_name>@appspot.gserviceaccount.com`.
   3. **Both service accounts must have the `Editor` role** . If either account does not have the `Editor` role, update the role by clicking the pencil icon on the right of the account, clicking the dropdown of the existing role, scrolling up to the top and clicking **Project** , then **Editor**.
2. **Insufficient quota** - The production deployment consumes Compute Engine
   quota. If the project does not have enough quota, the deployment may time
   out while trying to provision resources.

   1. Navigate to the **IAM \& Admin** page in the left-hand navigation bar in the Google Cloud console, then click the **Quotas** tab in the left-hand navigation bar.
   2. Near the top of the page, click the text box that says **Filter table** and type in `Compute Engine API`. Click the only result.
   3. Verify that all the quota statuses are within limit or have a green checkmark.
   4. Find and click into **CPUs**. Verify that the current usage plus the number of instances being deployed will still be below the limit for the deployment region.