function getGeneralDetails($tag, $typeString = '', $whatItDoes = '') { global $tagLibrary, $tagTypes, $container, $usedTriggers, $trigLibrary, $trigTypes, $untriggeredTags, $userIdUsed, $legacyTags, $folderArray, $usedUdvs, $udvUsage; $technicalDetails = ''; $rawHTML = getParam($tag, 'html'); $deets = '<table class="table table-bordered table-striped">'; $deets = $deets . '<tr><th>Name</th><td>' . $tag['name'] . '</td></tr>'; $deets = $deets . '<tr><th>Type</th><td>' . $typeString . '</td></tr>'; $deets = $deets . '<tr><th>What it does</th>'; if ($whatItDoes === '') { if ($rawHTML !== '') { $containsScript = strpos($rawHTML, '<script') > -1 ? 'contains JavaScript' : 'contains HTML'; $deets = $deets . '<td>This tag ' . $containsScript . '. Being a custom tag, you need to make sure this is carefully reviewed by your developers.<br />'; $deets = $deets . '<textarea class="form-control" rows="10" cols="60" disabled="disabled">' . $rawHTML . '</textarea></td></tr>'; if (getParam($tag, 'supportDocumentWrite') === 'true') { $deets = $deets . '<tr><th></th><td>This tag supports document.write.</td></tr>'; } } if (getParam($tag, 'trackType') !== '') { $deets = $deets . humanDetails(getParam($tag, 'trackType'), $tag); } if (getParam($tag, 'enableEcommerce') === 'true') { $deets = $deets . '<br />This tag uses Enhanced Ecommerce tracking features.<br />'; if (getParam($tag, 'useEcommerceDataLayer') === 'true') { $deets = $deets . 'The Data Layer is used to record the Enhanced Ecommerce data (<b>Technical!</b>)<br />'; } else { if (getParamTemplate($tag, 'ecommerceMacroData') !== '' && array_key_exists('value', getParamTemplate($tag, 'ecommerceMacroData'))) { $deets = $deets . variablise(getParamTemplate($tag, 'ecommerceMacroData')['value'], $tag, true) . ' is used to record the Enhanced Ecommerce data (<b>Technical!</b>)<br />'; } } $deets = $deets . '</td></tr>'; } else { $deets = $deets . '</tr>'; } if (getParam($tag, 'trackingId') !== '') { $deets = $deets . '<tr><th>The GA property ID is</th><td>' . translateToHuman(getParam($tag, 'trackingId'), $tag, true) . '</td></tr>'; } } else { $deets = $deets . $whatItDoes; } $deets = $deets . '<tr><th>When it does it</th>'; /****************************************************************************** Firing triggers ******************************************************************************/ if (array_key_exists('firingTriggerId', $tag) && count($tag['firingTriggerId']) > 0) { $triggerFound = false; $triggerLink = ''; $firingTrigArray = []; if (count($tag['firingTriggerId']) > 1) { $triggerLink = '<td>This tag is fired by the following triggers:<ul>'; foreach ($tag['firingTriggerId'] as $tagFiringKey => $tagFiringVal) { if (!array_search($tag['firingTriggerId'][$tagFiringKey], $usedTriggers)) { array_push($usedTriggers, $tag['firingTriggerId'][$tagFiringKey]); } $triggerFound = false; foreach ($trigTypes as $trigTypeKey => $trigTypeVal) { foreach ($trigLibrary[$trigTypeVal] as $trigKey => $trigVal) { if ($tag['firingTriggerId'][$tagFiringKey] === $trigLibrary[$trigTypeVal][$trigKey]['triggerId']) { $triggerLink = $triggerLink . buildTriggerLink($tag['firingTriggerId'][$tagFiringKey], '<li>', '</li> ', $trigLibrary, $trigTypes); $triggerFound = true; } } } if ($triggerFound === false) { $triggerLink = $triggerLink . '<li>Built-in <span title="This tag will fire on literally ALL PAGES!" style="background-color: #CCC"><b>All Pages</b></span> trigger.</li>'; } } $deets = $deets . $triggerLink . '</ul></td></tr>'; } else { if (!array_search($tag['firingTriggerId'][0], $usedTriggers)) { array_push($usedTriggers, $tag['firingTriggerId'][0]); } $triggerLink = buildTriggerLink($tag['firingTriggerId'][0], '<td>This tag is fired by the ', ' trigger. </td></tr>', $trigLibrary, $trigTypes); if ($triggerLink === '') { $deets = $deets . '<td>This tag is fired by the built-in <span title="This tag will fire on literally ALL PAGES!" style="background-color: #CCC"><b>All Pages</b></span> trigger.</td></tr>'; } else { $deets = $deets . $triggerLink; } } } else { $deets = $deets . '<td>This tag <i>appears</i> to have <span title="This tag will NOT fire." style="background-color: #CCC"><b>no firing triggers</b></span>.</td></tr>'; array_push($untriggeredTags, $tag); } /****************************************************************************** Blocking triggers ******************************************************************************/ if (array_key_exists('blockingTriggerId', $tag) && count($tag['blockingTriggerId']) > 0) { $deets = $deets . '<tr><th>When it is <b>stopped</b> from doing it</th>'; $triggerFound = false; $blockingTrigArray = []; if (count($tag['blockingTriggerId']) > 1) { $triggerLink = '<td>This tag is blocked by the following triggers.<ul>'; foreach ($tag['blockingTriggerId'] as $blockingTrigKey => $blockingTrigVal) { $triggerFound = false; foreach ($trigTypes as $trigTypeKey => $trigTypeVal) { foreach ($trigLibrary[$trigTypeVal] as $trigKey => $trigVal) { if ($tag['blockingTriggerId'][$blockingTrigKey] === $trigLibrary[$trigTypeVal][$trigKey]['triggerId']) { $triggerLink = $triggerLink . buildTriggerLink($tag['blockingTriggerId'][$blockingTrigKey], '<li>', '</li> '); $triggerFound = true; } } } if ($triggerFound === false) { $triggerLink = $triggerLink . '<li>Built-in <span title="This tag will be blocked on literally ALL PAGES!" style="background-color: #CCC"><b>All Pages</b></span> trigger.</li>'; } } $deets = $deets . $triggerLink . '</ul></td></tr>'; } else { $triggerLink = buildTriggerLink($tag['blockingTriggerId'][0], '<td>This tag is <b>BLOCKED</b> by the ', ' trigger. </td></tr>', $trigLibrary, $trigTypes); if ($triggerLink === '') { $deets = $deets . '<td>This tag is <b>BLOCKED</b> by the built-in <span title="This tag be blocked on literally ALL PAGES!" style="background-color: #CCC"><b>All Pages</b></span> trigger.</td></tr>'; } else { $deets = $deets . $triggerLink; } } } if (array_key_exists('scheduleStartMs', $tag)) { $deets = $deets . '<tr><th>Custom firing schedule start</th><td>The tag will only be live from ' . date('Y-m-d H:i:s', (int) $tag['scheduleStartMs'] / 1000); $nowDate = new DateTime(); $startDate = new DateTime(); $startDate->setTimestamp((int) $tag['scheduleStartMs'] / 1000); $interval = date_diff($nowDate, $startDate); if ($interval->invert === 1) { $deets = $deets . ' - this tag went live ' . $interval->format('%a days ago') . '.</td><tr>'; } if ($interval->invert === 0) { $deets = $deets . ' - this will go live in ' . $interval->format('%a days') . '.</td><tr>'; } } if (array_key_exists('scheduleEndMs', $tag)) { $deets = $deets . '<tr><th>Custom firing schedule end</th><td>The tag will only be live before ' . date('Y-m-d H:i:s', (int) $tag['scheduleEndMs'] / 1000); $nowDate = new DateTime(); $endDate = new DateTime(); $endDate->setTimestamp((int) $tag['scheduleEndMs'] / 1000); $interval = date_diff($nowDate, $endDate); if ($interval->invert === 1) { $deets = $deets . ' - this tag ended ' . $interval->format('%a days ago') . '. </td><tr>'; } if ($interval->invert === 0) { $deets = $deets . ' - this tag will end in ' . $interval->format('%a days') . '.</td><tr>'; } } /****************************************************************************** Sequencing ******************************************************************************/ $deets = $deets . sequence($tag); /****************************************************************************** Firing priority ******************************************************************************/ $deets = $deets . priority($tag); /****************************************************************************** Firing Options ******************************************************************************/ $humanFiringOption = array_key_exists('tagFiringOption', $tag) ? translateToHuman($tag['tagFiringOption'], $tag) : false; if ($humanFiringOption !== false) { $deets = $deets . '<tr><th></th><td>' . $humanFiringOption . '</td></tr>'; } /****************************************************************************** Published containers ******************************************************************************/ if ($tag['liveOnly'] === 'true') { $deets = $deets . '<tr><th></th><td>This tag will only fire in published containers</td></tr>'; } $deets = $deets . '<tr><th>Where it lives</th>'; if (array_key_exists('parentFolderId', $tag)) { $deets = $deets . '<td>' . folderisation($tag['parentFolderId'], 'tag') . '</td></tr>'; } else { $deets = $deets . '<td>' . folderisation(null, 'tag') . '</td></tr>'; } if ($rawHTML !== '') { $varRefs = getVarRefs($rawHTML, $tag); if ($varRefs !== '') { $technicalDetails = $technicalDetails . 'Variables referenced in this tag:<br />' . $varRefs; } } /****************************************************************************** Fields to Set (UA only) ******************************************************************************/ $technicalDetails = $technicalDetails . fieldsToSet($tag); /****************************************************************************** Custom Dimensions ******************************************************************************/ $technicalDetails = $technicalDetails . dimensions($tag); /****************************************************************************** Custom Metrics ******************************************************************************/ $technicalDetails = $technicalDetails . metrics($tag); /****************************************************************************** Custom Variables ******************************************************************************/ $technicalDetails = $technicalDetails . cvars($tag); /****************************************************************************** Mop up gnarly details ******************************************************************************/ $technicalDetails = $technicalDetails . getGnarlyDetails($tag); if ($technicalDetails !== '') { $deets = $deets . '<tr><th></th><td>' . $technicalDetails . '</td></tr>'; } $deets = $deets . '</table><br />'; return $deets; }
function udvDetail($udv, $typeString = '', $usage = '') { $attributeName = ''; $selectorType = ''; $deets = '<h3>Details for User-defined variable <i>' . $udv['name'] . '</i></h3>'; $deets = $deets . '<a href="https://tagmanager.google.com/#/container/accounts/' . $udv['accountId'] . '/containers/' . $udv['containerId'] . '/variables/' . $udv['variableId'] . '"'; $deets = $deets . ' style="position:relative;float:right;top:-40px;right:10px;" class="udvEdit">edit</a>'; $deets = $deets . '<table class="table table-bordered table-striped">'; $deets = $deets . '<tr><th>Name</th><td>' . $udv['name'] . '</td></tr>'; $deets = $deets . '<tr><th>What it\'s for</th><td>' . $typeString . '</td></tr>'; $deets = $deets . '<tr><th>What it does</th>'; $deets = $deets . '<td>' . $usage; if ($udv['type'] === 'd') { if (getParamTemplate($udv, 'attributeName') !== '') { $attributeName = array_key_exists('value', getParamTemplate($udv, 'attributeName')) ? getParamTemplate($udv, 'attributeName')['value'] : ''; } if (getParamTemplate($udv, 'selectorType') !== '') { $selectorType = array_key_exists('value', getParamTemplate($udv, 'selectorType')) ? getParamTemplate($udv, 'selectorType')['value'] : ''; } if ($selectorType !== '') { $selectorType = getParamTemplate($udv, 'selectorType')['value']; if ($selectorType === 'CSS') { $elementSelector = getParamTemplate($udv, 'elementSelector')['value']; $deets = $deets . '<br /><br />This variable will extract the "<b>' . variablise($attributeName, $udv) . '</b>" attribute from the first element on the page that matches the CSS selector "<b>' . variablise($elementSelector, $udv) . '</b>".<br /><br />'; $deets = $deets . '<b>Warning</b>: This is not supported in IE7. IE8 and only supports CSS 2.1 selectors.<br />'; } if ($selectorType === 'ID') { $elementId = getParamTemplate($udv, 'elementId')['value']; $deets = $deets . '<br /><br />This variable will extract the "<b>' . variablise($attributeName, $udv) . '</b>" attribute from the first element on the page with the ID "<b>' . variablise($elementId, $udv) . '</b>".<br /><br />'; $deets = $deets . 'Of course, there should only be one element with this ID so if there are multiple elements with the same ID, have a word with your front-end development team.<br />'; } } } if ($udv['type'] === 'aev') { $varType = getParamTemplate($udv, 'varType')['value']; $hostSource = 'Element URL'; switch ($varType) { case 'ELEMENT': $deets = $deets . 'The variable returns the value of the "gtm.element" key on the data layer. If populated by an Auto-Event, the result will be the DOM element that triggered the event.<br /><br />In other words, the <i>thing</i> on the page that was clicked or the form that was submitted.<br /><br />'; break; case 'ATTRIBUTE': $deets = $deets . 'The variable returns the value of the "' . getParamTemplate($udv, 'attribute')['value'] . '" attribute for the element that triggered the last click or form submit event.<br /><br /><br />'; break; case 'CLASSES': $deets = $deets . 'The variable returns the value of the "gtm.elementClasses" key on the data layer. If populated by an Auto-Event, the result will be the "class" attribute of the DOM element that triggered the event (the <i>thing</i> that was clicked or the form that was submitted).<br /><br />'; break; case 'ID': $deets = $deets . 'The variable returns the value of the "gtm.elementId" key on the data layer. If populated by an Auto-Event, the result will be the "id" attribute of the DOM element that triggered the event (the <i>thing</i> that was clicked or the form that was submitted).<br /><br />'; break; case 'TARGET': $deets = $deets . 'The variable returns the value of the "gtm.elementTarget" key on the data layer. If populated by an Auto-Event, the result will be the "target" attribute of the DOM element that triggered the event (the <i>thing</i> that was clicked or the form that was submitted).<br /><br />'; break; case 'TEXT': $deets = $deets . 'The variable returns the value of the "gtm.element" key on the data layer and its text content if there is any.<br />If populated by a click or link-click Auto-Event, the text content will be the "innerText" or the "textContent" attribute of the DOM element that triggered the event.<br /><b>Technical:</b> The text will be trimmed and normalised (white-spaces will be consolidated) to account for browsers variations.<br /><br />'; break; case 'URL': $deets = $deets . 'The variable returns the value of the "gtm.elementUrl" key on the data layer.<br />If populated by an Auto-Event, the result will be the "href" or "action" attribute of the DOM element that triggered the event, depending on the type of element (the <i>thing</i> that was clicked or the form that was submitted).<br /><br />'; $URLComponent = getParamTemplate($udv, 'component') !== '' ? getParamTemplate($udv, 'component')['value'] : ''; if ($URLComponent !== '') { switch ($URLComponent) { case 'HOST': $deets = $deets . 'The "hostname" part of the ' . $hostSource; if (getParam($udv, 'stripWww') !== null && getParam($udv, 'stripWww') === 'true') { $deets = $deets . ' - minus the www part - '; } $deets = $deets . ' will be returned.<br />'; break; case 'PATH': $deets = $deets . 'The path of the ' . $hostSource . ' will be returned.<br />'; if (strlen(getParamList($udv, 'defaultPages')) > 0) { $deets = $deets . 'The list of default pages to ignore is:<ul>'; $defaultPages = getParamList($udv, 'defaultPages'); foreach ($defaultPages as $defPageIndex => $defPageVal) { $deets = $deets . '<li>' . $defaultPages[$defPageIndex]['value'] . '</li>'; } $deets = $deets . '</ul><br />'; $deets = $deets . 'The last non-directory segment in the path will be stripped if it matches any of the default pages. For instance, if a default page is "index.html" and the URL is "http://a.com/x/index.html", the variable value will be "/x/".<br />'; } break; case 'QUERY': $queryKey = ''; if (getParamTemplate($udv, 'queryKey') !== '') { $queryKey = variablise(getParamTemplate($udv, 'queryKey')['value'], $udv); } $deets = $deets . 'The value of the querystring variable (the part after the ? on the ' . $hostSource . ') "' . $queryKey . '" will be returned.<br />'; break; case 'FRAGMENT': $deets = $deets . 'The fragment (the part after the # on the ' . $hostSource . ') will be returned.<br />'; break; case 'PORT': $deets = $deets . 'The port (80 or 443 for example) of the ' . $hostSource . ' will be returned.<br />'; break; case 'PROTOCOL': $deets = $deets . 'The protocol (http or https) of the ' . $hostSource . ' will be returned.<br />'; break; case 'URL': $deets = $deets . 'The full URL of the ' . $hostSource . ' will be returned.<br />'; break; } } break; case 'HISTORY_NEW_URL_FRAGMENT': $deets = $deets . 'The value is determined by reading the "gtm.newUrlFragment" key from the data layer. If populated by an Auto-Event, the result will be the new URL fragment set on a history change event (Used by AJAX forms - <b>Technical</b>).<br />'; break; case 'HISTORY_OLD_URL_FRAGMENT': $deets = $deets . 'The value is determined by reading the "gtm.oldUrlFragment" key from the data layer. If populated by an Auto-Event, the result will be the old URL fragment set on the previous history change event (Used by AJAX forms - <b>Technical</b>).<br />'; break; case 'HISTORY_NEW_STATE': $deets = $deets . 'The value is determined by reading the "gtm.newHistoryState" key from the data layer. If populated by an Auto-Event, the result will be the new history state set on a history change event (Used by AJAX forms - <b>Technical</b>).<br />'; break; case 'HISTORY_OLD_STATE': $deets = $deets . 'The value is determined by reading the "gtm.oldHistoryState" key from the data layer. If populated by an Auto-Event, the result will be the old history state set on the previous history change event (Used by AJAX forms - <b>Technical</b>).<br />'; break; case 'HISTORY_CHANGE_SOURCE': $deets = $deets . 'The value is determined by reading the "gtm.historyChangeSource" key from the data layer. If populated by an Auto-Event, the result will be the source of the gtm.historyChange event, which can be: "popstate", "pushState", "replaceState" or "polling" (Used by AJAX forms - <b>Technical</b>).<br />'; break; } } if ($udv['type'] === 'k') { if (getParam($udv, 'decodeCookie') === 'true') { $deets = $deets . "<br /><br />The value of the cookie will be URI-decoded. This is a nice thing to do to make your data human readable.<br />"; } else { $deets = $deets . "<br /><br />The value of the cookie will not be URI-decoded.<br />"; $deets = $deets . "If enabled, the value of the cookie 'xxx%3Dyyy' would become 'xxx=yyy'.<br />"; $deets = $deets . "This might be a nice thing to do to make your data human readable.<br />"; } } if ($udv['type'] === 'f') { if (array_key_exists('parameter', $udv)) { $component = getParam($udv, 'component'); if ($component === 'QUERY' || $component === 'FRAGMENT') { $deets = $deets . 'It returns the ' . translateToHuman($component, $udv) . ' part of the referring page URL using the '; if ($component === 'QUERY') { $deets = $deets . getParam($udv, 'queryKey') . ' querystring parameter.<br />'; } else { $deets = $deets . ' part of the URL after the "#" without the leading "#".<br />'; } } else { $deets = $deets . 'It returns the ' . translateToHuman($component, $udv) . ' the user just came from.<br />'; } if (getParam($udv, 'stripWww') === 'true') { $deets = $deets . 'The returned value will have the "www" part of the hostname stripped off.'; } } else { $deets = $deets . 'It returns the full URL of the last page the user was on.<br /><br />'; $deets = $deets . 'Why not just use the \'Referrer\' built in variable? It does the same thing.'; } } if ($udv['type'] === 'u') { $hostSource = 'URL'; $URLComponent = getParamTemplate($udv, 'component')['value']; $hostSource = getParamTemplate($udv, 'customUrlSource') !== '' ? translateToHuman(getParamTemplate($udv, 'customUrlSource')['value'], $udv) : $hostSource; switch ($URLComponent) { case 'HOST': $deets = $deets . 'The "hostname" part of the ' . $hostSource; if (getParam($udv, 'stripWww') !== null && getParam($udv, 'stripWww') === 'true') { $deets = $deets . ' - minus the www part - '; } $deets = $deets . ' will be returned.<br />'; break; case 'PATH': $deets = $deets . 'The path of the ' . $hostSource . ' will be returned.<br />'; if (strlen(getParamList($udv, 'defaultPages')) > 0) { $deets = $deets . 'The list of default pages to ignore is:<ul>'; $defaultPages = getParamList($udv, 'defaultPages'); foreach ($defaultPages as $defPageIndex => $defPageVal) { $deets = $deets . '<li>' . $defaultPages[$defPageIndex]['value'] . '</li>'; } $deets = $deets . '</ul><br />'; } break; case 'QUERY': $queryKey = ''; if (getParamTemplate($udv, 'queryKey') !== '') { $queryKey = variablise(getParamTemplate($udv, 'queryKey')['value'], $udv); } $deets = $deets . 'The value of the querystring variable (the part after the ? on the ' . $hostSource . ') "' . $queryKey . '" will be returned.<br /><br />'; break; case 'FRAGMENT': $deets = $deets . 'The fragment (the part after the # on the ' . $hostSource . ') will be returned.<br />'; break; case 'PORT': $deets = $deets . 'The port (80 or 443 for example) of the ' . $hostSource . ' will be returned.<br />'; break; case 'PROTOCOL': $deets = $deets . 'The protocol (http or https) of the ' . $hostSource . ' will be returned.<br />'; break; case 'URL': $deets = $deets . 'The full URL of the ' . $hostSource . ' will be returned.<br />'; break; } } if ($udv['type'] === 'smm') { $deets = $deets . 'The <i>input</i> variable for the lookup table is ' . variablise(getParamTemplate($udv, 'input')['value'] . '.<br /><br />', $udv); $deets = $deets . '<table class="table table-bordered table-striped"><tr><th>' . variablise(getParamTemplate($udv, 'input')['value'] . '', $udv) . '</th><th>Returned value</th></tr>'; $lookup = getParamList($udv, 'map'); foreach ($lookup as $lRow => $lRowVal) { $deets = $deets . '<tr><td>' . variablise($lookup[$lRow]['map'][0]['value'], $udv) . '</td>'; $deets = $deets . '<td>' . variablise($lookup[$lRow]['map'][1]['value'], $udv) . '</td></tr>'; } $deets = $deets . '</table>'; if (getParamTemplate($udv, 'defaultValue') !== '' && getParamTemplate($udv, 'defaultValue') !== null) { $deets = $deets . 'The default value returned if no matches are found in the table is "' . variablise(getParamTemplate($udv, 'defaultValue')['value'], $udv) . '".<br />'; } } if ($udv['type'] === 'jsm') { $varRefs = ''; $rawJS = getParam($udv, 'javascript'); $varRefs = getVarRefs($rawJS, $udv); findPushyVars($udv); if ($varRefs !== '') { $deets = $deets . 'Variables referenced in this variable:<br />' . $varRefs; } if ($rawJS !== '') { $deets = $deets . '<p style="margin:5px;"><textarea class="form-control" rows="10" cols="60" disabled="disabled">' . $rawJS . '</textarea></p><br />'; } } if ($udv['type'] !== 'c' && $udv['type'] !== 'smm') { $deets = $deets . defaultValue($udv); } $deets = $deets . '<tr><th>Where it\'s used</th>'; $deets = $deets . getUsage($udv); $deets = $deets . '<tr><th>Where it lives</th>'; if (array_key_exists('parentFolderId', $udv)) { $deets = $deets . '<td>' . folderisation($udv['parentFolderId'], 'User Defined Variable') . '</td></tr>'; } else { $deets = $deets . '<td>' . folderisation(null, 'User Defined Variable') . '</td></tr>'; } $deets = $deets . '</table>'; return $deets; }