### UpGuard Zapier Integrations Overview Source: https://www.upguard.com/integrations Lists common integrations available for UpGuard through Zapier, enabling automation between UpGuard and other business applications. ```Zapier UpGuard Integrations via Zapier: - Trello: Add attachment to card in Trello when a new data leak is Published in UpGuard. - Zendesk: Connect Zendesk for seamless workflow automation. - Slack: Connect Slack to easily collaborate with others on security related events. - Jira: Create a new service request in Jira when a new data leak is published in UpGuard. - Google Sheets: Automatically send info between UpGuard and Google Sheets. - ServiceNow: Automatically monitor vendors in UpGuard when they are added in ServiceNow. - Microsoft Teams: Get instant notifications about critical security events in your team chat. View all integrations: https://zapier.com/apps/upguard/integrations ``` -------------------------------- ### Load Script Utility Source: https://www.upguard.com/integrations A generic function to load a JavaScript file from a given source URL and execute a callback function once the script has loaded. ```javascript function loadScript(callback, src) { var script; script = document.createElement('script'); script.onload = callback; script.src = src; document.body.appendChild(script); } ``` -------------------------------- ### Initialize Segment.io Analytics Source: https://www.upguard.com/pricing Initializes the Segment.io analytics library. This snippet includes the standard setup for Segment, defining its methods, factories, and loading mechanism. It sets up a fallback for multiple inclusions and defines how to load the analytics script from a CDN. ```javascript !function(){ var i="analytics",analytics=window[i]=window[i]||[]; if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{ analytics.invoked=!0; analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"]; analytics.factory=function(e){ return function(){ if(window[i].initialized)return window[i][e].apply(window[i],arguments); var n=Array.prototype.slice.call(arguments); if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){ var c=document.querySelector("link[rel='canonical']"); n.push({"__t":"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer}) } n.unshift(e); analytics.push(n); return analytics } }; for(var n=0;n *, .children-h-full > .w-dyn-item > * { height: 100%; } ``` -------------------------------- ### Initialize Segment.io Analytics Source: https://www.upguard.com/integrations Initializes the Segment.io analytics library. This snippet configures the analytics object, defines its methods, and loads the Segment CDN script with a specific write key. It includes logic to handle potential duplicate inclusions and sets up basic page tracking properties. ```javascript !function(){ var i="analytics",analytics=window[i]=window[i]||[]; if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{ analytics.invoked=!0; analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"]; analytics.factory=function(e){ return function(){ if(window[i].initialized)return window[i][e].apply(window[i],arguments); var n=Array.prototype.slice.call(arguments); if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){ var c=document.querySelector("link[rel='canonical']"); n.push({"__t":"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer}) } n.unshift(e); analytics.push(n); return analytics } }; for(var n=0;n-1){var c=document.querySelector("link[rel='canonical']");n.push({"__t":"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n-1){var c=document.querySelector("link[rel='canonical']");n.push({"__t":"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n { const params = new URLSearchParams(window.location.search); if (params.has("ug_usercentrics_on")) { window.ug_usercentrics_on = true; document.addEventListener("DOMContentLoaded", () => { const resetBtn = document.createElement("button"); resetBtn.textContent = "Reset UC"; resetBtn.style = `position: fixed; z-index: 999; top: 0;right: 0; margin: 15px;`; resetBtn.onclick = () => { UC_UI.clearStorage(); location.reload(); }; document.body.appendChild(resetBtn); }); } const segmentKey = window.location.host === "www.upguard.com" ? "GAG8dK4Ra4de1G0AV7ah50u36nBVTYCt" : "IM4gZZObNPxWwjdMucSbgVCvYGDBHHmu"; if (!window.ug_usercentrics_on) { analytics.load(segmentKey); trackPageWithProperties() } else { let rulsetId = params.has("ug_uc_ruleset_id") ? params.get('ug_uc_ruleset_id') : false let settingsId = params.has("ug_uc_settings_id") ? params.get('ug_uc_settings_id') : false const s = document.createElement("script"); s.src = "https://web.cmp.usercentrics.eu/ui/loader.js"; s.id = "usercentrics-cmp"; s.setAttribute("data-draft", "true"); if(rulsetId){ s.setAttribute("data-ruleset-id", rulsetId) } else if (settingsId){ s.setAttribute("data-settings-id", settingsId) } else { s.setAttribute("data-settings-id", "ty7gEZF53bc1_x") } s.async = true; document.head.appendChild(s); window.addEventListener("usercentrics_update", handleUCExplicitConsent) let isSegmentLoaded = false function handleUCExplicitConsent(event) { if (isSegmentLoaded) return if (!(event.detail.event === "consent_status" && event.detail.type === "EXPLICIT")) return; const hasConsent = (str) => event.detail.hasOwnProperty(str) && event.detail[str] === true; analytics.load(segmentKey, { integrations: { All: false, "Mixpanel (Actions)": hasConsent("Mixpanel"), "Hubspot Web (Actions)": hasConsent("HubSpot"), "Google AdWords New": hasConsent("Google Ads"), "Facebook Pixel": hasConsent("Facebook Pixel"), "Google Analytics 4 Web": hasConsent("Google Analytics"), "PERSONAS - Google AdWords": hasConsent("Google Ads"), "Hotjar": hasConsent("Hotjar"), "HubSpot": hasConsent("HubSpot"), "LinkedIn Insight Tag": hasConsent("LinkedIn Insight Tag"), "LinkedIn Conversions API": hasConsent("LinkedIn Insight Tag"), "Linkedin Audiences": hasConsent("LinkedIn Insight Tag"), "Postgres": hasConsent("UpGuard Marketing Events Database"), "Segment.io": hasConsent("Segment") } }) trackPageWithProperties() isSegmentLoaded = true }; } // ``` -------------------------------- ### Responsive Grid Layouts Source: https://www.upguard.com/blog Implements a flexible grid system with predefined column counts (2, 3, 4) and responsive adjustments for different screen sizes. It uses CSS Grid properties to define column gaps and auto-columns. ```CSS /* Layout */ @media screen and (max-width: 767px) { :root { --page--margin: 2rem; } } @media screen and (max-width: 479px) { :root { --page--margin: 1.25rem; } } /* Grid */ .grid-4cols, .grid-3cols, .grid-2cols { grid-column-gap: var(--gap--grid); grid-row-gap: var(--gap--grid); grid-auto-columns: 1fr; width: 100%; display: grid; } .grid-4cols { grid-template-columns: 1fr 1fr 1fr 1fr; } @media screen and (max-width: 991px) { .grid-4cols { grid-template-columns: 1fr 1fr; } } @media screen and (max-width: 767px) { .grid-4cols { grid-template-columns: 1fr; } } .grid-3cols { grid-template-columns: 1fr 1fr 1fr; } @media screen and (max-width: 991px) { .grid-3cols { grid-template-columns: 1fr; } } .grid-2cols { grid-template-columns: 1fr 1fr; } @media screen and (max-width: 991px) { .grid-2cols { grid-template-columns: 1fr; } } @media screen and (max-width: 991px) and (min-width: 768px) { .grid-3cols-t { grid-template-columns: 1fr 1fr 1fr; } .grid-2cols-t { grid-template-columns: 1fr 1fr; } } @media screen and (max-width: 767px) and (min-width: 480px) { .grid-2cols-ml { grid-template-columns: 1fr 1fr; } } @media screen and (max-width: 479px) { .grid-2cols-mp { grid-template-columns: 1fr 1fr; } } ``` -------------------------------- ### Wait Before Calling Utility Source: https://www.upguard.com/integrations A utility function that delays the execution of a given function until a scroll event occurs, with an optional delay. It uses `requestIdleCallback` if available for more efficient execution. ```javascript window.waitBeforeCalling = (fn, ms=3000) => (...args) => { window.addEventListener("scroll", () => setTimeout( () => 'requestIdleCallback'in window ? requestIdleCallback( () => fn(...args)) : fn(...args), ms ), { once: true }); }; ``` -------------------------------- ### Update Copyright Year Source: https://www.upguard.com/product/breach-risk This JavaScript snippet dynamically updates the copyright year displayed on the page by getting the current year from the Date object. ```javascript document.getElementById("copyright-year").innerHTML = "@" + new Date().getFullYear(); ``` -------------------------------- ### Load Upguard Segment.js Script Source: https://www.upguard.com/integrations Appends the Segment.js script from Upguard's assets to the document's head. This script is typically utilized for analytics and user behavior tracking. ```javascript ( () => { const s = document.createElement('script') s.src = "https://assets.upguard.com/wf/segment.js" document.head.appendChild(s) } )() ``` -------------------------------- ### Initialize Image Zoom Plugin Source: https://www.upguard.com/blog Configures the 'imagezoomsl' jQuery plugin for elements with the class 'image-zoom-example'. It enables inner zoom, customizes the magnifier appearance, and optionally disables mouse wheel scrolling. ```javascript jQuery(function(){ if(!$.fn.imagezoomsl){ $('.msg').show(); return; } else $('.msg').hide(); // plugin initialization $('.image-zoom-example').imagezoomsl({ innerzoommagnifier: true, classmagnifier: "round-loope", magnifiersize: [150, 150], // disables the scrolling of the document with the mouse wheel when the cursor is over the image disablewheel: false }); }); ``` -------------------------------- ### Handle Usercentrics Update Event Source: https://www.upguard.com/integrations Listens for the 'usercentrics_update' event and dynamically adds a 'Do not sell or share my personal information' button to the footer. It ensures the button is added only once to prevent duplicates. ```javascript let isLinkAdded = false; window.addEventListener("usercentrics_update", (e) => { if (isLinkAdded) return; var newContent = ``; document.getElementById("uc-footer-link-a6j").innerHTML = newContent; isLinkAdded = true; }); ``` -------------------------------- ### HubSpot Form Initialization Source: https://www.upguard.com/blog This JavaScript snippet initializes a HubSpot form on the webpage. It uses a helper function `waitBeforeCalling` to ensure the script loads after a delay, and `loadScript` to dynamically load the HubSpot forms JavaScript library before creating the form instance with specified region, portalId, and formId. ```javascript waitBeforeCalling(() => { loadScript(function() { hbspt.forms.create({ region: "na1", portalId: "228391", formId: "8c367db9-e70f-4cd8-a16c-4d23ed1d29eb" }) }, "//js.hsforms.net/forms/v2.js"); }, 500)(); ``` -------------------------------- ### Button Styles: Outline Variant Source: https://www.upguard.com/integrations Styles buttons with a transparent background and border, using the theme's link color for text. Hover states maintain transparency but reduce opacity. ```css .button[data-style="outline"] { --button--background-color: transparent; --button--border-color: var(--theme--link-color, #fff); --button--text-color: var(--theme--link-color, #fff); --button--hover-background-color: transparent; --button--hover-border-color: var(--theme--link-color, #fff); --button--hover-text-color: var(--theme--link-color, #fff); --button--hover-opacity: 0.75; } ``` -------------------------------- ### Build Release Navigation Links Source: https://www.upguard.com/releases This JavaScript code generates a table of contents for release navigation. It calculates pagination links for monthly and yearly release archives, linking to specific dates within the content. It handles dynamic pagination parameters and Webflow's collection list limitations. ```javascript (() => { // This code builds ToC links to historic months and years, calulating which paginated page they appear on (eg /2#2024-06-01) and linking to the id of the first release in the corresponding month const postsPerPage = 12 // Match pagination settings const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] const currYear = (new Date()).getFullYear() const currUrl = new URL(window.location) const $$paginationLinks = Array.from(document.querySelectorAll(".w-pagination-next, .w-pagination-next")) // The links to /2 etc at the bottom of the page const $linksPlaceholder = document.querySelector('[data-placeholder="release-links-sidebar"]') // The element we're going to insert out ToC links into const $$dates = Array.from(document.querySelectorAll("[data-release-date]")) // The hidden (display: none) collection items that are just used so we can read ALL of the dates. This is multiple collection lists to get around Webflow's 100 item per list limitation. // Get the URL details for pagination, eg /releases?b5f7196c_page=n, since the param appears to be dynamic let urlPathname let urlPaginationParam $$paginationLinks.forEach($el => { const url = new URL($el.href) url.searchParams.forEach((_, key) => { if (key.indexOf("_page") > -1) { urlPathname = url.pathname urlPaginationParam = key } }) }) // Build monthly navigation for the current year's releases, then yearly for everything older let year let month const createWidget = () => { const $widget = document.createElement("div") $widget.classList.add("widget") return $widget } const createHeading = (title) => { const $h = document.createElement("h5") $h.classList.add("widget-heading") $h.innerText = title return $h } const createLink = (dateString, label, pageNum) => { const $link = document.createElement("a") $link.classList.add("categories-widget-item") $link.innerText = label // Handle smooth scrolling with a hash=only URL due to /releases and /releases?b5f7196c_page=1 both being valid URLs Webflow uses $link.href = currUrl.searchParams.get(urlPaginationParam) == pageNum || (!currUrl.searchParams.get(urlPaginationParam) && pageNum === 1) ? `#${dateString}` : `${urlPathname}?${urlPaginationParam}=${pageNum}#${dateString}` return $link } const $$currYearLinks = $$dates .map(($el, i) => { const dateString = $el.getAttribute("data-release-date") // eg 2024-06-19 const [y, m] = dateString.split("-").map(x => parseInt(x, 10)) // Monthly links if (y == currYear && !month || m < month) { month = m return createLink(dateString, `${monthNames[m - 1]} ${y}`, Math.floor(i / postsPerPage) + 1) } }) .filter(Boolean) // remove empty const $$previousYearLinks = $$dates .map(($el, i) => { const dateString = $el.getAttribute("data-release-date") // eg 2024-06-19 const [y, m] = dateString.split("-").map(x => parseInt(x, 10)) // Annual links if (y < currYear && !year || y < year) { year = y return createLink(dateString, `${y}`, Math.floor(i / postsPerPage) + 1) } }) .filter(Boolean) // remove empty if ($$currYearLinks.length) { const $widget = createWidget() $widget.append(createHeading(currYear + " Releases")) $$currYearLinks.forEach($link => $widget.append($link)) $linksPlaceholder.append($widget) } if ($$previousYearLinks.length) { const $widget = createWidget() $widget.append(createHeading("Older Releases")) $$previousYearLinks.forEach($link => $widget.append($link)) $linksPlaceholder.append($widget) } })() ``` -------------------------------- ### Initialize Segment.io Analytics Source: https://www.upguard.com/releases Initializes the Segment.io analytics library. It sets up the analytics object with various methods for tracking user events, page views, and user identification. The snippet includes logic to prevent double inclusion and defines a factory function for method initialization. It also specifies the Segment write key and snippet version. ```javascript // load Segment API !function(){ var i="analytics",analytics=window[i]=window[i]||[]; if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{ analytics.invoked=!0; analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"]; analytics.factory=function(e){ return function(){ if(window[i].initialized)return window[i][e].apply(window[i],arguments); var n=Array.prototype.slice.call(arguments); if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){ var c=document.querySelector("link[rel='canonical']"); n.push({"__t":"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer}) } n.unshift(e); analytics.push(n); return analytics } }; for(var n=0;n 7; _7d -= _Ve; _j3 == _j3; _7d += 61; _7d %= 94; _7d += 33; _j3 += String.fromCharCode(_7d) } return _j3 })(atob('YlFYendybWt8U20j'), 8)] = 'b9f622da431684301942'; var zi = document.createElement('script'); (zi.type = 'text/javascript'), (zi.async = true), (zi.src = (function(_x8E, _i2) { var _ss = ''; for (var _gp = 0; _gp < _x8E.length; _gp++) { _i2 > 5; var _oP = _x8E[_gp].charCodeAt(); _oP != _gp; _oP -= _i2; _oP += 61; _ss == _ss; _oP %= 94; _oP += 33; _ss += String.fromCharCode(_oP) })(atob('fCoqJilOQ0N+KUIwfUEpdyh9JiopQnclI0MwfUEqdXtCfik='), 20)), document.readyState === 'complete' ? document.body.appendChild(zi) : window.addEventListener('load', function() { document.body.appendChild(zi) });` }) ``` -------------------------------- ### Load HockeyStack Script Source: https://www.upguard.com/integrations Dynamically loads the HockeyStack analytics script. It includes an API key, enables cookieless tracking and auto-identification, and respects user consent settings via the 'data-usercentrics' attribute. ```javascript var hsscript = document.createElement("script"); hsscript.id = "wphs"; hsscript.src = "https://cdn.jsdelivr.net/npm/hockeystack@latest/hockeystack.min.js"; hsscript.async = 1; hsscript.dataset.apikey = "6e248ddcff92ec0dbfc3def09656b2"; hsscript.dataset.cookieless = 1; hsscript.dataset.autoIdentify = 1; if(window.ug_usercentrics_on){ hsscript.type = "text/plain" hsscript.dataset.usercentrics = "HockeyStack" } document.getElementsByTagName('head')[0].append(hsscript); ``` -------------------------------- ### Dynamic Release Link Rendering (JavaScript) Source: https://www.upguard.com/releases This JavaScript code dynamically renders lists of links for current and previous release years. It appends widgets containing headings and links to a placeholder element, likely for a release notes section. ```javascript rYear)) $$currYearLinks.forEach($link => $widget.append($link)) $linksPlaceholder.append($widget) } if ($$previousYearLinks.length) { const $widget = createWidget() $widget.append(createHeading("Previous Releases")) $$previousYearLinks.forEach($link => $widget.append($link)) $linksPlaceholder.append($widget) } })() ``` -------------------------------- ### Button Styles: Size Variants Source: https://www.upguard.com/integrations Defines specific font sizes, line heights, and padding for different button sizes, including 'small' and 'nav'. These styles adjust the visual dimensions and readability of buttons. ```css .button[data-size="small"] { /* height 36px, font 13px */ font-size: 0.8125rem; line-height: 1.125rem; padding: 8px 14px; } .button[data-size="nav"] { /* height 38px, font 15px */ font-size: 0.9375rem; line-height: 1.25rem; padding: 8px 14px; } ``` -------------------------------- ### Load Jetboost Script Source: https://www.upguard.com/product/vendorrisk This JavaScript snippet initializes Jetboost by setting a site ID and asynchronously loading the Jetboost JavaScript library from a CDN. It's used for enhancing website functionality. ```javascript window.JETBOOST_SITE_ID = "ckcu36rvzeeld078130pdnjt5"; (function(d) { var s = d.createElement("script"); s.src = "https://cdn.jetboost.io/jetboost.js"; s.async = 1; d.getElementsByTagName("head")[0].appendChild(s); })(document); ``` -------------------------------- ### Button Styles: Base and Hover Effects Source: https://www.upguard.com/integrations Defines base styles and hover/focus-visible states for buttons, including transitions and opacity changes. It also handles parent-based hover states for elements like arrows. ```css [data-hover-parent]:hover .arrow__tip, [data-hover-parent]:focus-visible .arrow__tip, .arrow:hover .arrow__tip, .arrow:focus-visible .arrow__tip { transform: translateX(4px); } [data-hover-parent]:hover .arrow__tail, [data-hover-parent]:focus-visible .arrow__tail, .arrow:hover .arrow__tail, .arrow:focus-visible .arrow__tail { transform: scaleX(1); } .button:hover, button:focus-visible, [data-hover-parent]:hover .button, [data-hover-parent]:focus-visible .button { --button--background-color: var(--button--hover-background-color); --button--border-color: var(--button--hover-border-color); --button--text-color: var(--button--hover-text-color); opacity: var(--button--hover-opacity, 1); } ```