{"id":8812,"date":"2026-08-05T15:36:34","date_gmt":"2026-08-05T13:36:34","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=8812"},"modified":"2026-08-05T17:52:04","modified_gmt":"2026-08-05T15:52:04","slug":"gtm-container-history-deep-search-engine","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/","title":{"rendered":"GTM Container History &#038; Deep Search Engine"},"content":{"rendered":"<p><script src=\"https:\/\/accounts.google.com\/gsi\/client\" async defer><\/script><\/p>\n<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary); margin-bottom: 20px; line-height: 1.6;\">\n        Connect directly to the <strong>Google Tag Manager REST API v2<\/strong> using OAuth 2.0.<br \/>\n        Fetch version headers and deeply search through hundreds of container versions for tags, scripts, triggers, or variables without manual file exports.\n    <\/p>\n<p>    <!-- STEP 1: OAUTH & API AUTHENTICATION --><\/p>\n<div style=\"background: var(--bg-body, #101416); padding: 20px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 20px;\">\n<h3 style=\"color: var(--accent); font-size: 1rem; margin-top: 0; margin-bottom: 12px;\">1. Google API Authentication<\/h3>\n<div style=\"display: flex; gap: 15px; flex-wrap: wrap; align-items: flex-end;\">\n<div style=\"flex: 1; min-width: 280px;\">\n                <label style=\"color: var(--text-secondary); display: block; font-size: 0.85rem; margin-bottom: 6px;\">Google Cloud OAuth Client ID:<\/label><br \/>\n                <input type=\"text\" id=\"api-client-id\" value=\"423029313598-2ko0jilc28eevp253rqncvodg2181e1l.apps.googleusercontent.com\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-panel); border: 1px solid var(--border); color: var(--text-primary); border-radius: 6px; font-family: monospace;\">\n            <\/div>\n<div>\n                <button id=\"auth-btn\" class=\"button\" style=\"background: var(--accent); color: #0b1114; border: none; padding: 11px 22px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Authorize with Google<\/button>\n            <\/div>\n<\/p><\/div>\n<div id=\"auth-status\" style=\"margin-top: 10px; font-size: 0.85rem; color: var(--text-secondary);\">Status: <strong style=\"color: #ff6b6b;\">Not connected<\/strong><\/div>\n<\/p><\/div>\n<p>    <!-- STEP 2: CONTAINER SELECTOR --><\/p>\n<div id=\"container-selector-panel\" style=\"background: var(--bg-body); padding: 20px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 20px; display: none;\">\n<h3 style=\"color: var(--accent); font-size: 1rem; margin-top: 0; margin-bottom: 12px;\">2. Select GTM Container &amp; Version Range<\/h3>\n<div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 15px;\">\n<div>\n                <label style=\"color: var(--text-secondary); display: block; font-size: 0.85rem; margin-bottom: 6px;\">GTM Account:<\/label><br \/>\n                <select id=\"account-select\" style=\"width: 100%; padding: 10px; background: var(--bg-panel); color: var(--text-primary); border: 1px solid var(--border); border-radius: 6px;\"><option value=\"\">&#8212; Select Account &#8212;<\/option><\/select>\n            <\/div>\n<div>\n                <label style=\"color: var(--text-secondary); display: block; font-size: 0.85rem; margin-bottom: 6px;\">Container:<\/label><br \/>\n                <select id=\"container-select\" style=\"width: 100%; padding: 10px; background: var(--bg-panel); color: var(--text-primary); border: 1px solid var(--border); border-radius: 6px;\" disabled><option value=\"\">&#8212; Select Container &#8212;<\/option><\/select>\n            <\/div>\n<div>\n                <label style=\"color: var(--text-secondary); display: block; font-size: 0.85rem; margin-bottom: 6px;\">Versions Range to Scan:<\/label><br \/>\n                <select id=\"range-select\" style=\"width: 100%; padding: 10px; background: var(--bg-panel); color: var(--text-primary); border: 1px solid var(--border); border-radius: 6px;\" disabled><option value=\"30\">Latest 30 Versions (Fast)<\/option><option value=\"100\">Latest 100 Versions<\/option><option value=\"300\">Latest 300 Versions<\/option><option value=\"all\">ALL Versions (Enterprise Scan)<\/option><\/select>\n            <\/div>\n<\/p><\/div>\n<div id=\"header-status\" style=\"font-size: 0.85rem; color: var(--text-secondary);\"><\/div>\n<\/p><\/div>\n<p>    <!-- STEP 3: DEEP SEARCH CONTROLS --><\/p>\n<div id=\"search-controls-panel\" style=\"background: var(--bg-body); padding: 20px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 25px; display: none;\">\n<h3 style=\"color: var(--accent); font-size: 1rem; margin-top: 0; margin-bottom: 12px;\">3. Deep Historical Search<\/h3>\n<div style=\"display: flex; gap: 15px; flex-wrap: wrap; margin-bottom: 15px;\">\n<div style=\"flex: 1; min-width: 260px;\">\n                <input type=\"text\" id=\"search-query\" placeholder=\"e.g., G-XXXXXXX, fbq(, analytics_storage, or ^gtm\\..*\" style=\"width: 100%; padding: 12px; background: var(--bg-panel); border: 1px solid var(--border); color: var(--text-primary); border-radius: 6px; font-family: monospace;\">\n            <\/div>\n<div>\n                <button id=\"run-api-search-btn\" class=\"button\" style=\"background: var(--accent); color: #0b1114; border: none; padding: 12px 28px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Run Deep API Search<\/button>\n            <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 15px; flex-wrap: wrap; align-items: center; border-top: 1px solid var(--border); padding-top: 15px; font-size: 0.85rem;\">\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" id=\"opt-regex\"> Use Regex<\/label><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" id=\"opt-case\"> Case Sensitive<\/label><br \/>\n            <span style=\"color: var(--border);\">|<\/span><br \/>\n            <span style=\"color: var(--text-primary); font-weight: bold;\">Scan Scopes:<\/span><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" class=\"scope-cb\" value=\"tag\" checked> Tags<\/label><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" class=\"scope-cb\" value=\"trigger\" checked> Triggers<\/label><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" class=\"scope-cb\" value=\"variable\" checked> Variables<\/label><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" class=\"scope-cb\" value=\"customTemplate\" checked> Templates<\/label><br \/>\n            <label style=\"color: var(--text-secondary); cursor: pointer;\"><input type=\"checkbox\" class=\"scope-cb\" value=\"folder\" checked> Folders<\/label>\n        <\/div>\n<p>        <!-- PROGRESS BAR --><\/p>\n<div id=\"progress-container\" style=\"margin-top: 15px; display: none;\">\n<div style=\"display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 5px;\">\n                <span id=\"progress-text\">Scanning GTM API versions&#8230;<\/span><br \/>\n                <span id=\"progress-percent\">0%<\/span>\n            <\/div>\n<div style=\"width: 100%; height: 8px; background: #242b30; border-radius: 4px; overflow: hidden;\">\n<div id=\"progress-bar\" style=\"width: 0%; height: 100%; background: #51cf66; transition: width 0.2s;\"><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>    <!-- RESULTS --><\/p>\n<div id=\"api-search-results\"><\/div>\n<\/div>\n<p><script>\n(() => {\n    let accessToken = null;\n    let tokenClient = null;\n    let versionHeaders = [];\n    const accountsMap = {};\n    const containersMap = {};<\/p>\n<p>    const authBtn = document.getElementById(\"auth-btn\");\n    const authStatus = document.getElementById(\"auth-status\");\n    const accSelect = document.getElementById(\"account-select\");\n    const contSelect = document.getElementById(\"container-select\");\n    const rangeSelect = document.getElementById(\"range-select\");\n    const headerStatus = document.getElementById(\"header-status\");\n    const resultsEl = document.getElementById(\"api-search-results\");\n    const progressCont = document.getElementById(\"progress-container\");\n    const progressBar = document.getElementById(\"progress-bar\");\n    const progressText = document.getElementById(\"progress-text\");\n    const progressPercent = document.getElementById(\"progress-percent\");<\/p>\n<p>    const esc = (str) => String(str).replace(\/&\/g, \"&amp;\").replace(\/<\/g, \"&lt;\").replace(\/>\/g, \"&gt;\");<\/p>\n<p>    \/\/ 1. OAUTH 2.0 INITIALIZATION\n    authBtn.addEventListener(\"click\", () => {\n        const clientId = document.getElementById(\"api-client-id\").value.trim();\n        if (!clientId) {\n            alert(\"Please enter a valid Google Cloud Client ID.\");\n            return;\n        }<\/p>\n<p>        if (!window.google || !google.accounts || !google.accounts.oauth2) {\n            alert(\"Google Identity Services script is still loading. Please try again in a second.\");\n            return;\n        }<\/p>\n<p>        tokenClient = google.accounts.oauth2.initTokenClient({\n            client_id: clientId,\n            scope: \"https:\/\/www.googleapis.com\/auth\/tagmanager.readonly\",\n            callback: (resp) => {\n                if (resp.error) {\n                    authStatus.innerHTML = \"Status: <strong style='color:#ff6b6b;'>Auth Error: \" + esc(resp.error) + \"<\/strong>\";\n                    return;\n                }\n                accessToken = resp.access_token;\n                authStatus.innerHTML = \"Status: <strong style='color:#51cf66;'>Connected (Read-Only Access)<\/strong>\";\n                document.getElementById(\"container-selector-panel\").style.display = \"block\";\n                loadAccounts();\n            }\n        });\n        tokenClient.requestAccessToken();\n    });<\/p>\n<p>    \/\/ 2. API FETCHER WITH RATE-LIMIT THROTTLING & ADVANCED ERROR DECODING\n    const gtmApi = async (path) => {\n        const res = await fetch(\"https:\/\/tagmanager.googleapis.com\/tagmanager\/v2\/\" + path, {\n            headers: { \"Authorization\": \"Bearer \" + accessToken }\n        });\n        if (res.status === 429) {\n            await new Promise(r => setTimeout(r, 1500));\n            return gtmApi(path);\n        }\n        if (!res.ok) {\n            let errDetails = res.statusText || \"Unknown API Error\";\n            try {\n                const errJson = await res.json();\n                if (errJson && errJson.error && errJson.error.message) {\n                    errDetails = errJson.error.message;\n                }\n            } catch (e) {}\n            throw new Error(\"API Error \" + res.status + \": \" + errDetails);\n        }\n        return res.json();\n    };<\/p>\n<p>    const loadAccounts = async () => {\n        try {\n            accSelect.innerHTML = \"<option>Loading accounts...<\/option>\";\n            const data = await gtmApi(\"accounts\");\n            accSelect.innerHTML = \"<option value='>-- Select Account --<\/option>\";\n            (data.account || []).forEach(a => {\n                accountsMap[a.accountId] = a.name;\n                const opt = document.createElement(\"option\");\n                opt.value = a.accountId;\n                opt.textContent = a.name + \" (\" + a.accountId + \")\";\n                accSelect.appendChild(opt);\n            });\n        } catch (e) {\n            accSelect.innerHTML = \"<option>Error loading accounts<\/option>\";\n            alert(\"Failed to fetch accounts: \" + e.message);\n        }\n    };<\/p>\n<p>    accSelect.addEventListener(\"change\", async () => {\n        const accId = accSelect.value;\n        if (!accId) return;\n        try {\n            contSelect.innerHTML = \"<option>Loading containers...<\/option>\";\n            contSelect.disabled = true;\n            const data = await gtmApi(\"accounts\/\" + accId + \"\/containers\");\n            contSelect.innerHTML = \"<option value='>-- Select Container --<\/option>\";\n            (data.container || []).forEach(c => {\n                containersMap[c.containerId] = c;\n                const opt = document.createElement(\"option\");\n                opt.value = c.containerId;\n                opt.textContent = c.name + \" (\" + c.publicId + \")\";\n                contSelect.appendChild(opt);\n            });\n            contSelect.disabled = false;\n        } catch (e) {\n            alert(\"Failed to load containers: \" + e.message);\n        }\n    });<\/p>\n<p>    contSelect.addEventListener(\"change\", async () => {\n        const accId = accSelect.value;\n        const contId = contSelect.value;\n        if (!contId) return;\n        try {\n            headerStatus.innerHTML = \"Fetching metadata for all container versions...\";\n            const data = await gtmApi(\"accounts\/\" + accId + \"\/containers\/\" + contId + \"\/version_headers\");\n            versionHeaders = (data.containerVersionHeader || []).sort((a, b) => Number(b.containerVersionId) - Number(a.containerVersionId));\n            headerStatus.innerHTML = \"<strong style='color:#51cf66;'>Success:<\/strong> Found <strong>\" + versionHeaders.length + \" versions<\/strong> in this container.\";\n            rangeSelect.disabled = false;\n            document.getElementById(\"search-controls-panel\").style.display = \"block\";\n        } catch (e) {\n            headerStatus.innerHTML = \"<span style='color:#ff6b6b;'>Error loading version headers: \" + esc(e.message) + \"<\/span>\";\n        }\n    });<\/p>\n<p>    \/\/ 3. DEEP SEARCH TRAVERSAL LOGIC\n    const searchInObject = (obj, regex, path = \"\") => {\n        const matches = [];\n        if (typeof obj === \"string\") {\n            if (regex.test(obj)) matches.push({ path: path || \"value\", snippet: obj });\n        } else if (Array.isArray(obj)) {\n            obj.forEach((item, idx) => matches.push(...searchInObject(item, regex, path ? path + \"[\" + idx + \"]\" : \"[\" + idx + \"]\")));\n        } else if (obj && typeof obj === \"object\") {\n            for (const key in obj) {\n                if (Object.prototype.hasOwnProperty.call(obj, key)) {\n                    const val = obj[key];\n                    const nextPath = path ? path + \".\" + key : key;\n                    if (regex.test(key)) matches.push({ path: nextPath, snippet: typeof val === \"object\" ? JSON.stringify(val) : String(val) });\n                    matches.push(...searchInObject(val, regex, nextPath));\n                }\n            }\n        }\n        return matches;\n    };<\/p>\n<p>    const getBadge = (type) => {\n        const colors = {\n            tag: { bg: \"#1a3a4b\", color: \"#51cf66\", label: \"TAG\" },\n            trigger: { bg: \"#4b3a1a\", color: \"#ff922b\", label: \"TRIGGER\" },\n            variable: { bg: \"#2a1a4b\", color: \"#339af0\", label: \"VARIABLE\" },\n            customTemplate: { bg: \"#4b1a47\", color: \"#cc5de8\", label: \"TEMPLATE\" },\n            folder: { bg: \"#242b30\", color: \"#a0a6b0\", label: \"FOLDER\" }\n        };\n        const c = colors[type] || { bg: \"#242b30\", color: \"#ffffff\", label: type.toUpperCase() };\n        return \"<span style='background:\" + c.bg + \"; color:\" + c.color + \"; padding:3px 8px; border-radius:4px; font-size:0.75rem; font-weight:700;'>\" + c.label + \"<\/span>\";\n    };<\/p>\n<p>    \/\/ 4. QUEUED SCANNER ENGINE\n    document.getElementById(\"run-api-search-btn\").addEventListener(\"click\", async () => {\n        const query = document.getElementById(\"search-query\").value.trim();\n        if (!query) { alert(\"Please enter a search query.\"); return; }<\/p>\n<p>        const isRegex = document.getElementById(\"opt-regex\").checked;\n        const isCase = document.getElementById(\"opt-case\").checked;\n        const activeScopes = Array.from(document.querySelectorAll(\".scope-cb:checked\")).map(cb => cb.value);<\/p>\n<p>        let regex;\n        try {\n            const flags = isCase ? \"g\" : \"gi\";\n            regex = isRegex ? new RegExp(query, flags) : new RegExp(query.replace(\/[.*+?^${}()|[\\]\\\\]\/g, \"\\\\$&\"), flags);\n        } catch (e) {\n            alert(\"Invalid Regex: \" + e.message); return;\n        }<\/p>\n<p>        const rangeVal = rangeSelect.value;\n        const toScan = rangeVal === \"all\" ? versionHeaders : versionHeaders.slice(0, Number(rangeVal));<\/p>\n<p>        resultsEl.innerHTML = \"\";\n        progressCont.style.display = \"block\";\n        const allResults = [];\n        let completed = 0;<\/p>\n<p>        \/\/ Run batch pool of 3 concurrent API calls to avoid 429 limit\n        const concurrency = 3;\n        for (let i = 0; i < toScan.length; i += concurrency) {\n            const batch = toScan.slice(i, i + concurrency);\n            await Promise.all(batch.map(async (vh) => {\n                try {\n                    const fullVer = await gtmApi(vh.path);\n                    activeScopes.forEach((scope) => {\n                        const items = fullVer[scope] || [];\n                        items.forEach((item) => {\n                            const itemMatches = searchInObject(item, regex);\n                            if (itemMatches.length > 0) {\n                                allResults.push({\n                                    versionId: vh.containerVersionId,\n                                    versionName: vh.name || \"(Unnamed)\",\n                                    type: scope,\n                                    entityName: item.name || \"(Unnamed Item)\",\n                                    matches: itemMatches\n                                });\n                            }\n                        });\n                    });\n                } catch (err) {\n                    console.error(\"Error scanning version \" + vh.containerVersionId, err);\n                } finally {\n                    completed++;\n                    const pct = Math.round((completed \/ toScan.length) * 100);\n                    progressBar.style.width = pct + \"%\";\n                    progressPercent.textContent = pct + \"%\";\n                    progressText.textContent = \"Scanned version \" + completed + \" of \" + toScan.length + \"...\";\n                }\n            }));\n        }<\/p>\n<p>        progressText.textContent = \"Scan complete!\";<\/p>\n<p>        if (!allResults.length) {\n            resultsEl.innerHTML = \"<\/p>\n<div style='background:var(--bg-body); padding:25px; border-radius:6px; border:1px solid var(--border); text-align:center; color:var(--text-secondary);'>No matches found for <strong>\" + esc(query) + \"<\/strong> across scanned versions.<\/div>\n<p>\";\n            return;\n        }<\/p>\n<p>        allResults.sort((a, b) => Number(b.versionId) - Number(a.versionId));<\/p>\n<p>        const cardsHtml = allResults.map((res) => {\n            const matchRows = res.matches.slice(0, 6).map((m) => [\n                \"<\/p>\n<div style='background:#0b1114; border:1px solid var(--border); padding:10px; border-radius:4px; margin-top:8px; font-family:monospace; font-size:0.85rem; overflow-x:auto;'>\",\n                \"  <span style='color:#ff922b; display:block; margin-bottom:4px;'>\" + esc(m.path) + \"<\/span>\",\n                \"  <span style='color:#e0e6ed; white-space:pre-wrap;'>\" + esc(m.snippet.slice(0, 400)) + (m.snippet.length > 400 ? \"...\" : \"\") + \"<\/span>\",\n                \"<\/div>\n<p>\"\n            ].join(\"\")).join(\"\");<\/p>\n<p>            return [\n                \"<\/p>\n<div style='background:var(--bg-body); border:1px solid var(--border); border-radius:8px; padding:18px; margin-bottom:15px;'>\",\n                \"  <\/p>\n<div style='display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px; border-bottom:1px solid var(--border); padding-bottom:12px; margin-bottom:12px;'>\",\n                \"    <\/p>\n<div style='display:flex; align-items:center; gap:10px;'>\",\n                \"      \" + getBadge(res.type),\n                \"      <strong style='color:var(--text-primary); font-size:1.05rem;'>\" + esc(res.entityName) + \"<\/strong>\",\n                \"    <\/div>\n<p>\",\n                \"    <\/p>\n<div style='color:var(--text-secondary); font-size:0.85rem;'>\",\n                \"      Found in Version: <strong style='color:var(--accent);'>v\" + esc(res.versionId) + \"<\/strong> (\" + esc(res.versionName) + \")\",\n                \"    <\/div>\n<p>\",\n                \"  <\/p><\/div>\n<p>\",\n                \"  <\/p>\n<div style='color:var(--text-secondary); font-size:0.85rem;'>Matched Properties (\" + res.matches.length + \"):<\/div>\n<p>\",\n                \"  \" + matchRows,\n                \"<\/p><\/div>\n<p>\"\n            ].join(\"\");\n        }).join(\"\");<\/p>\n<p>        resultsEl.innerHTML = [\n            \"<\/p>\n<h3 style='color:var(--text-primary); margin-bottom:15px; font-size:1.15rem;'>Found \" + allResults.length + \" Historical Match(es)<\/h3>\n<p>\",\n            cardsHtml\n        ].join(\"\");\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Calculate total power draw across PoE hardware and verify switch capacity saturation for UniFi deployments.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"class_list":["post-8812","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GTM Container History &amp; Deep Search Engine - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GTM Container History &amp; Deep Search Engine - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Calculate total power draw across PoE hardware and verify switch capacity saturation for UniFi deployments.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-05T15:52:04+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/gtm-container-history-deep-search-engine\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/gtm-container-history-deep-search-engine\\\/\",\"name\":\"GTM Container History & Deep Search Engine - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-05T13:36:34+00:00\",\"dateModified\":\"2026-08-05T15:52:04+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/gtm-container-history-deep-search-engine\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/gtm-container-history-deep-search-engine\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/gtm-container-history-deep-search-engine\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"GTM Container History &#038; Deep Search Engine\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GTM Container History & Deep Search Engine - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/","og_locale":"en_US","og_type":"article","og_title":"GTM Container History & Deep Search Engine - Lukas Wojcik - Blog","og_description":"Calculate total power draw across PoE hardware and verify switch capacity saturation for UniFi deployments.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-08-05T15:52:04+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/","name":"GTM Container History & Deep Search Engine - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-05T13:36:34+00:00","dateModified":"2026-08-05T15:52:04+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/gtm-container-history-deep-search-engine\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"GTM Container History &#038; Deep Search Engine"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/8812","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=8812"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/8812\/revisions"}],"predecessor-version":[{"id":8818,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/8812\/revisions\/8818"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=8812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}