{"version":3,"sources":["jsdelivr-header.js","/gh/trysurface/scripts@0.1.45/surface_tracking.js"],"names":[],"mappings":"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","file":"/gh/trysurface/scripts@0.1.45/surface_tracking.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /gh/trysurface/scripts@0.1.45/surface_tracking.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","window.SurfaceTracking = (() => {\n  \"use strict\";\n\n  const SurfaceTracking = {};\n\n  const documentAlias = document;\n  const navigatorAlias = navigator;\n  const windowAlias = window;\n\n  let serverBaseUrl = \"https://app.withsurface.com/api/v1\";\n  const localUrl = localStorage.getItem(\"surfaceServerBaseURL\");\n  // to set the local url as the server url is exists in local storage\n  if (localUrl) {\n    serverBaseUrl = localUrl;\n  }\n\n  const surfaceScriptElement =\n    document.currentScript ||\n    document.querySelector('script[src*=\"surface_tracking.min.js\"]');\n\n  const environmentId = surfaceScriptElement.getAttribute(\"environmentid\");\n  const debugMode = window.location.search.includes(\"surfaceDebug=true\");\n  let userFingerprint = null;\n\n  const addEvent = (element, type, listener) => {\n    if (debugMode)\n      console.log(\"Adding event listener for\", type, \"on\", element);\n    if (typeof element.addEventListener !== \"undefined\")\n      element.addEventListener(type, listener, false);\n    else element.attachEvent(\"on\" + type, listener);\n  };\n\n  async function getHash(input) {\n    const encoder = new TextEncoder();\n    const data = encoder.encode(input);\n    const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n    const hashArray = Array.from(new Uint8Array(hashBuffer));\n    const hashHex = hashArray\n      .map((b) => b.toString(16).padStart(2, \"0\"))\n      .join(\"\");\n    return hashHex;\n  }\n\n  function isEmailInput(inputElement) {\n    if (!(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid HTML element provided.\");\n      return false;\n    }\n\n    const emailRegex = /email/i; // Case-insensitive regex for \"email\"\n\n    const emailValueRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/; // Matches typical email formats\n    const isEmailPlaceholder =\n      (inputElement.placeholder &&\n        emailValueRegex.test(inputElement.placeholder)) ||\n      emailRegex.test(inputElement.placeholder);\n    const hasEmailLabel = emailRegex.test(\n      document.querySelector(`label[for=\"${inputElement.id}\"]`)?.textContent\n    );\n\n    return (\n      inputElement.type === \"email\" ||\n      (inputElement.type === \"text\" && emailRegex.test(inputElement.name)) ||\n      emailRegex.test(inputElement.className) ||\n      hasEmailLabel ||\n      isEmailPlaceholder\n    );\n  }\n\n  function isPhoneInput(inputElement) {\n    if (!(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid HTML element provided.\");\n      return false;\n    }\n\n    const phoneRegex =\n      /^\\+?(?:\\s|-|\\()?[0-9]{1,4}(?:\\s|-|\\))?[0-9]{1,4}\\s?[0-9]{1,4}$/i;\n    const phoneTermRegex =\n      /phone|Tel|Telephone|telephone|cell|Cell|mobile|Mobile|call|Call/i;\n\n    const hasNameAtribute = phoneTermRegex.test(inputElement.name); // Check if pattern attribute includes terms\n    const hasClassNameAttribute = phoneTermRegex.test(inputElement.className);\n    const isPhonePlaceholder =\n      phoneTermRegex.test(inputElement.placeholder) ||\n      phoneRegex.test(inputElement.placeholder); // Check if placeholder includes 'phone'\n    const hasPhoneLabel = phoneTermRegex.test(\n      document.querySelector(`label[for=\"${inputElement.id}\"]`)?.textContent\n    );\n\n    return (\n      inputElement.type === \"tel\" ||\n      hasNameAtribute ||\n      hasClassNameAttribute ||\n      isPhonePlaceholder ||\n      hasPhoneLabel\n    );\n  }\n\n  function isFirstNameInput(inputElement) {\n    if (!inputElement || !(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid input element provided.\");\n      return false;\n    }\n\n    // Case-insensitive regex for common last name  terms\n    const firstNameRegex =\n      /first|Forename|given|Given|firstname|FirstName|name|Name|givenName|GivenName|forename|Forename/i;\n\n    // Check if the input element is of type \"text\" or \"search\"\n    const isTextInput =\n      inputElement.type === \"text\" || inputElement.type === \"search\";\n\n    // Check for additional conditions that may indicate a first name input\n    const hasNameAtribute = firstNameRegex.test(inputElement.name); // Check if pattern attribute includes 'name'\n    const hasClassNameAttribute = firstNameRegex.test(inputElement.className);\n    const hasNamePlaceholder = firstNameRegex.test(inputElement.placeholder); // Check if placeholder includes 'first name'\n    const hasNameLabel =\n      !!document\n        .querySelector(`label[for=\"${inputElement.id}\"]`)\n        ?.textContent.toLowerCase()\n        .includes(\"name\") ||\n      firstNameRegex.test(\n        document.querySelector(`label[for=\"${inputElement.id}\"]`)?.textContent\n      ); // Check if associated label includes 'first name'\n\n    // Combine conditions\n    return (\n      isTextInput &&\n      (hasNameAtribute ||\n        hasClassNameAttribute ||\n        hasNamePlaceholder ||\n        hasNameLabel)\n    );\n  }\n\n  function isLastNameInput(inputElement) {\n    if (!inputElement || !(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid input element provided.\");\n      return false;\n    }\n\n    // Case-insensitive regex for common last name  terms\n    const lastNameRegex =\n      /last|Surname|family|Family|lastname|Lastname|lname|l-name|LName|familyName|FamilyName|surname|Surname|familyName|FamilyName/i;\n\n    // Check if the input element is of type \"text\" or \"search\"\n    const isTextInput =\n      inputElement.type === \"text\" || inputElement.type === \"search\";\n\n    // Check for additional conditions that may indicate a last name input\n    const hasNameAttribute = lastNameRegex.test(inputElement.name);\n    const hasClassNameAttribute = lastNameRegex.test(inputElement.className);\n    const hasNamePlaceholder =\n      !!inputElement.placeholder?.toLowerCase().includes(\"last name\") ||\n      lastNameRegex.test(inputElement.placeholder); // Check if placeholder includes 'last name'\n    const hasNameLabel =\n      !!document\n        .querySelector(`label[for=\"${inputElement.id}\"]`)\n        ?.textContent.toLowerCase()\n        .includes(\"last name\") ||\n      lastNameRegex.test(\n        document.querySelector(`label[for=\"${inputElement.id}\"]`)?.textContent\n      ); // Check if associated label includes 'last name'\n\n    // Combine conditions\n    return (\n      isTextInput &&\n      (hasNameAttribute ||\n        hasClassNameAttribute ||\n        hasNamePlaceholder ||\n        hasNameLabel)\n    );\n  }\n\n  function isCompanyInput(inputElement) {\n    if (!(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid HTML element provided.\");\n      return false;\n    }\n\n    const companyRegex = /company|organization|business|firm|enterprise/i; // Case-insensitive regex for common company terms\n\n    const companyValueRegex =\n      /(Pvt\\s*Ltd|LLC|Inc|Corporation|Ltd|Limited|GmbH|Co|Partnership)$/i; // Matches typical company name formats\n    const isCompanyPlaceholder =\n      inputElement.placeholder &&\n      (companyValueRegex.test(inputElement.placeholder) ||\n        companyRegex.test(inputElement.placeholder));\n    const hasCompanyLabel = companyRegex.test(\n      document.querySelector(`label[for=\"${inputElement.id}\"]`)?.textContent\n    ); // Check if associated label includes 'company'\n    return (\n      inputElement.type === \"text\" &&\n      (companyRegex.test(inputElement.name) ||\n        companyRegex.test(inputElement.className) ||\n        hasCompanyLabel ||\n        isCompanyPlaceholder)\n    );\n  }\n\n  async function getBrowserFingerprint() {\n    if (userFingerprint != null) {\n      return userFingerprint;\n    }\n\n    let fingerprint = {};\n\n    // Device Type\n    fingerprint.deviceType = /Mobi|Android/i.test(navigator.userAgent)\n      ? \"Mobile\"\n      : \"Desktop\";\n\n    // Screen Properties\n    fingerprint.screen = {\n      width: screen.width,\n      height: screen.height,\n      colorDepth: screen.colorDepth,\n    };\n\n    // Browser, OS, and Version\n    fingerprint.userAgent = navigator.userAgent;\n    let userAgentData = navigator.userAgentData || {};\n    fingerprint.browser = userAgentData.brands ||\n      userAgentData.uaList || [{ brand: \"unknown\", version: \"unknown\" }];\n    fingerprint.os = userAgentData.platform || \"unknown\";\n\n    // Browser Language\n    fingerprint.language = navigator.language;\n\n    // Installed Plugins\n    if (navigator.plugins != null) {\n      fingerprint.plugins = Array.from(navigator.plugins).map(\n        (plugin) => plugin.name\n      );\n    }\n\n    // TODO: attach extensions data\n\n    // Time Zone\n    fingerprint.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n    fingerprint.environmentId = environmentId;\n\n    // Combine all fingerprint data into a single string\n    let fingerprintString = JSON.stringify(fingerprint);\n\n    // Generate a unique ID using a hash function\n    fingerprint.id = await getHash(fingerprintString);\n\n    // Store the result to make future function calls faster\n    userFingerprint = fingerprint;\n\n    return fingerprint;\n  }\n\n  async function callIdentifyApi() {\n    const browserFingerprint = await getBrowserFingerprint();\n    const url = `${serverBaseUrl}/lead/identify`; // Replace with your server endpoint\n\n    const { href, hostname, pathname, search } = window.location;\n    const payload = {\n      fingerprint: browserFingerprint.id,\n      environmentId,\n      source: \"htmlForm\",\n      sourceURL: href,\n      sourceURLDomain: hostname,\n      sourceURLPath: pathname,\n      sourceUrlSearchParams: search,\n    };\n\n    const res = await fetch(url, {\n      method: \"POST\",\n      body: JSON.stringify(payload),\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n    });\n    const result = await res?.json();\n    return result?.data?.data;\n  }\n\n  async function callCaptureApi({ attributes }) {\n    const browserFingerprint = await getBrowserFingerprint();\n    const url = `${serverBaseUrl}/lead/capture`;\n\n    const payload = {\n      fingerprint: browserFingerprint.id,\n      data: attributes,\n      sessionId: SurfaceTracking.sessionId,\n    };\n\n    const blob = new Blob([JSON.stringify(payload)], {\n      type: \"application/json\",\n    });\n\n    if (navigator.sendBeacon) {\n      navigator.sendBeacon(url, blob);\n    } else {\n      // Fallback to fetch if sendBeacon is not supported\n      await fetch(url, {\n        method: \"POST\",\n        body: JSON.stringify(payload),\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n      });\n    }\n  }\n\n  function extractInputValue(inputElement) {\n    if (!(inputElement instanceof HTMLElement)) {\n      console.error(\"Invalid HTML element provided.\");\n      return;\n    }\n\n    const inputType = inputElement.type;\n    let value;\n\n    switch (inputType) {\n      case \"checkbox\":\n        value = inputElement.checked;\n        break;\n      case \"radio\":\n        value = inputElement.checked ? inputElement.value : null;\n        break;\n      case \"select-one\":\n      case \"select-multiple\":\n        value = Array.from(inputElement.selectedOptions).map(\n          (option) => option.value\n        );\n        if (inputType === \"select-one\") {\n          value = value[0]; // For select-one, just take the first value\n        }\n        break;\n      case \"text\":\n      case \"password\":\n      case \"email\":\n      case \"number\":\n      case \"textarea\":\n      default:\n        value = inputElement.value;\n        break;\n    }\n\n    return {\n      name: inputElement.name,\n      value: value,\n    };\n  }\n\n  function calculateInputType(element) {\n    if (isEmailInput(element)) {\n      return \"email\";\n    }\n    if (isPhoneInput(element)) {\n      return \"phone\";\n    }\n    if (isCompanyInput(element)) {\n      return \"company\";\n    }\n    if (isLastNameInput(element)) {\n      return \"lastName\";\n    }\n    if (isFirstNameInput(element)) {\n      return \"firstName\";\n    }\n    return \"other\";\n  }\n\n  function isElementVisible(element) {\n    if (!element) return false;\n\n    function isVisible(el) {\n      const style = window.getComputedStyle(el);\n      return (\n        style.display !== \"none\" &&\n        style.visibility !== \"hidden\" &&\n        style.opacity !== \"0\"\n      );\n    }\n\n    function isWithinViewport(el) {\n      const rect = el.getBoundingClientRect();\n      return (\n        rect.top >= 0 &&\n        rect.left >= 0 &&\n        rect.bottom <=\n          (window.innerHeight || document.documentElement.clientHeight) &&\n        rect.right <=\n          (window.innerWidth || document.documentElement.clientWidth)\n      );\n    }\n\n    let currentElement = element;\n    while (currentElement) {\n      if (!isVisible(currentElement)) {\n        return false;\n      }\n      currentElement = currentElement.parentElement; // Move to the parent element\n    }\n\n    return isWithinViewport(element);\n  }\n\n  async function checkSubmitClickInForm(target) {\n    const clickedButton = target.closest(\"button\") || target.closest(\"a\");\n    if (!clickedButton) {\n      return;\n    }\n\n    // check if the element is an anchor tag disguised as a button, if its a normal anchor tag, then return\n    if (\n      clickedButton.nodeName === \"A\" &&\n      !clickedButton.className.includes(\"button\") &&\n      !clickedButton.className.includes(\"btn\")\n    ) {\n      return;\n    }\n\n    const form = target.closest(\"form\");\n    if (form) {\n      const elements = form.elements;\n      let isValid = true;\n\n      const formData = {};\n\n      const attributes = [];\n      let sourceFormId = \"Unknown form\";\n\n      if (form.id) {\n        sourceFormId = form.id;\n      } else if (form.className) {\n        sourceFormId = form.className;\n      }\n      // loop through all the inputs of the form and extract their content.\n      for (let i = 0; i < elements.length; i++) {\n        const element = elements[i];\n        if (!element || element.type === \"hidden\") continue;\n        const isInputVisible = isElementVisible(element);\n        const isInputInvalid =\n          isInputVisible && element.validity && !element.validity.valid;\n\n        // due to some reason nextiva tel input always returns invalid but site redirects to success page.\n        if (isInputInvalid && element.type !== \"tel\") {\n          isValid = false;\n        }\n\n        const inputData = extractInputValue(element);\n        if (inputData.value.toString() && inputData.name) {\n          const inputType = calculateInputType(element);\n\n          attributes.push({\n            type: inputType,\n            name: inputData.name,\n            value: inputData.value.toString(),\n            sourceFormId,\n          });\n\n          // it might cause duplicate entries, but if we prevent this then below case wont work\n          // ex: if two fields triggered phone input validation then only one of them will be sent to server\n          // due to above case didn't prevented duplicate values.\n          formData[inputData.name] = inputData.value;\n        }\n\n        if (isInputInvalid && debugMode) {\n          console.log(\"invalid input\", inputData, element.validity);\n        }\n      }\n\n      if (debugMode) {\n        console.table(formData);\n      }\n\n      // track submission if button is type submit or has submission classes\n      const hasSubmissionClasses = !!clickedButton.className.match(\n        /(cta |submit|submission|book\\-demo)/g\n      );\n      const hasSubmissionIds = !!clickedButton.id.match(\n        /(cta|submit|submission|book\\-demo|button)/g\n      );\n\n      if (\n        isValid &&\n        attributes.length > 0 &&\n        (clickedButton.type === \"submit\" ||\n          hasSubmissionClasses ||\n          hasSubmissionIds)\n      ) {\n        await callCaptureApi({ attributes });\n      }\n    }\n  }\n\n  async function handleOnClick(e) {\n    await checkSubmitClickInForm(e.target);\n  }\n\n  SurfaceTracking.init = async function (apiKey) {\n    addEvent(windowAlias, \"mousedown\", async (e) => handleOnClick(e));\n    const { sessionId } = await callIdentifyApi();\n    SurfaceTracking.sessionId = sessionId;\n  };\n\n  if (!environmentId) {\n    console.error(\"Please add a valid environmentid in surface script tag\");\n    return;\n  }\n\n  SurfaceTracking.init();\n  return SurfaceTracking;\n})();\n"]}