{"version":3,"file":"siteMetadata.CSAr2XT7.mjs","names":[],"sources":["https:/framerusercontent.com/modules/zd2KTEKTM8WkfVPuesqs/Av05RzCqJxYXkDFgMuSV/siteMetadata.js"],"sourcesContent":["// Generated by Framer (53c1d35)\nexport default function metadata(params,activeLocale){return{customHTMLBodyEnd:'\\n\\n<script defer=\"\" src=\"https://cloud.umami.is/script.js\" data-website-id=\"69a19bb7-27bc-44db-93fd-443b8dc56634\"></script>\\n\\n<script>\\n  // Listen for SPA navigation using History API\\n  (function () {\\n    const pushState = history.pushState;\\n    const replaceState = history.replaceState;\\n\\n    history.pushState = function () {\\n      pushState.apply(this, arguments);\\n      window.dispatchEvent(new Event(\"navigation\"));\\n    };\\n\\n    history.replaceState = function () {\\n      replaceState.apply(this, arguments);\\n      window.dispatchEvent(new Event(\"navigation\"));\\n    };\\n\\n    // Event listener for navigation changes\\n    window.addEventListener(\"navigation\", trackPage);\\n    window.addEventListener(\"popstate\", trackPage); // Handles back/forward navigation\\n  })();\\n</script>\\n\\n<script>\\n  (function () {\\n  // Define UTM parameters you care about\\n  const utmParams = [\\'utm_source\\', \\'utm_medium\\', \\'utm_campaign\\', \\'utm_term\\', \\'utm_content\\'];\\n\\n  // Parse query string\\n  const urlParams = new URLSearchParams(window.location.search);\\n\\n  // Get current domain root (e.g., example.com from sub.example.com)\\n  const getRootDomain = () => {\\n    const hostname = window.location.hostname;\\n    const parts = hostname.split(\\'.\\');\\n    if (parts.length > 2) {\\n      return parts.slice(-2).join(\\'.\\');\\n    }\\n    return hostname;\\n  };\\n\\n  const rootDomain = getRootDomain();\\n\\n  const refvalue = urlParams.get(\\'ref\\');\\n  if (refvalue) {\\n    document.cookie = `${\\'cross_domain_referral\\'}=${encodeURIComponent(refvalue)}; path=/; domain=.${rootDomain}; max-age=${60 * 60 * 24 * 30}`;\\n  }\\n\\n  // Store each UTM parameter as a cookie\\n  utmParams.forEach(param => {\\n    const value = urlParams.get(param);\\n    if (value) {\\n      document.cookie = `${param}=${encodeURIComponent(value)}; path=/; domain=.${rootDomain}; max-age=${60 * 60 * 24 * 30}`;\\n    }\\n  });\\n})();\\n</script>\\n\\n<!-- store referrer start-->\\n<script>\\n(function () {\\n  const referrer = document.referrer;\\n\\n  // Check if the referrer exists and is NOT from a teamcamp.app domain and cookie is not already set\\n  if (\\n    referrer &&\\n    !referrer.includes(\\'.teamcamp.app\\') &&\\n    !referrer.includes(\\'teamcamp.app\\') && // covers root too\\n    !getCookie(\\'referrer_url\\')\\n  ) {\\n    setCookie(\\'referrer_url\\', referrer, 90);\\n  }\\n if (!getCookie(\\'lp_path\\')) {\\n  const landingPage = window.location.pathname + window.location.search;\\n  setCookie(\\'lp_path\\', landingPage, 90);\\n}\\n  \\n  // Set cookie for all *.teamcamp.app for 30 days\\n  function setCookie(name, value, days) {\\n    const oneDayMs = 60 * 60 * 24 * 1000; // 1 day in milliseconds\\n    const expires = new Date(Date.now() + days * oneDayMs).toUTCString();\\n    document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; domain=.teamcamp.app; samesite=lax`;\\n  }\\n\\n  // Helper to get cookie value by name\\n  function getCookie(name) {\\n    const match = document.cookie.match(new RegExp(\\'(^| )\\' + name + \\'=([^;]+)\\'));\\n    return match ? decodeURIComponent(match[2]) : null;\\n  }\\n})();\\n</script>\\n<!-- store referrer end-->\\n\\n<!-- event track start-->\\n<script>\\n  const trackingRoutes = [\\n    {\\n      match: (path) => path === \"/\",\\n      event: \"lp: home viewed\"\\n    },\\n    {\\n      match: (path) => path === \"/pricing\",\\n      event: \"lp: pricing viewed\"\\n    },\\n    {\\n      match: (path) => path === \"/product\",\\n      event: \"lp: feature list viewed\"\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/product/\"),\\n      event: \"lp: feature viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1(),slug: window.location.pathname.split(\"/\").pop() })\\n    },\\n    {\\n      match: (path) => path === \"/solution/marketing-teams\",\\n      event: \"lp: solution marketing teams viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1() })\\n    },\\n    {\\n      match: (path) => path === \"/solution/remote-teams\",\\n      event: \"lp: solution remote teams viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1() })\\n    },\\n    {\\n      match: (path) => path === \"/solution/agencies-studios\",\\n      event: \"lp: solution agency teams viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1() })\\n    },\\n    {\\n      match: (path) => path === \"/solution/it-software\",\\n      event: \"lp: solution it software teams viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1() })\\n    },\\n    {\\n      match: (path) => path === \"/resources/templates\",\\n      event: \"lp: template list viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/resources/templates/\"),\\n      event: \"lp: template viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1(),slug: window.location.pathname.split(\"/\").pop() }),\\n    },\\n    {\\n      match: (path) => path === \"/blogs\",\\n      event: \"lp: blog list viewed\"\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/blogs/category/\"),\\n      event: \"lp: blog category viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1(),slug: window.location.pathname.split(\"/\").pop() })\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/blogs/\") && !path.includes(\"/category/\"),\\n      event: \"lp: blog article viewed\",\\n      getProps: async () => ({ name: await getPageTitleFromH1(),slug: window.location.pathname.split(\"/\").pop() })\\n    },\\n    {\\n      match: (path) => path === \"/integrations\",\\n      event: \"lp: integration list viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/integrations/\"),\\n      event: \"lp: integration viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/updates\",\\n      event: \"lp: update viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/manifesto\",\\n      event: \"lp: manifesto viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/privacy-policy\",\\n      event: \"lp: privacy policy viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/terms-of-use\",\\n      event: \"lp: terms of use viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/contact-us\",\\n      event: \"lp: contact us viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/customers\",\\n      event: \"lp: customer list viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/customers/\"),\\n      event: \"lp: customer viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/download\",\\n      event: \"lp: download viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/comparison\",\\n      event: \"lp: comparison list viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/comparison/\"),\\n      event: \"lp: comparison viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/affiliate\",\\n      event: \"lp: affiliate viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/glossary\",\\n      event: \"lp: sales glossary viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/resources/glossary/\"),\\n      event: \"lp: sales glossary article viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/watch-demo\",\\n      event: \"lp: watch demo viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/activate-subscription\",\\n      event: \"lp: activate subscription viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/help\",\\n      event: \"lp: help center viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/help/\"),\\n      event: \"lp: help article viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/video-guides\",\\n      event: \"lp: video guide list viewed\",\\n    },\\n    {\\n      match: (path) => path.startsWith(\"/video-guides/\"),\\n      event: \"lp: video guide viewed\",\\n      getProps: async () => ({\\n        name: await getPageTitleFromH1(),\\n        slug: window.location.pathname.split(\"/\").pop(),\\n      }),\\n    },\\n    {\\n      match: (path) => path === \"/startup-program\",\\n      event: \"lp: startup program viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lp\",\\n      event: \"lp: landing page viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lp/form\",\\n      event: \"lp: landing page form viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lp/confirm\",\\n      event: \"lp: landing page confirmation viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lpv2\",\\n      event: \"lp: landing page 2 viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lpv2/form\",\\n      event: \"lp: landing page 2 form viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/lpv2/confirm\",\\n      event: \"lp: landing page 2 confirmation viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/utm-builder\",\\n      event: \"lp: utm builder viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/invoice-generator\",\\n      event: \"lp: invoice generator viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/burndown-chart-generator\",\\n      event: \"lp: burndown chart generator viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/font-convertor\",\\n      event: \"lp: font converter viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/image-convertor\",\\n      event: \"lp: image converter viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/agile-velocity-calculator\",\\n      event: \"lp: agile velocity calculator viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/roi-calculator\",\\n      event: \"lp: roi calculator viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/project-cost-calculator\",\\n      event: \"lp: project cost calculator viewed\",\\n    },\\n    {\\n      match: (path) => path === \"/resources/csv-to-json-converter\",\\n      event: \"lp: csv to json converter viewed\",\\n    },\\n  ];\\n\\n  function trackEvent(eventName, properties = {}) {\\n    if (typeof window.rudderanalytics !== \"undefined\") {\\n      window.rudderanalytics.track(eventName, properties);\\n    } \\n  }\\n\\n  async function getPageTitleFromH1(retries = 10) {\\n    while (retries > 0) {\\n      const h1 = document.querySelector(\"h1\");\\n      if (h1 && h1.innerText.trim()) return h1.innerText.trim();\\n      await new Promise(resolve => setTimeout(resolve, 200)); // wait 100ms\\n      retries--;\\n    }\\n    return \"Unknown Title\";\\n  }\\n\\n  async function handlePageViewTracking() {\\n    const currentPath = window.location.pathname;\\n\\n    for (const route of trackingRoutes) {\\n      if (route.match(currentPath)) {\\n        const props = route.getProps ? await route.getProps() : {};\\n        trackEvent(route.event, props);\\n        return;\\n      }\\n    }\\n\\n  }\\n\\n  // Initial page load\\n  document.addEventListener(\"DOMContentLoaded\", handlePageViewTracking);\\n\\n   // Function to set up download link tracking\\n    function setupDownloadLink({ selector, eventName, section }) {\\n      const waitForLink = setInterval(() => {\\n        const downloadLink = document.querySelector(selector);\\n\\n        if (downloadLink) {\\n          clearInterval(waitForLink); // Stop checking once the download link is found\\n          downloadLink.addEventListener(\"click\", async (event) => {\\n            event.preventDefault(); // Prevent the default anchor behavior\\n            const slug = downloadLink.getAttribute(\"href\"); // Get the URL from the href attribute\\n            const name = await getPageTitleFromH1(); // Get the page title\\n            trackEvent(eventName, {\\n              name,\\n              slug,\\n              section,\\n            }); // Track the download event\\n            setTimeout(() => {\\n              window.open(slug, \"_blank\"); // Open the download link in a new tab after a short delay\\n            }, 300);\\n          });\\n        }\\n      }, 200); // Check every 200ms for the download link\\n    }\\n\\n    // Set up download links for both sections\\n    setupDownloadLink({\\n      selector: \"#hero-section-download-button a\",\\n      eventName: \"lp: template download clicked\",\\n      section: \"hero section\",\\n    });\\n    setupDownloadLink({\\n      selector: \"#left-section-download-button a\",\\n      eventName: \"lp: template download clicked\",\\n      section: \"left section\",\\n    });\\n\\n  // SPA navigation (pushState, replaceState, popstate)\\n  function wrapHistoryMethod(method) {\\n    if (typeof history[method] === \"function\") {\\n      history[method] = new Proxy(history[method], {\\n        apply: (target, thisArg, argArray) => {\\n          const result = target.apply(thisArg, argArray);\\n          setTimeout(() => {\\n            handlePageViewTracking();\\n          }, 500);\\n          return result;\\n        },\\n      });\\n    }\\n  }\\n\\n  wrapHistoryMethod(\"pushState\");\\n  wrapHistoryMethod(\"replaceState\");\\n\\n  window.addEventListener(\"popstate\", () => {\\n    setTimeout(() => {\\n      handlePageViewTracking();\\n    }, 500);\\n  });\\n</script>\\n<!-- event track end-->\\n\\n',customHTMLBodyStart:'<!-- Google Tag Manager (noscript) -->\\n<noscript><iframe src=\"https://www.googletagmanager.com/ns.html?id=GTM-N8SMZXPX\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"></iframe></noscript>\\n<!-- End Google Tag Manager (noscript) -->',customHTMLHeadEnd:'<script type=\"text/javascript\">\\n  !function(){\"use strict\";window.RudderSnippetVersion=\"3.0.32\";var e=\"rudderanalytics\";window[e]||(window[e]=[])\\n  ;var rudderanalytics=window[e];if(Array.isArray(rudderanalytics)){\\n  if(true===rudderanalytics.snippetExecuted&&window.console&&console.error){\\n  console.error(\"RudderStack JavaScript SDK snippet included more than once.\")}else{rudderanalytics.snippetExecuted=true,\\n  window.rudderAnalyticsBuildType=\"legacy\";var sdkBaseUrl=\"https://cdn.rudderlabs.com/v3\";var sdkName=\"rsa.min.js\"\\n  ;var scriptLoadingMode=\"async\"\\n  ;var r=[\"setDefaultInstanceKey\",\"load\",\"ready\",\"page\",\"track\",\"identify\",\"alias\",\"group\",\"reset\",\"setAnonymousId\",\"startSession\",\"endSession\",\"consent\"]\\n  ;for(var n=0;n<r.length;n++){var t=r[n];rudderanalytics[t]=function(r){return function(){var n\\n  ;Array.isArray(window[e])?rudderanalytics.push([r].concat(Array.prototype.slice.call(arguments))):null===(n=window[e][r])||void 0===n||n.apply(window[e],arguments)\\n  }}(t)}try{\\n  new Function(\\'class Test{field=()=>{};test({prop=[]}={}){return prop?(prop?.property??[...prop]):import(\"\");}}\\'),\\n  window.rudderAnalyticsBuildType=\"modern\"}catch(o){}var d=document.head||document.getElementsByTagName(\"head\")[0]\\n  ;var i=document.body||document.getElementsByTagName(\"body\")[0];window.rudderAnalyticsAddScript=function(e,r,n){\\n  var t=document.createElement(\"script\");t.src=e,t.setAttribute(\"data-loader\",\"RS_JS_SDK\"),r&&n&&t.setAttribute(r,n),\\n  \"async\"===scriptLoadingMode?t.async=true:\"defer\"===scriptLoadingMode&&(t.defer=true),\\n  d?d.insertBefore(t,d.firstChild):i.insertBefore(t,i.firstChild)},window.rudderAnalyticsMount=function(){!function(){\\n  if(\"undefined\"==typeof globalThis){var e;var r=function getGlobal(){\\n  return\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:null}();r&&Object.defineProperty(r,\"globalThis\",{\\n  value:r,configurable:true})}\\n  }(),window.rudderAnalyticsAddScript(\"\".concat(sdkBaseUrl,\"/\").concat(window.rudderAnalyticsBuildType,\"/\").concat(sdkName),\"data-rsa-write-key\",\"2pcDOg9QtG21slSRjvYA0PzL7x9\")\\n  },\\n  \"undefined\"==typeof Promise||\"undefined\"==typeof globalThis?window.rudderAnalyticsAddScript(\"https://polyfill-fastly.io/v3/polyfill.min.js?version=3.111.0&features=Symbol%2CPromise&callback=rudderAnalyticsMount\"):window.rudderAnalyticsMount()\\n  ;var loadOptions={ autoTrack: false};rudderanalytics.load(\"2pcDOg9QtG21slSRjvYA0PzL7x9\",\"https://pixersanjgywax.dataplane.rudderstack.com\",loadOptions)}}}();\\n</script>',customHTMLHeadStart:'<!-- Google Tag Manager -->\\n<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\\'gtm.start\\':\\nnew Date().getTime(),event:\\'gtm.js\\'});var f=d.getElementsByTagName(s)[0],\\nj=d.createElement(s),dl=l!=\\'dataLayer\\'?\\'&l=\\'+l:\\'\\';j.async=true;j.src=\\n\\'https://www.googletagmanager.com/gtm.js?id=\\'+i+dl;\\nj.addEventListener(\\'load\\', function() {\\n  var _ge = new CustomEvent(\\'gtm_loaded\\', { bubbles: true });\\n  d.dispatchEvent(_ge);\\n});\\nf.parentNode.insertBefore(j,f);\\n})(window,document,\\'script\\',\\'dataLayer\\',\\'GTM-N8SMZXPX\\');</script>\\n<!-- End Google Tag Manager -->\\n\\n<script type=\"text/javascript\" src=\"//app.pageproofer.com/embed/cf85707c-f298-548d-abbf-65b663f39cdf\" async=\"true\"></script>\\n\\n<script type=\"application/ld+json\">\\n{\\n  \"@context\": \"https://schema.org\",\\n  \"@type\": \"Organization\",\\n  \"name\": \"Teamcamp\",\\n  \"url\": \"https://www.teamcamp.app\",\\n  \"logo\": \"https://media2.dev.to/dynamic/image/width=320,height=320,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10233%2Fa214d929-4a86-43e3-8a25-ba25c166bdae.png\",\\n  \"sameAs\": [\\n    \"https://www.linkedin.com/company/teamcamp-app/\",\\n    \"https://x.com/teamcampapp\"\\n  ]\\n}\\n</script>\\n<script type=\"application/ld+json\">\\n{\\n  \"@type\": \"SoftwareApplication\",\\n  \"name\": \"Teamcamp - All-in-one Project Management Applicatoin\",\\n  \"operatingSystem\": \"All\",\\n  \"applicationCategory\": \"Project Management\",\\n  \"offers\": {\\n    \"@type\": \"Offer\",\\n    \"price\": \"49\",\\n    \"priceCurrency\": \"USD\"\\n  }\\n}\\n</script>\\n',description:\"Discover Teamcamp: the project management tool for IT, marketing, freelancers, and agencies. Manage tasks, collaborate, track time, and simplify billing easily.\",favicon:\"https://framerusercontent.com/assets/B7FVn96BbMrxlynl96uOTWs8jiU.png\",robots:\"max-image-preview:large\",socialImage:\"https://framerusercontent.com/assets/GyM58HUbE2FAXakf0OVOZ5KI.png\",title:\"Teamcamp: Streamline Project Management for IT, Marketing, and Agencies\"};}export const metadataVersion=1;\nexport const __FramerMetadata__ = {\"exports\":{\"metadataVersion\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"default\":{\"type\":\"function\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}"],"mappings":"2DACA,SAAwB,EAAS,EAAO,EAAa,CAAC,MAAM,CAAC,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAgya,oBAAoB;;4CAAwP,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;YAA+8E,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAsiD,YAAY,mKAAmK,QAAQ,uEAAuE,OAAO,0BAA0B,YAAY,oEAAoE,MAAM,0EAA0E,AAAE"}