{
  "$schema": "https://savvytoolz.com/data/tool-data-processing.schema.json",
  "schemaVersion": "1.0.0",
  "documentType": "tool-data-processing-disclosure",
  "site": "https://savvytoolz.com",
  "canonicalHumanReadableUrl": "https://savvytoolz.com/en/methodology",
  "schemaUrl": "https://savvytoolz.com/data/tool-data-processing.schema.json",
  "lastSourceReview": "2026-07-17",
  "maintenance": {
    "owner": "SavvyToolz site operator",
    "reviewPolicy": "Review after changes to providers, network endpoints, analytics fields, browser storage, or tool processing behavior.",
    "versioningPolicy": "Use semantic versions: patch for clarifications, minor for backward-compatible fields, and major for incompatible schema changes."
  },
  "scope": "Current SavvyToolz client application source. This describes intended application behavior, not every behavior of the browser, operating system, extension, network, or external provider.",
  "importantQualification": "Browser-local describes where the primary tool transformation occurs. It does not mean that the page makes zero network requests. Ordinary requests can expose network metadata such as an IP address and user agent to the receiving provider.",
  "processingProfiles": {
    "browser-local": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": false,
      "description": "User-provided tool input is transformed in the browser. No tool-specific third-party processing API request was identified in the reviewed source.",
      "qualification": "Site-wide analytics and font requests can still occur on production pages. Browser extensions and the local device are outside SavvyToolz control."
    },
    "browser-local-with-local-persistence": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": false,
      "description": "User-provided input is processed in the browser and selected state is persisted in browser localStorage on the device.",
      "qualification": "Data remains until the app or browser clears it. Other people or software with access to the same browser profile may be able to read it."
    },
    "browser-local-with-shareable-url": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": false,
      "description": "The timer runs in the browser. When a shareable countdown is created, selected countdown settings are encoded in the page URL.",
      "qualification": "Anyone who receives the shared URL can read the values in it. The application analytics boundary collapses query strings and fragments before sending page metadata."
    },
    "browser-local-with-provider-reference-data": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": true,
      "description": "The calculation and entered amount remain in the browser, while a third party supplies reference data.",
      "providerRequestId": "exchange-rate-api"
    },
    "third-party-ip-lookup": {
      "primaryProcessingLocation": "third-party-data-source-and-user-browser",
      "toolSpecificThirdPartyNetworkRequest": true,
      "description": "The browser requests IP and approximate network/location data from ipapi.co, then renders the response locally.",
      "providerRequestId": "ipapi-co"
    },
    "browser-local-with-third-party-runtime-assets": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": true,
      "description": "Image inference and output encoding run in the browser. The library downloads its default ONNX model and WebAssembly runtime assets from a third-party static host.",
      "providerRequestId": "imgly-runtime-assets"
    },
    "browser-local-with-third-party-editor-runtime": {
      "primaryProcessingLocation": "user-browser",
      "toolSpecificThirdPartyNetworkRequest": true,
      "description": "Document parsing and rendering run in the browser. The editor wrapper downloads the Monaco editor runtime from a third-party static host under its default configuration.",
      "providerRequestId": "jsdelivr-monaco"
    }
  },
  "toolRoutes": [
    {
      "name": "Secure Password Generator",
      "routes": ["/en/password-generator"],
      "profile": "browser-local",
      "inputTypes": ["password length", "character-set options"],
      "notes": "Generated password characters are drawn with Web Crypto and are not intentionally included in external provider requests."
    },
    {
      "name": "QR Code Generator",
      "routes": ["/en/qr-code-generator"],
      "profile": "browser-local",
      "inputTypes": ["URL", "text", "Wi-Fi configuration", "style settings"]
    },
    {
      "name": "Percentage Calculator",
      "routes": ["/en/percentage-calculator"],
      "profile": "browser-local",
      "inputTypes": ["numbers", "percentage values"]
    },
    {
      "name": "Adult BMI Calculator",
      "routes": ["/en/bmi-calculator"],
      "profile": "browser-local",
      "inputTypes": ["height", "weight", "unit selection"],
      "notes": "BMI is an informational screening calculation, not a diagnosis."
    },
    {
      "name": "Random Spinner",
      "routes": ["/en/random-spinner"],
      "profile": "browser-local",
      "inputTypes": ["names or choices", "display settings", "optional imported file"]
    },
    {
      "name": "Barcode Generator",
      "routes": ["/en/barcode-generator"],
      "profile": "browser-local",
      "inputTypes": ["barcode content", "format", "display settings"]
    },
    {
      "name": "Word and Character Counter",
      "routes": ["/en/word-counter"],
      "profile": "browser-local",
      "inputTypes": ["text"]
    },
    {
      "name": "Countdown Timer",
      "routes": ["/en/countdown-timer"],
      "profile": "browser-local-with-shareable-url",
      "inputTypes": ["event name", "date", "time", "time zone", "theme", "timer duration"]
    },
    {
      "name": "Age Calculator",
      "routes": ["/en/age-calculator"],
      "profile": "browser-local",
      "inputTypes": ["birth date"]
    },
    {
      "name": "Image Compressor",
      "routes": ["/en/image-compressor"],
      "profile": "browser-local",
      "inputTypes": ["image file", "quality and format settings"]
    },
    {
      "name": "Online Color Picker",
      "routes": ["/en/color-picker", "/en/color-picker/*"],
      "profile": "browser-local",
      "inputTypes": ["color values", "optional image file"]
    },
    {
      "name": "JSON Formatter and Validator",
      "routes": ["/en/json-formatter"],
      "profile": "browser-local-with-third-party-editor-runtime",
      "inputTypes": ["JSON text"],
      "notes": "The entered JSON is not placed in the Monaco runtime asset requests."
    },
    {
      "name": "Tip Calculator",
      "routes": ["/en/tip-calculator"],
      "profile": "browser-local",
      "inputTypes": ["bill amount", "tip rate", "number of people"]
    },
    {
      "name": "AI Background Remover",
      "routes": ["/en/background-remover"],
      "profile": "browser-local-with-third-party-runtime-assets",
      "inputTypes": ["image file"],
      "notes": "The current application does not call a remote image-inference API. The ONNX model and WebAssembly runtime are fetched from staticimgly.com under the library default configuration."
    },
    {
      "name": "Lorem Ipsum Generator",
      "routes": ["/en/lorem-ipsum-generator"],
      "profile": "browser-local",
      "inputTypes": ["output length and type"]
    },
    {
      "name": "Case Converter",
      "routes": ["/en/case-converter"],
      "profile": "browser-local",
      "inputTypes": ["text", "case mode"]
    },
    {
      "name": "Unit Converter",
      "routes": ["/en/unit-converter", "/en/unit-converter/*"],
      "profile": "browser-local",
      "inputTypes": ["numeric value", "source unit", "destination unit"]
    },
    {
      "name": "Loan Calculator",
      "routes": ["/en/loan-calculator"],
      "profile": "browser-local",
      "inputTypes": ["principal", "interest rate", "term"],
      "notes": "Results are informational estimates and omit fees, taxes, insurance, and lender-specific rules."
    },
    {
      "name": "Base64 Encoder and Decoder",
      "routes": ["/en/base64-converter"],
      "profile": "browser-local",
      "inputTypes": ["text or Base64 string"]
    },
    {
      "name": "Pomodoro Timer",
      "routes": ["/en/pomodoro-timer"],
      "profile": "browser-local",
      "inputTypes": ["timer controls"],
      "browserPermissions": ["optional notification permission"]
    },
    {
      "name": "Currency Converter",
      "routes": ["/en/currency-converter"],
      "profile": "browser-local-with-provider-reference-data",
      "inputTypes": ["amount", "source currency", "destination currency"],
      "notes": "The provider request is a fixed USD reference-rate feed. The entered amount is not appended to that request."
    },
    {
      "name": "UUID v4 Generator",
      "routes": ["/en/uuid-generator"],
      "profile": "browser-local",
      "inputTypes": ["quantity", "format settings"]
    },
    {
      "name": "Regex Tester",
      "routes": ["/en/regex-tester"],
      "profile": "browser-local",
      "inputTypes": ["regular expression", "test text", "flags"]
    },
    {
      "name": "Text Diff Checker",
      "routes": ["/en/text-diff-checker"],
      "profile": "browser-local",
      "inputTypes": ["two text values", "comparison mode"]
    },
    {
      "name": "PDF to Image Converter",
      "routes": ["/en/pdf-to-image"],
      "profile": "browser-local",
      "inputTypes": ["PDF file", "scale", "output format"]
    },
    {
      "name": "What Is My IP Address",
      "routes": ["/en/what-is-my-ip-address"],
      "profile": "third-party-ip-lookup",
      "inputTypes": ["public network request"],
      "notes": "The provider can see the requesting public IP and returns approximate geolocation and network details."
    },
    {
      "name": "Hash Generator",
      "routes": ["/en/hash-generator"],
      "profile": "browser-local",
      "inputTypes": ["text", "hash algorithm"]
    },
    {
      "name": "Invoice Generator and Designer",
      "routes": ["/en/invoice-generator"],
      "profile": "browser-local-with-local-persistence",
      "inputTypes": ["invoice fields", "line items", "branding images", "design settings"],
      "localStorageKeys": ["invoice-design-studio-state"],
      "notes": "The page also loads Google Fonts as described in siteWideServices."
    },
    {
      "name": "Markdown Editor",
      "routes": ["/en/markdown-editor"],
      "profile": "browser-local-with-third-party-editor-runtime",
      "inputTypes": ["Markdown text"],
      "notes": "The entered Markdown is not placed in the Monaco runtime asset requests."
    },
    {
      "name": "Date Difference Calculator",
      "routes": ["/en/date-difference-calculator"],
      "profile": "browser-local",
      "inputTypes": ["start date", "end date", "inclusive-date option"]
    },
    {
      "name": "Unix Timestamp Converter",
      "routes": ["/en/unix-timestamp-converter"],
      "profile": "browser-local",
      "inputTypes": ["timestamp", "date and time"]
    },
    {
      "name": "World Clock",
      "routes": ["/en/world-clock"],
      "profile": "browser-local-with-local-persistence",
      "inputTypes": ["selected cities"],
      "localStorageKeys": ["worldClock_cities"]
    },
    {
      "name": "Days Until Calculator",
      "routes": ["/en/days-until-calculator"],
      "profile": "browser-local-with-local-persistence",
      "inputTypes": ["event name", "target date", "business-day option"],
      "localStorageKeys": ["daysUntil_targetDate", "daysUntil_eventName", "daysUntil_businessDaysOnly"]
    },
    {
      "name": "Time Duration Calculator",
      "routes": ["/en/time-duration-calculator", "/en/time-between-two-dates"],
      "profile": "browser-local",
      "inputTypes": ["durations", "dates", "times"]
    },
    {
      "name": "JWT Encoder and Decoder",
      "routes": ["/en/jwt-encoder-decoder"],
      "profile": "browser-local",
      "inputTypes": ["JWT header", "JWT payload", "token", "optional HMAC secret"],
      "notes": "JWT encoding is not encryption. Avoid using production secrets on shared devices or in browsers with untrusted extensions."
    },
    {
      "name": "Time Zone Converter",
      "routes": ["/en/time-zone-converter", "/en/converter/*"],
      "profile": "browser-local",
      "inputTypes": ["source city", "destination city", "date and time"],
      "notes": "Location records are bundled into the deployed application. City and regional offsets are calculated for the selected date with the browser Intl implementation using IANA time-zone identifiers. Explicit standard/daylight abbreviations are labeled fixed-offset choices."
    }
  ],
  "providerRequests": [
    {
      "id": "exchange-rate-api",
      "provider": "ExchangeRate-API",
      "endpoint": "https://api.exchangerate-api.com/v4/latest/USD",
      "trigger": "Currency Converter page load",
      "purpose": "Retrieve a USD-based public reference-rate table and provider timestamp.",
      "applicationFieldsSent": [],
      "applicationFieldsNotSent": ["entered amount", "selected source currency", "selected destination currency"],
      "ordinaryNetworkMetadata": "The provider can receive metadata inherent to the HTTPS request, including the requesting IP address and user agent.",
      "documentation": "https://www.exchangerate-api.com/docs/free"
    },
    {
      "id": "ipapi-co",
      "provider": "ipapi.co",
      "endpoint": "https://ipapi.co/json/",
      "trigger": "IP Lookup page load",
      "purpose": "Return the requesting public IP and approximate location, timezone, ISP, and network data.",
      "applicationFieldsSent": [],
      "ordinaryNetworkMetadata": "The public IP is necessarily visible to the provider as part of the request and is the subject of the lookup.",
      "documentation": "https://ipapi.co/api/",
      "privacyPolicy": "https://ipapi.co/privacy/"
    },
    {
      "id": "imgly-runtime-assets",
      "provider": "IMG.LY",
      "endpointPattern": "https://staticimgly.com/@imgly/background-removal-data/{package-version}/dist/",
      "trigger": "First use of the Background Remover, subject to browser cache",
      "purpose": "Download ONNX model metadata/model chunks and WebAssembly runtime assets used for in-browser inference.",
      "applicationFieldsSent": ["static asset paths required by the library"],
      "applicationFieldsNotSent": ["uploaded image contents"],
      "ordinaryNetworkMetadata": "The provider can receive metadata inherent to the HTTPS asset requests, including the requesting IP address and user agent.",
      "documentation": "https://github.com/imgly/background-removal-js"
    },
    {
      "id": "jsdelivr-monaco",
      "provider": "jsDelivr",
      "endpointPattern": "https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs/",
      "trigger": "First load of the JSON Formatter or Markdown Editor, subject to browser cache",
      "purpose": "Download the Monaco code-editor runtime used by the in-browser editor controls.",
      "applicationFieldsSent": [
        "static Monaco runtime asset paths"
      ],
      "applicationFieldsNotSent": [
        "entered JSON text",
        "entered Markdown text"
      ],
      "ordinaryNetworkMetadata": "The provider can receive metadata inherent to the HTTPS asset requests, including the requesting IP address and user agent.",
      "documentation": "https://github.com/suren-atoyan/monaco-react#loader-config",
      "privacyPolicy": "https://www.jsdelivr.com/terms/privacy-policy-jsdelivr-net"
    }
  ],
  "siteWideServices": [
    {
      "id": "google-analytics-4",
      "provider": "Google",
      "service": "Google Analytics 4",
      "productionOnly": true,
      "measurementId": "G-PHGRH17S09",
      "endpoints": ["https://www.googletagmanager.com/gtag/js"],
      "purpose": "Aggregate page and tool-usage measurement.",
      "explicitEventFieldsAllowlist": [
        "stable page path and page location",
        "coarse page title derived from tool name or stable path",
        "tool_name",
        "action",
        "mode",
        "from_unit",
        "to_unit",
        "format",
        "algorithm",
        "category",
        "file_type",
        "session",
        "calculator_type"
      ],
      "explicitlySuppressedOrDiscarded": [
        "query strings",
        "URL fragments",
        "page referrer",
        "dynamic document title",
        "arbitrary strings not in an application allowlist",
        "numeric tool inputs",
        "file contents",
        "entered text"
      ],
      "configuration": {
        "send_page_view": false,
        "allow_google_signals": false,
        "allow_ad_personalization_signals": false
      },
      "qualification": "Google can still receive metadata inherent to its script and event requests under Google's policies. This disclosure does not claim that Analytics traffic is anonymous.",
      "privacyInformation": "https://support.google.com/analytics/answer/11593727"
    },
    {
      "id": "google-fonts",
      "provider": "Google",
      "service": "Google Fonts",
      "endpoints": ["https://fonts.googleapis.com", "https://fonts.gstatic.com"],
      "purpose": "Load interface fonts and Invoice Designer font choices.",
      "applicationFieldsSent": ["font family, weight, and display parameters in the stylesheet URL"],
      "applicationFieldsNotSent": ["tool input", "file contents"],
      "ordinaryNetworkMetadata": "Google can receive metadata inherent to stylesheet and font-file requests, including the requesting IP address and user agent.",
      "privacyInformation": "https://developers.google.com/fonts/faq/privacy"
    }
  ],
  "browserStorage": [
    {
      "scope": "site-wide",
      "key": "timezone-app-theme",
      "purpose": "Theme preference",
      "mechanism": "localStorage"
    },
    {
      "scope": "site-wide",
      "key": "i18nextLng",
      "purpose": "Language preference",
      "mechanism": "localStorage"
    },
    {
      "scope": "homepage",
      "key": "savvytoolz-pinned-tools",
      "purpose": "Pinned tool routes",
      "mechanism": "localStorage"
    },
    {
      "scope": "invoice-generator",
      "key": "invoice-design-studio-state",
      "purpose": "Invoice draft and design state",
      "mechanism": "localStorage"
    },
    {
      "scope": "world-clock",
      "key": "worldClock_cities",
      "purpose": "Selected cities",
      "mechanism": "localStorage"
    },
    {
      "scope": "days-until-calculator",
      "keys": ["daysUntil_targetDate", "daysUntil_eventName", "daysUntil_businessDaysOnly"],
      "purpose": "Target date, event label, and business-day option",
      "mechanism": "localStorage"
    }
  ],
  "accuracyLimitations": [
    "JavaScript uses binary floating-point numbers; displayed results can be rounded and tiny internal representation differences can occur.",
    "Currency rates are informational reference data and can differ from executable rates after spreads, fees, taxes, or provider timing.",
    "IP geolocation is approximate and can reflect a provider, VPN, proxy, or network gateway rather than a precise device location.",
    "Browser time-zone data can lag newly announced government changes, and repeated or nonexistent daylight-saving wall times can be ambiguous.",
    "BMI is a screening calculation and is not medical advice or a diagnosis.",
    "Password strength labels are heuristics and do not guarantee resistance to every attack or breach.",
    "QR codes, barcodes, PDFs, compressed images, and background masks should be tested in the downstream scanner, printer, browser, or production workflow."
  ]
}
