{
  "version": 3,
  "sources": ["ssg:https://framerusercontent.com/modules/ceJuitnhWPSAptJ9wpoJ/nXYVKYCREs5wkiMfiKKF/siteMetadata.js"],
  "sourcesContent": ["// Generated by Framer (dc5e905)\nconst htmlEscape=value=>{if(typeof value!==\"string\")return\"\";return value.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\");};const toString=value=>{return typeof value===\"string\"?value:String(value);};export default function metadata(params,activeLocale){const os=params?.os;const user=params?.user;return{customHTMLBodyEnd:'<!-- Mida A/B Testing Script -->\\n<script type=\"text/javascript\" async=\"\" src=\"https://cdn.mida.so/js/optimize.js?key=3Ejq4KNndxAp9YJyArpv7b\"></script>\\n\\n<script type=\"application/ld+json\">\\n{\\n  \"@context\": \"https://schema.org\",\\n  \"@graph\": [\\n    {\\n      \"@type\": [\"SoftwareApplication\", \"Product\"],\\n      \"@id\": \"https://pieces.app/#software\",\\n      \"name\": \"Pieces for developers \u2013 long-term memory agent\",\\n      \"description\": \"Pieces is your AI long-term memory agent that captures live context from browsers to IDEs and tools, manages snippets, and supports multiple LLMs.\",\\n      \"operatingSystem\": [\"Windows\", \"macOS\", \"Linux\"],\\n      \"applicationCategory\": \"DeveloperApplication\",\\n      \"downloadUrl\": \"https://docs.pieces.app/installation-getting-started/what-am-i-installing\",\\n      \"url\": \"https://pieces.app/\"\\n    },\\n    {\\n      \"@type\": \"Organization\",\\n      \"@id\": \"https://pieces.app/#organization\",\\n      \"name\": \"Pieces\",\\n      \"url\": \"https://pieces.app\",\\n      \"logo\": {\\n        \"@type\": \"ImageObject\",\\n        \"url\": \"https://docs.pieces.app/assets/pieces_logos/wordmark.svg\",\\n        \"width\": 112,\\n        \"height\": 112\\n      },\\n      \"sameAs\": [\\n        \"https://twitter.com/getpieces\",\\n        \"https://github.com/pieces-app\"\\n      ]\\n    },\\n    {\\n      \"@type\": \"WebSite\",\\n      \"@id\": \"https://pieces.app/#website\",\\n      \"url\": \"https://pieces.app/\",\\n      \"name\": \"Pieces for developers \u2013 long-term memory agent\",\\n      \"description\": \"Pieces is your AI long-term memory agent that captures live context from browsers to IDEs and tools, manages snippets, and supports multiple LLMs.\",\\n      \"publisher\": {\\n        \"@id\": \"https://pieces.app/#organization\"\\n      }\\n    },\\n    {\\n      \"@type\": \"WebPage\",\\n      \"@id\": \"https://pieces.app/#webpage\",\\n      \"url\": \"https://pieces.app/\",\\n      \"name\": \"Pieces for developers \u2013 long-term memory agent\",\\n      \"isPartOf\": { \"@id\": \"https://pieces.app/#website\" },\\n      \"breadcrumb\": { \"@id\": \"https://pieces.app/#breadcrumb\" },\\n      \"description\": \"Pieces is your AI long-term memory agent that captures live context from browsers to IDEs and tools, manages snippets, and supports multiple LLMs.\",\\n      \"inLanguage\": \"en-US\"\\n    },\\n    {\\n      \"@type\": \"BreadcrumbList\",\\n      \"@id\": \"https://pieces.app/#breadcrumb\",\\n      \"itemListElement\": [\\n        {\\n          \"@type\": \"ListItem\",\\n          \"position\": 1,\\n          \"item\": {\\n            \"@id\": \"https://pieces.app/\",\\n            \"name\": \"Home\"\\n          }\\n        }\\n      ]\\n    }\\n  ]\\n}\\n</script>',customHTMLBodyStart:'<!-- Google Tag Manager (noscript) -->\\n<noscript><iframe src=\"https://www.googletagmanager.com/ns.html?id=GTM-K8C6QWB\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"></iframe></noscript>\\n<!-- End Google Tag Manager (noscript) -->',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;f.parentNode.insertBefore(j,f);\n})(window,document,'script','dataLayer','GTM-K8C6QWB');</script>\n<!-- End Google Tag Manager -->\n\n<script>\n  !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<analytics.methods.length;n++){var key=analytics.methods[n];analytics[key]=analytics.factory(key)}analytics.load=function(key,n){var t=document.createElement(\"script\");t.type=\"text/javascript\";t.async=!0;t.setAttribute(\"data-global-segment-analytics-key\",i);t.src=\"https://cdn.segment.com/analytics.js/v1/\" + key + \"/analytics.min.js\";var r=document.getElementsByTagName(\"script\")[0];r.parentNode.insertBefore(t,r);analytics._loadOptions=n};analytics._writeKey=\"5v6JATBPr9p7vYKDCp3JHGw5YsBUtyep\";;analytics.SNIPPET_VERSION=\"5.2.0\";\n  analytics.load(\"5v6JATBPr9p7vYKDCp3JHGw5YsBUtyep\");\n  // analytics.page();\n  }}();\n</script>\n\n\n<script>\nfunction getCookie(name) {\n    var match = document.cookie.match(new RegExp(\"(^| )\" + name + \"=([^;]+)\"));\n    return match ? match[2] : null;\n}\n\nfunction getParamFromURL(param) {\n    var params = new URLSearchParams(window.location.search);\n    return params.has(param) ? params.get(param) : null;\n}\n\nfunction initializeIndexedDB() {\n    return new Promise((resolve, reject) => {\n        let request = indexedDB.open(\"TrackingDB\", 2); // Increment version to trigger onupgradeneeded\n        \n        request.onupgradeneeded = function(event) {\n            let db = event.target.result;\n            \n            // Check if the object store exists and create it if it doesn't\n            if (!db.objectStoreNames.contains(\"TrackingStore\")) {\n                db.createObjectStore(\"TrackingStore\", { keyPath: \"id\" });\n                console.log(\"\u2705 Object store 'TrackingStore' created\");\n            }\n        };\n        \n        request.onsuccess = function(event) {\n            console.log(\"\u2705 IndexedDB initialized successfully\");\n            let db = event.target.result;\n            resolve(db);\n        };\n        \n        request.onerror = function(event) {\n            console.error(\"\u274C Error initializing IndexedDB:\", event.target.error);\n            reject(event.target.error);\n        };\n    });\n}\n\nfunction saveToIndexedDB(newData) {\n    return initializeIndexedDB()\n        .then(db => {\n            return new Promise((resolve, reject) => {\n                try {\n                    let tx = db.transaction(\"TrackingStore\", \"readwrite\");\n                    let store = tx.objectStore(\"TrackingStore\");\n                    let getRequest = store.get(1);\n                    \n                    getRequest.onsuccess = function(event) {\n                        let existingData = event.target.result || {};\n                        \n                        let mergedData = {\n                            id: 1,\n                            firstVisitDate: existingData.firstVisitDate || new Date().toISOString(),\n                            osDetectedDate: existingData.osDetectedDate || (newData.osId ? new Date().toISOString() : null),\n                            osId: newData.osId || existingData.osId,\n                            userName: newData.userName || existingData.userName,\n                            referrer: newData.referrer || existingData.referrer,\n                            // Only update these fields if new values are explicitly provided (not null/undefined)\n                            trafficSource: newData.trafficSource !== undefined && newData.trafficSource !== null \n                                ? newData.trafficSource \n                                : existingData.trafficSource,\n                            trafficMedium: newData.trafficMedium !== undefined && newData.trafficMedium !== null \n                                ? newData.trafficMedium \n                                : existingData.trafficMedium,\n                            trafficName: newData.trafficName !== undefined && newData.trafficName !== null \n                                ? newData.trafficName \n                                : existingData.trafficName,\n                            gaId: newData.gaId || existingData.gaId,\n                            pageUrl: newData.pageUrl,\n                            pagePath: newData.pagePath,\n                            lastUpdated: new Date().toISOString()\n                        };\n                        \n                        let putRequest = store.put(mergedData);\n                        \n                        putRequest.onsuccess = function() {\n                            console.log(\"\u2705 Data saved to IndexedDB\", mergedData);\n                            resolve(mergedData);\n                        };\n                        \n                        putRequest.onerror = function(event) {\n                            console.error(\"\u274C Error saving to IndexedDB:\", event.target.error);\n                            reject(event.target.error);\n                        };\n                    };\n                    \n                    getRequest.onerror = function(event) {\n                        console.error(\"\u274C Error reading from IndexedDB:\", event.target.error);\n                        reject(event.target.error);\n                    };\n                    \n                    tx.oncomplete = function() {\n                        db.close();\n                    };\n                    \n                    tx.onerror = function(event) {\n                        console.error(\"\u274C Transaction error:\", event.target.error);\n                        reject(event.target.error);\n                    };\n                } catch (error) {\n                    console.error(\"\u274C Exception in saveToIndexedDB:\", error);\n                    reject(error);\n                }\n            });\n        })\n        .catch(error => {\n            console.error(\"\u274C Failed to save data:\", error);\n            // Try to recover by deleting and recreating the database\n            return deleteDatabase().then(() => {\n                console.log(\"\uD83D\uDD04 Database deleted, attempting to reinitialize...\");\n                return initializeIndexedDB().then(() => {\n                    console.log(\"\uD83D\uDD04 Retrying save operation...\");\n                    return saveToIndexedDB(newData);\n                });\n            });\n        });\n}\n\nfunction retrieveFromIndexedDB() {\n    return initializeIndexedDB()\n        .then(db => {\n            return new Promise((resolve, reject) => {\n                try {\n                    let tx = db.transaction(\"TrackingStore\", \"readonly\");\n                    let store = tx.objectStore(\"TrackingStore\");\n                    let getRequest = store.get(1);\n                    \n                    getRequest.onsuccess = function(event) {\n                        let data = event.target.result || {};\n                        console.log(\"\uD83D\uDD0D Retrieved from IndexedDB:\", data);\n                        resolve(data);\n                    };\n                    \n                    getRequest.onerror = function(event) {\n                        console.error(\"\u274C Error retrieving from IndexedDB:\", event.target.error);\n                        reject(event.target.error);\n                    };\n                    \n                    tx.oncomplete = function() {\n                        db.close();\n                    };\n                } catch (error) {\n                    console.error(\"\u274C Exception in retrieveFromIndexedDB:\", error);\n                    reject(error);\n                }\n            });\n        })\n        .catch(error => {\n            console.error(\"\u274C Failed to retrieve data:\", error);\n            return {};\n        });\n}\n\nfunction deleteDatabase() {\n    return new Promise((resolve, reject) => {\n        let deleteRequest = indexedDB.deleteDatabase(\"TrackingDB\");\n        \n        deleteRequest.onsuccess = function() {\n            console.log(\"\u2705 Database deleted successfully\");\n            resolve();\n        };\n        \n        deleteRequest.onerror = function(event) {\n            console.error(\"\u274C Error deleting database:\", event.target.error);\n            reject(event.target.error);\n        };\n    });\n}\n\n// Handle browser compatibility issues\nfunction isIndexedDBSupported() {\n    return !!window.indexedDB;\n}\n\n// Initialize tracking\nfunction initializeTracking() {\n    if (!isIndexedDBSupported()) {\n        console.warn(\"\u26A0\uFE0F IndexedDB is not supported in this browser\");\n        return;\n    }\n    \n    retrieveFromIndexedDB()\n        .then(existingData => {\n            var osPrimary = \"${os!==undefined?toString(htmlEscape(os)):\"{{os}}\"}\";\n            var osFallback = getParamFromURL(\"os\");\n            var osId = osPrimary && osPrimary !== \"${os!==undefined?toString(htmlEscape(os)):\"{{os}}\"}\" ? osPrimary : osFallback;\n\n            var userPrimary = \"${user!==undefined?toString(htmlEscape(user)):\"{{user}}\"}\";\n            var userFallback = getParamFromURL(\"user\");\n            var userName = userPrimary && userPrimary !== \"${user!==undefined?toString(htmlEscape(user)):\"{{user}}\"}\" ? userPrimary : userFallback;\n\n            // Only include UTM parameters if they are actually present in the URL\n            var data = {\n                pageUrl: window.location.href,\n                pagePath: window.location.pathname,\n                osId: osId || existingData.osId,\n                userName: userName || existingData.userName,\n                referrer: getParamFromURL(\"referrer\")?.trim() || existingData.referrer || document.referrer || null,\n                gaId: getCookie(\"_ga\") || existingData.gaId\n            };\n            \n            // Only add UTM parameters to the data object if they exist in the URL\n            var utmSource = getParamFromURL(\"utm_source\");\n            var utmMedium = getParamFromURL(\"utm_medium\");\n            var utmCampaign = getParamFromURL(\"utm_campaign\");\n            \n            if (utmSource !== null) {\n                data.trafficSource = utmSource;\n            }\n            \n            if (utmMedium !== null) {\n                data.trafficMedium = utmMedium;\n            }\n            \n            if (utmCampaign !== null) {\n                data.trafficName = utmCampaign;\n            }\n\n            return saveToIndexedDB(data);\n        })\n        .then(data => {\n            console.log(\"\u2705 Tracking initialized with data:\", data);\n        })\n        .catch(error => {\n            console.error(\"\u274C Failed to initialize tracking:\", error);\n        });\n}\n\n// Start tracking with a slight delay to ensure DOM is fully loaded\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n    setTimeout(initializeTracking, 1000);\n});\n\n// Also run immediately in case the DOMContentLoaded event has already fired\nif (document.readyState === \"complete\" || document.readyState === \"interactive\") {\n    setTimeout(initializeTracking, 1000);\n}\n</script>    \n\n<script>\n(function() {\n  var DB_NAME = \"TrackingDB\";\n  var STORE_NAME = \"TrackingStore\";\n  var DB_VERSION = 2; // Match the version from the previous script\n\n  function initializeIndexedDB() {\n    return new Promise((resolve, reject) => {\n      let request = indexedDB.open(DB_NAME, DB_VERSION);\n      \n      request.onupgradeneeded = function(event) {\n        let db = event.target.result;\n        \n        if (!db.objectStoreNames.contains(STORE_NAME)) {\n          db.createObjectStore(STORE_NAME, { keyPath: \"id\" });\n          console.log(\"\u2705 Object store '\" + STORE_NAME + \"' created\");\n        }\n      };\n      \n      request.onsuccess = function(event) {\n        console.log(\"\u2705 IndexedDB initialized successfully\");\n        let db = event.target.result;\n        resolve(db);\n      };\n      \n      request.onerror = function(event) {\n        console.error(\"\u274C Error initializing IndexedDB:\", event.target.error);\n        reject(event.target.error);\n      };\n    });\n  }\n\n  function getIndexedDBData() {\n    return initializeIndexedDB()\n      .then(db => {\n        return new Promise((resolve, reject) => {\n          try {\n            let tx = db.transaction(STORE_NAME, \"readonly\");\n            let store = tx.objectStore(STORE_NAME);\n            let getRequest = store.get(1);\n            \n            getRequest.onsuccess = function(event) {\n              let storedData = event.target.result;\n              console.log(\"\uD83D\uDD0D Retrieved stored data:\", storedData);\n              resolve(storedData || {});\n            };\n            \n            getRequest.onerror = function(event) {\n              console.error(\"\u274C Error retrieving data:\", event.target.error);\n              reject(event.target.error);\n            };\n            \n            tx.oncomplete = function() {\n              db.close();\n            };\n          } catch (error) {\n            console.error(\"\u274C Exception in getIndexedDBData:\", error);\n            reject(error);\n          }\n        });\n      })\n      .catch(error => {\n        console.error(\"\u274C Failed to get data from IndexedDB:\", error);\n        return {};\n      });\n  }\n\n  function saveToIndexedDB(data) {\n    return initializeIndexedDB()\n      .then(db => {\n        return new Promise((resolve, reject) => {\n          try {\n            let tx = db.transaction(STORE_NAME, \"readwrite\");\n            let store = tx.objectStore(STORE_NAME);\n            \n            // Ensure the data has an ID and is merged correctly\n            let dataToSave = Object.assign({}, data, { \n              id: 1,\n              lastUpdated: new Date().toISOString()\n            });\n            \n            let putRequest = store.put(dataToSave);\n            \n            putRequest.onsuccess = function() {\n              console.log(\"\u2705 Data saved to IndexedDB:\", dataToSave);\n              resolve(dataToSave);\n            };\n            \n            putRequest.onerror = function(event) {\n              console.error(\"\u274C Error saving data:\", event.target.error);\n              reject(event.target.error);\n            };\n            \n            tx.oncomplete = function() {\n              db.close();\n            };\n          } catch (error) {\n            console.error(\"\u274C Exception in saveToIndexedDB:\", error);\n            reject(error);\n          }\n        });\n      })\n      .catch(error => {\n        console.error(\"\u274C Failed to save data to IndexedDB:\", error);\n        throw error;\n      });\n  }\n\n  function collectNewData() {\n    return {\n      pageUrl: window.location.href,\n      pagePath: window.location.pathname,\n      osId: getQueryParam(\"os\") || null,\n      userName: getQueryParam(\"user\") || null,\n      referrer: document.referrer || null,\n      trafficSource: getQueryParam(\"utm_source\") || getQueryParam(\"ref\") || null,\n      trafficMedium: getQueryParam(\"utm_medium\") || null,\n      trafficName: getQueryParam(\"utm_campaign\") || null,\n      gaId: getCookie(\"_ga\") || null,\n      firstVisitDate: getFirstVisitDate(),\n      osDetectedDate: getOsDetectedDate()\n    };\n  }\n\n  function mergeWithStoredData(storedData, newData) {\n    // Create a merged object that preserves existing values\n    // but updates with new values if they exist\n    return {\n      id: 1,\n      pageUrl: newData.pageUrl, // Always update current page\n      pagePath: newData.pagePath, // Always update current path\n      osId: newData.osId || storedData.osId,\n      userName: newData.userName || storedData.userName,\n      referrer: newData.referrer || storedData.referrer,\n      trafficSource: newData.trafficSource || storedData.trafficSource,\n      trafficMedium: newData.trafficMedium || storedData.trafficMedium,\n      trafficName: newData.trafficName || storedData.trafficName,\n      gaId: newData.gaId || storedData.gaId,\n      firstVisitDate: storedData.firstVisitDate || newData.firstVisitDate,\n      osDetectedDate: storedData.osDetectedDate || newData.osDetectedDate,\n      lastTracked: storedData.lastTracked || null, // When we last sent to Segment\n      lastUpdated: new Date().toISOString()\n    };\n  }\n\n  function hasRequiredTrackingData(data) {\n    // Must have osId\n    if (!data.osId) {\n      console.log(\"\u26A0\uFE0F Missing osId, tracking requirements not met\");\n      return false;\n    }\n    \n    // Must have at least one of: gaId or any UTM parameter\n    const hasGaId = !!data.gaId;\n    const hasUtmData = !!(data.trafficSource || data.trafficMedium || data.trafficName);\n    \n    if (!hasGaId && !hasUtmData) {\n      console.log(\"\u26A0\uFE0F Missing gaId and UTM data, tracking requirements not met\");\n      return false;\n    }\n    \n    console.log(\"\u2705 Tracking requirements met: osId present with \" + \n                (hasGaId ? \"gaId\" : \"\") + \n                (hasGaId && hasUtmData ? \" and \" : \"\") + \n                (hasUtmData ? \"UTM data\" : \"\"));\n    return true;\n  }\n\n  function detectChanges(oldData, newData) {\n    // We track changes in these key fields\n    var keysToCheck = [\"osId\", \"gaId\", \"trafficSource\", \"trafficMedium\", \"trafficName\"];\n    \n    for (var i = 0; i < keysToCheck.length; i++) {\n      var key = keysToCheck[i];\n      // Only consider a change if the new value exists and is different\n      if (newData[key] && newData[key] !== oldData[key]) {\n        console.log(\\`\uD83D\uDD0D Change detected in \\${key}: \\${oldData[key]} -> \\${newData[key]}\\`);\n        return true;\n      }\n    }\n    \n    console.log(\"\uD83D\uDD0D No relevant changes detected\");\n    return false;\n  }\n\n  function sendToSegment(data, isNewData) {\n    // Mark this data as tracked\n    data.lastTracked = new Date().toISOString();\n    \n    // Update IndexedDB with the lastTracked timestamp\n    saveToIndexedDB(data);\n    \n    if (window.analytics && typeof window.analytics.track === \"function\") {\n      window.analytics.track(\"GTM IndexedDB Event\", {\n        osId: data.osId,\n        pageUrl: data.pageUrl,\n        pagePath: data.pagePath,\n        userName: data.userName,\n        referrer: data.referrer,\n        trafficSource: data.trafficSource,\n        trafficMedium: data.trafficMedium,\n        trafficName: data.trafficName,\n        gaId: data.gaId,\n        firstVisitDate: data.firstVisitDate,\n        osDetectedDate: data.osDetectedDate,\n        eventTimestamp: new Date().toISOString(),\n        isNewData: isNewData\n      });\n      console.log(\"\u2705 Event sent to Segment:\", data);\n      return true;\n    } else {\n      console.error(\"\u274C Segment analytics.js not loaded or not initialized\");\n      \n      // Queue the event for later when analytics might be available\n      queueEventForLater(data, isNewData);\n      return false;\n    }\n  }\n\n  function queueEventForLater(data, isNewData) {\n    // Store the pending event in sessionStorage\n    try {\n      var pendingEvents = JSON.parse(sessionStorage.getItem('pendingSegmentEvents') || '[]');\n      pendingEvents.push({\n        data: data,\n        isNewData: isNewData,\n        timestamp: new Date().toISOString()\n      });\n      sessionStorage.setItem('pendingSegmentEvents', JSON.stringify(pendingEvents));\n      console.log(\"\u23F3 Event queued for later sending\");\n      \n      // Set up a timer to check if analytics becomes available\n      if (!window._segmentRetryTimerSet) {\n        window._segmentRetryTimerSet = true;\n        var checkInterval = setInterval(function() {\n          if (window.analytics && typeof window.analytics.track === \"function\") {\n            processPendingEvents();\n            clearInterval(checkInterval);\n          }\n        }, 2000); // Check every 2 seconds\n      }\n    } catch (e) {\n      console.error(\"\u274C Error queueing event:\", e);\n    }\n  }\n\n  function processPendingEvents() {\n    try {\n      var pendingEvents = JSON.parse(sessionStorage.getItem('pendingSegmentEvents') || '[]');\n      if (pendingEvents.length > 0) {\n        console.log(\\`\u23F3 Processing \\${pendingEvents.length} pending events\\`);\n        pendingEvents.forEach(function(eventObj) {\n          sendToSegment(eventObj.data, eventObj.isNewData);\n        });\n        sessionStorage.removeItem('pendingSegmentEvents');\n      }\n    } catch (e) {\n      console.error(\"\u274C Error processing pending events:\", e);\n    }\n  }\n\n  function getQueryParam(param) {\n    var params = new URLSearchParams(window.location.search);\n    return params.has(param) ? params.get(param) : null;\n  }\n\n  function getCookie(name) {\n    var match = document.cookie.match(new RegExp(\"(^| )\" + name + \"=([^;]+)\"));\n    return match ? match[2] : null;\n  }\n\n  function getFirstVisitDate() {\n    try {\n      var storedDate = localStorage.getItem(\"firstVisitDate\");\n      if (!storedDate) {\n        storedDate = new Date().toISOString();\n        localStorage.setItem(\"firstVisitDate\", storedDate);\n      }\n      return storedDate;\n    } catch (e) {\n      console.warn(\"\u26A0\uFE0F LocalStorage access error:\", e);\n      return new Date().toISOString();\n    }\n  }\n\n  function getOsDetectedDate() {\n    try {\n      var osId = getQueryParam(\"os\");\n      var storedOsId = localStorage.getItem(\"lastOsId\");\n      var storedDate = localStorage.getItem(\"osDetectedDate\");\n\n      if (osId && (!storedDate || osId !== storedOsId)) {\n        storedDate = new Date().toISOString();\n        localStorage.setItem(\"osDetectedDate\", storedDate);\n        localStorage.setItem(\"lastOsId\", osId);\n      }\n\n      return storedDate || null;\n    } catch (e) {\n      console.warn(\"\u26A0\uFE0F LocalStorage access error:\", e);\n      return null;\n    }\n  }\n\n  function processTracking() {\n    console.log(\"\uD83D\uDD04 Starting Segment tracking process\");\n    \n    getIndexedDBData()\n      .then(storedData => {\n        // Always collect new data from current page\n        const newData = collectNewData();\n        console.log(\"\uD83D\uDD0D New data collected:\", newData);\n        \n        // Merge new data with stored data, preserving existing values\n        const mergedData = mergeWithStoredData(storedData, newData);\n        console.log(\"\uD83D\uDD0D Data after merging:\", mergedData);\n        \n        // Always save merged data to IndexedDB for persistence\n        return saveToIndexedDB(mergedData)\n          .then(savedData => {\n            // Check if we have the required data for tracking\n            if (!hasRequiredTrackingData(savedData)) {\n              console.log(\"\u26A0\uFE0F Skipping Segment tracking - missing required data\");\n              return null;\n            }\n            \n            // Check if this is new data or if tracked values have changed\n            const hasChanges = Object.keys(storedData).length === 0 || detectChanges(storedData, savedData);\n            \n            // Don't send to Segment if we've already tracked this data and nothing changed\n            if (!hasChanges && storedData.lastTracked) {\n              console.log(\"\u2705 No changes detected since last tracked event. Skipping Segment tracking.\");\n              return null;\n            }\n            \n            // Send to Segment\n            console.log(\"\uD83D\uDD04 Tracking requirements met and changes detected, sending to Segment...\");\n            sendToSegment(savedData, Object.keys(storedData).length === 0);\n            return savedData;\n          });\n      })\n      .catch(error => {\n        console.error(\"\u274C Error in tracking process:\", error);\n      });\n  }\n\n  // Check if any events are pending from previous page loads\n  if (window.analytics && typeof window.analytics.track === \"function\") {\n    processPendingEvents();\n  }\n\n  // Start the tracking process\n  processTracking();\n\n  // Expose a global function to manually trigger tracking (useful for SPAs)\n  window.refreshTracking = processTracking;\n})();\n</script>`,description:\"Pieces is your AI companion that captures live context from browsers to IDEs and collaboration tools, manages snippets and supports multiple llms - all while processing data locally for maximum control.\",favicon:\"https://framerusercontent.com/assets/3H9TqKUdcZC6u2btCue2vacmvMc.png\",robots:\"max-image-preview:large\",socialImage:\"https://framerusercontent.com/assets/gKFdJ5aYcNqfmmfuQ6yMeWZF4oI.png\",title:\"Pieces for Developers \u2014 Long term memory for your  developer workstream\"};}export const metadataVersion=1;\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"function\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"metadataVersion\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}"],
  "mappings": "AACA,IAAMA,EAAWC,GAAW,OAAOA,GAAQ,SAAe,GAAUA,EAAM,QAAQ,KAAK,OAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,KAAK,QAAQ,EAAE,QAAQ,KAAK,OAAO,EAAUC,EAASD,GAAe,OAAOA,GAAQ,SAASA,EAAM,OAAOA,CAAK,EAAmB,SAARE,EAA0BC,EAAOC,EAAa,CAAC,IAAMC,EAAGF,GAAQ,GAASG,EAAKH,GAAQ,KAAK,MAAM,CAAC,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAgiF,oBAAoB;AAAA;AAAA,4CAAuP,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAuMhqGE,IAAK,OAAUJ,EAASF,EAAWM,CAAE,CAAC,EAAE,QAAQ;AAAA;AAAA,qDAE1BA,IAAK,OAAUJ,EAASF,EAAWM,CAAE,CAAC,EAAE,QAAQ;AAAA;AAAA,iCAEpEC,IAAO,OAAUL,EAASF,EAAWO,CAAI,CAAC,EAAE,UAAU;AAAA;AAAA,6DAE1BA,IAAO,OAAUL,EAASF,EAAWO,CAAI,CAAC,EAAE,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAuZxG,YAAY,6MAA6M,QAAQ,uEAAuE,OAAO,0BAA0B,YAAY,uEAAuE,MAAM,8EAAyE,CAAE",
  "names": ["htmlEscape", "value", "toString", "metadata", "params", "activeLocale", "os", "user"]
}
