Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Offical apps | Community apps | Demo | Docs | Install
  1. Cloudron Forum
  2. App Packaging & Development
  3. Sharing My Experiment To Create Server Side Tracking (sGTM)

Sharing My Experiment To Create Server Side Tracking (sGTM)

Scheduled Pinned Locked Moved App Packaging & Development
2 Posts 2 Posters 58 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    IniBudi
    translator
    wrote last edited by
    #1

    I just wanna share my experiment to install sGTM on Cloudron.

    And I think it works well, and I got this code from Claude AI.

    You can use this CloudronManifest.json and execute it via Cloudron CLI:

    And my question is how to make the update process automatically from Cloudron dashboard?

    Thank you.

    {
      "id": "com.example.sgtm",
      "title": "Server-side GTM",
      "author": "Admin",
      "description": "Google server-side Tag Manager (sGTM) tagging server, packaged for Cloudron.",
      "tagline": "Self-hosted sGTM tagging server",
      "version": "1.0.4",
      "dockerImage": "gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:688d35c6c54473be42d5128befa4d98a722d76d6fdf9cb84d63b52a3f223a1e6",
      "healthCheckPath": "/healthz",
      "httpPort": 8080,
      "manifestVersion": 2,
      "website": "https://services.example.com",
      "contactEmail": "admin@example.com",
      "tags": [
        "analytics",
        "gtm",
        "tracking"
      ],
      "memoryLimit": 1073741824,
      "addons": {
        "localstorage": {}
      }
    }
    

    And this is the README.md:

    Server-Side GTM (sGTM) on Cloudron — Setup Guide & Best Practices

    This guide explains how to run the official Google image gcr.io/cloud-tagging-10302018/gtm-cloud-image as a custom Cloudron app, directly without building a Dockerfile. The image is pinned via the dockerImage field in CloudronManifest.json using an immutable digest (@sha256:...). There is no Dockerfile, and no build process is required.

    You will run TWO apps from the same package:

    Role Domain (REMEMBER!) Required Environment Variables
    Serving services.example.com CONTAINER_CONFIG + PREVIEW_SERVER_URL (no RUN_AS_*)
    Preview service.example.com CONTAINER_CONFIG + RUN_AS_PREVIEW_SERVER=true

    ⚠️ Important: Naming Convention (Easy to mix up!)

    • "services" (PLURAL, with an 's') = PRODUCTION / Serving -> serves your gtm.js
    • "service" (SINGULAR) = PREVIEW / Debug
    • Note: The role is strictly determined by the Environment Variables (ENV VAR), not the domain name. If they ever get swapped, check the variables!

    ⚠️ Important: Docker Images (A hard-learned lesson!)

    • DO NOT use the :stable tag in dockerImage. Cloudron/Docker caches :stable to the old digest. This means an update might report as "successful," but the old version will still be running (e.g., sticking to 4.3.0 instead of 4.4.0). Using --no-cache DOES NOT help here—that's a build-cache flag, not a pull-cache flag, and this setup doesn't use builds anyway.
    • USE A DIGEST (@sha256:...). It is immutable and content-addressed, making it impossible to cache incorrectly. Explicit version tags (e.g., :4.4.0) are also safe; only :stable (and :latest) are dangerous because they are mutable.
    • Since there is no Dockerfile and no build, setting dockerfileName: null in the app config is the correct approach.

    The Correct Serving Path: /gtm.js (NOT /load)

    The server only serves the default /gtm.js path. Custom paths like /load WILL NOT work (returning a 400/Not Found error). In your GTM "Web Container" client, it doesn't matter if you fill the Tag serving path with /load or leave it empty—it won't affect anything, as the server will always use the default /gtm.js.

    The first-party URL used by your site (via GTM4WP):
    https://services.example.com/gtm.js?id=GTM-XXXXXXX
    (The ?id= parameter is MANDATORY; without it, you will get an error, which is completely normal).


    1) Check & Fix Server Roles (If your first-party /gtm.js isn't working)

    Check the environment variables for both apps:

    cloudron env list --app services.example.com
    cloudron env list --app service.example.com
    

    PRODUCTION (services) MUST HAVE:

    • CONTAINER_CONFIG = (your configuration string)
    • PREVIEW_SERVER_URL = https://service.example.com
    • NO RUN_AS_PREVIEW_SERVER variable

    If your services app was accidentally set as preview, fix it:

    cloudron env unset --app services.example.com RUN_AS_PREVIEW_SERVER
    cloudron env set   --app services.example.com PREVIEW_SERVER_URL='https://service.example.com'
    cloudron restart   --app services.example.com
    

    PREVIEW (service) MUST HAVE:

    • CONTAINER_CONFIG = (your configuration string)
    • RUN_AS_PREVIEW_SERVER = true

    Test it: Visit https://services.example.com/gtm.js?id=GTM-XXXXXXX -> It should output JavaScript code.

    NOTE: CONTAINER_CONFIG and sensitive tokens are NOT stored in this repository. Always set them via cloudron env set, keeping them out of Git.


    2) Updating the Image to the Latest Version

    Because the image is pinned via dockerImage (not a Dockerfile build), updating simply means changing the image reference in CloudronManifest.json and deploying. You DO NOT need --no-cache, and there is no Dockerfile to edit.

    Steps:

    1. Find the latest version & digest:

      • Go to Google Cloud > Artifact Registry > package gtm-cloud-image (project cloud-tagging-10302018, repo gcr.io), and open the Overview tab.
      • Look at the Tags: find the latest version (e.g., 4.5.0). Copy the "Digest" value (sha256:...) from the version that also holds the stable tag.
      • Alternative: Check Google's server-side release notes for version numbers.
    2. Edit CloudronManifest.json:

      • Increase the version (e.g., 1.0.3 -> 1.0.4) — MUST be increased with every update.
      • Change dockerImage to the new digest:
        "gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<NEW_DIGEST>"
        (If you prefer readability, you can use the version tag: ...gtm-cloud-image:4.5.0)
    3. Commit & push to your Git repository.

    4. Deploy BOTH apps from the repo folder (from any machine with the Cloudron CLI installed):

      git clone https://git.example.com/username/sgtm-cloudron.git   # first time only
      cd sgtm-cloudron
      git pull                                                       # if already cloned
      cloudron update --app services.example.com                     # PRODUCTION
      cloudron update --app service.example.com                      # PREVIEW
      

      Cloudron will read the dockerImage from the local manifest and pull that image directly. A different digest equals a different image, guaranteeing a fresh pull.

    Quick Alternative without editing the manifest (Ad-hoc):
    This is valid but leaves your repo out-of-sync with what's actually running. If you use this, please update your manifest afterward!

    cloudron update --app services.example.com --image gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<DIGEST>
    cloudron update --app service.example.com  --image gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<DIGEST>
    

    Verification:

    • https://services.example.com/healthz -> Should return OK
    • https://services.example.com/gtm.js?id=GTM-XXXXXXX -> Should still return JS code
    • GTM > Admin > Container Settings -> Version number should increase.
      • Note: This number is REPORTED via usage beacons triggered by traffic and can be DELAYED up to 24 hours. The preview server rarely gets traffic, so it reports the slowest, and GTM tends to display the oldest version between the two servers. To confirm quickly without waiting: run Preview mode + send a few new requests from the web container, then check the Console (the outdated version warning should disappear).

    Update downtime is just a few seconds and WILL NOT affect your site.


    3) Update Cadence (Security)

    The image consists of Node.js + libraries. Google releases periodic security patches. Because this is self-hosted, keeping it updated is your responsibility.

    • Update quarterly.
    • Update when a version warning appears in the GTM Console.
    • Update when a major release drops.
      Just repeat the steps in Section 2.

    Note: The enableAutomaticUpdate feature in Cloudron DOES NOT pull new Google versions on its own—it's only for package versions we publish. Google version updates are always manual via Section 2.


    4) Files in this Repository

    • CloudronManifest.json: App metadata + pinned image via dockerImage (digest). This is the SOURCE OF TRUTH for the running version.
    • README.md: This file.
    J 1 Reply Last reply
    1
    • I IniBudi

      I just wanna share my experiment to install sGTM on Cloudron.

      And I think it works well, and I got this code from Claude AI.

      You can use this CloudronManifest.json and execute it via Cloudron CLI:

      And my question is how to make the update process automatically from Cloudron dashboard?

      Thank you.

      {
        "id": "com.example.sgtm",
        "title": "Server-side GTM",
        "author": "Admin",
        "description": "Google server-side Tag Manager (sGTM) tagging server, packaged for Cloudron.",
        "tagline": "Self-hosted sGTM tagging server",
        "version": "1.0.4",
        "dockerImage": "gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:688d35c6c54473be42d5128befa4d98a722d76d6fdf9cb84d63b52a3f223a1e6",
        "healthCheckPath": "/healthz",
        "httpPort": 8080,
        "manifestVersion": 2,
        "website": "https://services.example.com",
        "contactEmail": "admin@example.com",
        "tags": [
          "analytics",
          "gtm",
          "tracking"
        ],
        "memoryLimit": 1073741824,
        "addons": {
          "localstorage": {}
        }
      }
      

      And this is the README.md:

      Server-Side GTM (sGTM) on Cloudron — Setup Guide & Best Practices

      This guide explains how to run the official Google image gcr.io/cloud-tagging-10302018/gtm-cloud-image as a custom Cloudron app, directly without building a Dockerfile. The image is pinned via the dockerImage field in CloudronManifest.json using an immutable digest (@sha256:...). There is no Dockerfile, and no build process is required.

      You will run TWO apps from the same package:

      Role Domain (REMEMBER!) Required Environment Variables
      Serving services.example.com CONTAINER_CONFIG + PREVIEW_SERVER_URL (no RUN_AS_*)
      Preview service.example.com CONTAINER_CONFIG + RUN_AS_PREVIEW_SERVER=true

      ⚠️ Important: Naming Convention (Easy to mix up!)

      • "services" (PLURAL, with an 's') = PRODUCTION / Serving -> serves your gtm.js
      • "service" (SINGULAR) = PREVIEW / Debug
      • Note: The role is strictly determined by the Environment Variables (ENV VAR), not the domain name. If they ever get swapped, check the variables!

      ⚠️ Important: Docker Images (A hard-learned lesson!)

      • DO NOT use the :stable tag in dockerImage. Cloudron/Docker caches :stable to the old digest. This means an update might report as "successful," but the old version will still be running (e.g., sticking to 4.3.0 instead of 4.4.0). Using --no-cache DOES NOT help here—that's a build-cache flag, not a pull-cache flag, and this setup doesn't use builds anyway.
      • USE A DIGEST (@sha256:...). It is immutable and content-addressed, making it impossible to cache incorrectly. Explicit version tags (e.g., :4.4.0) are also safe; only :stable (and :latest) are dangerous because they are mutable.
      • Since there is no Dockerfile and no build, setting dockerfileName: null in the app config is the correct approach.

      The Correct Serving Path: /gtm.js (NOT /load)

      The server only serves the default /gtm.js path. Custom paths like /load WILL NOT work (returning a 400/Not Found error). In your GTM "Web Container" client, it doesn't matter if you fill the Tag serving path with /load or leave it empty—it won't affect anything, as the server will always use the default /gtm.js.

      The first-party URL used by your site (via GTM4WP):
      https://services.example.com/gtm.js?id=GTM-XXXXXXX
      (The ?id= parameter is MANDATORY; without it, you will get an error, which is completely normal).


      1) Check & Fix Server Roles (If your first-party /gtm.js isn't working)

      Check the environment variables for both apps:

      cloudron env list --app services.example.com
      cloudron env list --app service.example.com
      

      PRODUCTION (services) MUST HAVE:

      • CONTAINER_CONFIG = (your configuration string)
      • PREVIEW_SERVER_URL = https://service.example.com
      • NO RUN_AS_PREVIEW_SERVER variable

      If your services app was accidentally set as preview, fix it:

      cloudron env unset --app services.example.com RUN_AS_PREVIEW_SERVER
      cloudron env set   --app services.example.com PREVIEW_SERVER_URL='https://service.example.com'
      cloudron restart   --app services.example.com
      

      PREVIEW (service) MUST HAVE:

      • CONTAINER_CONFIG = (your configuration string)
      • RUN_AS_PREVIEW_SERVER = true

      Test it: Visit https://services.example.com/gtm.js?id=GTM-XXXXXXX -> It should output JavaScript code.

      NOTE: CONTAINER_CONFIG and sensitive tokens are NOT stored in this repository. Always set them via cloudron env set, keeping them out of Git.


      2) Updating the Image to the Latest Version

      Because the image is pinned via dockerImage (not a Dockerfile build), updating simply means changing the image reference in CloudronManifest.json and deploying. You DO NOT need --no-cache, and there is no Dockerfile to edit.

      Steps:

      1. Find the latest version & digest:

        • Go to Google Cloud > Artifact Registry > package gtm-cloud-image (project cloud-tagging-10302018, repo gcr.io), and open the Overview tab.
        • Look at the Tags: find the latest version (e.g., 4.5.0). Copy the "Digest" value (sha256:...) from the version that also holds the stable tag.
        • Alternative: Check Google's server-side release notes for version numbers.
      2. Edit CloudronManifest.json:

        • Increase the version (e.g., 1.0.3 -> 1.0.4) — MUST be increased with every update.
        • Change dockerImage to the new digest:
          "gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<NEW_DIGEST>"
          (If you prefer readability, you can use the version tag: ...gtm-cloud-image:4.5.0)
      3. Commit & push to your Git repository.

      4. Deploy BOTH apps from the repo folder (from any machine with the Cloudron CLI installed):

        git clone https://git.example.com/username/sgtm-cloudron.git   # first time only
        cd sgtm-cloudron
        git pull                                                       # if already cloned
        cloudron update --app services.example.com                     # PRODUCTION
        cloudron update --app service.example.com                      # PREVIEW
        

        Cloudron will read the dockerImage from the local manifest and pull that image directly. A different digest equals a different image, guaranteeing a fresh pull.

      Quick Alternative without editing the manifest (Ad-hoc):
      This is valid but leaves your repo out-of-sync with what's actually running. If you use this, please update your manifest afterward!

      cloudron update --app services.example.com --image gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<DIGEST>
      cloudron update --app service.example.com  --image gcr.io/cloud-tagging-10302018/gtm-cloud-image@sha256:<DIGEST>
      

      Verification:

      • https://services.example.com/healthz -> Should return OK
      • https://services.example.com/gtm.js?id=GTM-XXXXXXX -> Should still return JS code
      • GTM > Admin > Container Settings -> Version number should increase.
        • Note: This number is REPORTED via usage beacons triggered by traffic and can be DELAYED up to 24 hours. The preview server rarely gets traffic, so it reports the slowest, and GTM tends to display the oldest version between the two servers. To confirm quickly without waiting: run Preview mode + send a few new requests from the web container, then check the Console (the outdated version warning should disappear).

      Update downtime is just a few seconds and WILL NOT affect your site.


      3) Update Cadence (Security)

      The image consists of Node.js + libraries. Google releases periodic security patches. Because this is self-hosted, keeping it updated is your responsibility.

      • Update quarterly.
      • Update when a version warning appears in the GTM Console.
      • Update when a major release drops.
        Just repeat the steps in Section 2.

      Note: The enableAutomaticUpdate feature in Cloudron DOES NOT pull new Google versions on its own—it's only for package versions we publish. Google version updates are always manual via Section 2.


      4) Files in this Repository

      • CloudronManifest.json: App metadata + pinned image via dockerImage (digest). This is the SOURCE OF TRUTH for the running version.
      • README.md: This file.
      J Offline
      J Offline
      joseph
      Staff
      wrote last edited by
      #2

      @IniBudi said:

      And my question is how to make the update process automatically from Cloudron dashboard?

      Do you mean you want Cloudron to track upstream releases and make new packages and have an update available? If so, there is no such feature. An idea is to automate this in your CI (Cloudron team uses renovate for it's packages).

      1 Reply Last reply
      0

      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

      With your input, this post could be even better 💗

      Register Login
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Bookmarks
      • Search