From 2b881a3533c36b2c8a7551a29bbcd6000cee7b17 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Thu, 9 Jan 2025 18:27:15 +0900 Subject: [PATCH 01/16] add basic playwire integration --- src/lib/components/DrawerMenu.svelte | 3 +- src/lib/components/TrackingRampSetup.svelte | 70 ++++++ src/playwire.d.ts | 20 ++ src/routes/+layout.svelte | 3 + src/routes/privacy/+page.svelte | 224 ++++++++++++++++++++ 5 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 src/lib/components/TrackingRampSetup.svelte create mode 100644 src/playwire.d.ts diff --git a/src/lib/components/DrawerMenu.svelte b/src/lib/components/DrawerMenu.svelte index 4a274fc..cac20bf 100644 --- a/src/lib/components/DrawerMenu.svelte +++ b/src/lib/components/DrawerMenu.svelte @@ -92,10 +92,9 @@ const version = patch?.version;
  • - + { $t("menu-privacy") } - {$t("term-soon")}
  • diff --git a/src/lib/components/TrackingRampSetup.svelte b/src/lib/components/TrackingRampSetup.svelte new file mode 100644 index 0000000..5590452 --- /dev/null +++ b/src/lib/components/TrackingRampSetup.svelte @@ -0,0 +1,70 @@ + + + + {#if ga4MeasurementId} + + {/if} + diff --git a/src/playwire.d.ts b/src/playwire.d.ts new file mode 100644 index 0000000..4343aeb --- /dev/null +++ b/src/playwire.d.ts @@ -0,0 +1,20 @@ +interface PlaywireUnit { + type: string; + selectorId?: string; +} + +interface Window { + ramp: { + que: unknown[]; + passiveMode: boolean; + addUnits: (units: PlaywireUnit[]) => Promise; + displayUnits: () => void; + destroyUnits: (what: string) => Promise; + processPage: (path: string) => void; + showCmpModal: () => void; + }; + + _pwGA4PageviewId: string; + dataLayer: unknown[]; + gtag: (...args: unknown[]) => void; +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index ea3b721..a605de4 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -13,6 +13,7 @@ import { t } from "$lib/i18n.svelte"; import { crowdinLink } from "$lib/constants"; import { phalanxI18nData } from "$lib/data/phalanx-i18n"; import { phalanxPatch } from "$lib/data/phalanx-patch"; +import TrackingRampSetup from "$lib/components/TrackingRampSetup.svelte"; const { children } = $props(); @@ -48,6 +49,8 @@ theme.subscribe((theme) => { Dauntless Builder + +
    diff --git a/src/routes/privacy/+page.svelte b/src/routes/privacy/+page.svelte index 45e2fc1..9d023dc 100644 --- a/src/routes/privacy/+page.svelte +++ b/src/routes/privacy/+page.svelte @@ -2,4 +2,228 @@ import PageTitle from "$lib/components/PageTitle.svelte"; + + + +

    + At Dauntless Builder, accessible from https://dauntless-builder.com, one of our main priorities is the privacy + of our visitors. This Privacy Policy document contains types of information that is collected and recorded by + Dauntless Builder and how we use it. +

    + +

    + If you have additional questions or require more information about our Privacy Policy, do not hesitate to contact + us. +

    + +

    + This Privacy Policy applies only to our online activities and is valid for visitors to our website with regards to + the information that they shared and/or collect in Dauntless Builder. This policy is not applicable to any + information collected offline or via channels other than this website. +

    + +

    Consent

    + +

    By using our website, you hereby consent to our Privacy Policy and agree to its terms.

    + +

    Information we collect

    + +

    + The personal information that you are asked to provide, and the reasons why you are asked to provide it, will be + made clear to you at the point we ask you to provide your personal information. +

    +

    + If you contact us directly, we may receive additional information about you such as your name, email address, phone + number, the contents of the message and/or attachments you may send us, and any other information you may choose to + provide. +

    +

    + When you register for an Account, we may ask for your contact information, including items such as name, company + name, address, email address, and telephone number. +

    + +

    How we use your information

    + +

    We use the information we collect in various ways, including to:

    + +
      +
    • Provide, operate, and maintain our website
    • +
    • Improve, personalize, and expand our website
    • +
    • Understand and analyze how you use our website
    • +
    • Develop new products, services, features, and functionality
    • +
    • + Communicate with you, either directly or through one of our partners, including for customer service, to provide + you with updates and other information relating to the website, and for marketing and promotional purposes +
    • +
    • Send you emails
    • +
    • Find and prevent fraud
    • +
    + +

    Log Files

    + +

    + Dauntless Builder follows a standard procedure of using log files. These files log visitors when they visit + websites. All hosting companies do this and a part of hosting services' analytics. The information collected by log + files include internet protocol (IP) addresses, browser type, Internet Service Provider (ISP), date and time stamp, + referring/exit pages, and possibly the number of clicks. These are not linked to any information that is personally + identifiable. The purpose of the information is for analyzing trends, administering the site, tracking users' + movement on the website, and gathering demographic information. +

    + +

    Cookies and Web Beacons

    + +

    + Like any other website, Dauntless Builder uses "cookies". These cookies are used to store information including + visitors' preferences, and the pages on the website that the visitor accessed or visited. The information is used to + optimize the users' experience by customizing our web page content based on visitors' browser type and/or other + information. +

    + +

    Our Advertising Partners

    + +

    + Some of advertisers on our site may use cookies and web beacons. Our advertising partners are listed below. Each of + our advertising partners has their own Privacy Policy for their policies on user data. For easier access, we + hyperlinked to their Privacy Policies below. +

    + +

    Google

    + +https://policies.google.com/technologies/ads + +

    Playwire LLC

    + +

    + All or partial advertising on this Website or App is managed by Playwire LLC. If Playwire publisher advertising + services are used, Playwire LLC may collect and use certain aggregated and anonymized data for advertising purposes. + To learn more about the types of data collected, how data is used and your choices as a user, please visit + https://www.playwire.com/privacy-policy. +

    +

    + For EU Users only: If you are located in countries that are part of the European Economic Area, in + the United Kingdom or Switzerland, and publisher advertising services are being provided by Playwire LLC, you were + presented with messaging from our Consent Management Platform (CMP) around your privacy choices as a user in regards + to digital advertising, applicable vendors, cookie usage and more. If you’d like to revisit the choices you have + made previously on this Website or App, please + window.ramp.showCmpModal()} + href="#clickme" + > + click here + . +

    + +

    Advertising Partners Privacy Policies

    + +

    You may consult this list to find the Privacy Policy for each of the advertising partners of Dauntless Builder.

    + +

    + Third-party ad servers or ad networks uses technologies like cookies, JavaScript, or Web Beacons that are used in + their respective advertisements and links that appear on Dauntless Builder, which are sent directly to users' + browser. They automatically receive your IP address when this occurs. These technologies are used to measure the + effectiveness of their advertising campaigns and/or to personalize the advertising content that you see on websites + that you visit. +

    + +

    + Note that Dauntless Builder has no access to or control over these cookies that are used by third-party advertisers. +

    + +

    Third Party Privacy Policies

    + +

    + Dauntless Builder's Privacy Policy does not apply to other advertisers or websites. Thus, we are advising you to + consult the respective Privacy Policies of these third-party ad servers for more detailed information. It may + include their practices and instructions about how to opt-out of certain options. +

    + +

    + You can choose to disable cookies through your individual browser options. To know more detailed information about + cookie management with specific web browsers, it can be found at the browsers' respective websites. +

    + +

    CCPA Privacy Rights (Do Not Sell My Personal Information)

    + +

    Under the CCPA, among other rights, California consumers have the right to:

    +

    + Request that a business that collects a consumer's personal data disclose the categories and specific pieces of + personal data that a business has collected about consumers. +

    +

    Request that a business delete any personal data about the consumer that a business has collected.

    +

    Request that a business that sells a consumer's personal data, not sell the consumer's personal data.

    +

    + If you make a request, we have one month to respond to you. If you would like to exercise any of these rights, + please contact us. +

    + +

    GDPR Data Protection Rights

    + +

    + We would like to make sure you are fully aware of all of your data protection rights. Every user is entitled to the + following: +

    +

    + The right to access – You have the right to request copies of your personal data. We may charge you a small fee for + this service. +

    +

    + The right to rectification – You have the right to request that we correct any information you believe is + inaccurate. You also have the right to request that we complete the information you believe is incomplete. +

    +

    The right to erasure – You have the right to request that we erase your personal data, under certain conditions.

    +

    + The right to restrict processing – You have the right to request that we restrict the processing of your personal + data, under certain conditions. +

    +

    + The right to object to processing – You have the right to object to our processing of your personal data, under + certain conditions. +

    +

    + The right to data portability – You have the right to request that we transfer the data that we have collected to + another organization, or directly to you, under certain conditions. +

    +

    + If you make a request, we have one month to respond to you. If you would like to exercise any of these rights, + please contact us. +

    + +

    Children's Information

    + +

    + Another part of our priority is adding protection for children while using the internet. We encourage parents and + guardians to observe, participate in, and/or monitor and guide their online activity. +

    + +

    + Dauntless Builder does not knowingly collect any Personal Identifiable Information from children under the age of + 13. If you think that your child provided this kind of information on our website, we strongly encourage you to + contact us immediately and we will do our best efforts to promptly remove such information from our records. +

    + +

    Changes to This Privacy Policy

    + +

    + We may update our Privacy Policy from time to time. Thus, we advise you to review this page periodically for any + changes. We will notify you of any changes by posting the new Privacy Policy on this page. These changes are + effective immediately, after they are posted on this page. +

    + +

    + Our Privacy Policy was created with the help of the + Privacy Policy Generator. +

    + +

    Contact Us

    + +

    If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us.

    From ec6d93792038b0f8d4b7a5001ce9f532601429db Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Thu, 9 Jan 2025 18:38:04 +0900 Subject: [PATCH 02/16] fix build --- src/lib/components/TrackingRampSetup.svelte | 13 +++++++------ src/lib/utils/env.ts | 12 ++++++++++++ src/routes/privacy/+page.svelte | 7 ++++--- 3 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 src/lib/utils/env.ts diff --git a/src/lib/components/TrackingRampSetup.svelte b/src/lib/components/TrackingRampSetup.svelte index 5590452..a886822 100644 --- a/src/lib/components/TrackingRampSetup.svelte +++ b/src/lib/components/TrackingRampSetup.svelte @@ -1,13 +1,14 @@ + + {/if} diff --git a/src/lib/utils/logger.ts b/src/lib/utils/logger.ts new file mode 100644 index 0000000..0989fc6 --- /dev/null +++ b/src/lib/utils/logger.ts @@ -0,0 +1,138 @@ +export enum LogLevel { + Trace, + Debug, + Info, + Warn, + Error, +} + +const MAX_LOCAL_STORAGE_LOGS = 500; +const LOCAL_STORAGE_KEY = "db:logs"; +const isDevMode = localStorage.getItem("devmode") === "true"; + +export class Logger { + private logLevel: LogLevel = isDevMode ? LogLevel.Debug : LogLevel.Info; + + private print(level: LogLevel, message: string, data: object = {}) { + const logLevelStr = Logger.prefixByLevel(level); + const logFunc = Logger.logFunctionByLevel(level); + + const logMessage = `[${logLevelStr}] ${message}`; + + Logger.storeLog(level, logMessage, data); + + if (this.logLevel > level) { + return; + } + + if (Object.keys(data).length > 0) { + logFunc(logMessage, data); + } else { + logFunc(logMessage); + } + } + + public setLogLevel(level: LogLevel) { + this.logLevel = level; + } + + public debug(message: string, data: object = {}) { + this.print(LogLevel.Debug, message, data); + } + + public info(message: string, data: object = {}) { + this.print(LogLevel.Info, message, data); + } + + public warn(message: string, data: object = {}) { + this.print(LogLevel.Warn, message, data); + } + + public error(message: string, data: object = {}) { + this.print(LogLevel.Error, message, data); + } + + public timer(label: string) { + if (this.logLevel > LogLevel.Debug) { + return; + } + + /*eslint-disable*/ + console.time(label); + /*eslint-enable*/ + } + + public timerEnd(label: string) { + if (this.logLevel > LogLevel.Debug) { + return; + } + + /*eslint-disable*/ + console.timeEnd(label); + /*eslint-enable*/ + } + + private static logFunctionByLevel(level: LogLevel): (...data: unknown[]) => void { + /*eslint-disable*/ + // we do not allow usage of console commands in the project except for this function + switch (level) { + case LogLevel.Trace: + return (...data: unknown[]) => { + console.groupCollapsed(...data); + console.trace(); + console.groupEnd(); + }; + case LogLevel.Debug: + case LogLevel.Info: + return console.info; + case LogLevel.Warn: + return console.warn; + case LogLevel.Error: + return console.error; + } + return console.log; + /*eslint-enable*/ + } + + private static prefixByLevel(level: LogLevel): string { + switch (level) { + case LogLevel.Trace: + return "TRACE"; + case LogLevel.Debug: + return "DEBUG"; + case LogLevel.Info: + return "INFO"; + case LogLevel.Warn: + return "WARN"; + case LogLevel.Error: + return "ERROR"; + } + return "???"; + } + + private static storeLog(level: LogLevel, message: string, data: object) { + const logs = Logger.data(); + + while (logs.length >= MAX_LOCAL_STORAGE_LOGS) { + logs.shift(); + } + + const timestamp = Date.now(); + + logs.push({ + data, + level, + message, + timestamp, + }); + + localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(logs)); + } + + public static data() { + return JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) ?? "[]"); + } +} + +const log = new Logger(); +export default log; From 7db3a1deb95509b73a1c77aba4cd6317346d8fa7 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Fri, 10 Jan 2025 11:10:09 +0900 Subject: [PATCH 09/16] fix logger using localStorage in non browser context --- src/lib/components/TrackingRampSetup.svelte | 4 ++-- src/lib/utils/logger.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/components/TrackingRampSetup.svelte b/src/lib/components/TrackingRampSetup.svelte index e8ea62c..d8f0e48 100644 --- a/src/lib/components/TrackingRampSetup.svelte +++ b/src/lib/components/TrackingRampSetup.svelte @@ -28,13 +28,13 @@ const init = async () => { // if we are displaying placeholders instead, just stop here if (displayPlaceholders) { - logger.debug("ads: display placeholder") + logger.debug("ads: display placeholder"); return; } // not properly set up? if (!publisherId || !websiteId) { - logger.debug("ads: pw data not setup correctly") + logger.debug("ads: pw data not setup correctly"); return; } diff --git a/src/lib/utils/logger.ts b/src/lib/utils/logger.ts index 0989fc6..8fc2d9b 100644 --- a/src/lib/utils/logger.ts +++ b/src/lib/utils/logger.ts @@ -1,3 +1,5 @@ +import { browser } from "$app/environment"; + export enum LogLevel { Trace, Debug, @@ -8,7 +10,7 @@ export enum LogLevel { const MAX_LOCAL_STORAGE_LOGS = 500; const LOCAL_STORAGE_KEY = "db:logs"; -const isDevMode = localStorage.getItem("devmode") === "true"; +const isDevMode = browser ? localStorage.getItem("devmode") === "true" : false; export class Logger { private logLevel: LogLevel = isDevMode ? LogLevel.Debug : LogLevel.Info; @@ -111,6 +113,10 @@ export class Logger { } private static storeLog(level: LogLevel, message: string, data: object) { + if (!browser) { + return; + } + const logs = Logger.data(); while (logs.length >= MAX_LOCAL_STORAGE_LOGS) { @@ -130,6 +136,9 @@ export class Logger { } public static data() { + if (!browser) { + return []; + } return JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) ?? "[]"); } } From 3faee490a3eac9034e29369629f01fa857fe3b80 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Fri, 10 Jan 2025 11:16:39 +0900 Subject: [PATCH 10/16] fix ga4 init --- src/lib/components/TrackingRampSetup.svelte | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/lib/components/TrackingRampSetup.svelte b/src/lib/components/TrackingRampSetup.svelte index d8f0e48..652d4eb 100644 --- a/src/lib/components/TrackingRampSetup.svelte +++ b/src/lib/components/TrackingRampSetup.svelte @@ -12,6 +12,9 @@ const websiteId = env("DB_PW_WEBSITE_ID"); const ga4MeasurementId = env("DB_GA4_MEASUREMENT_ID"); const init = async () => { + window.gtag("js", new Date()); + window.gtag("config", ga4MeasurementId); + logger.debug("ga4 initialized"); // feature flag hasn't been enabled @@ -73,17 +76,12 @@ const init = async () => { {#if ga4MeasurementId} - - + {/if} From 6777d0da6a622b29ddc5deb943337df650458b50 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Fri, 10 Jan 2025 11:23:32 +0900 Subject: [PATCH 11/16] after navigating report new url --- src/lib/components/TrackingRampSetup.svelte | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/components/TrackingRampSetup.svelte b/src/lib/components/TrackingRampSetup.svelte index 652d4eb..17643ec 100644 --- a/src/lib/components/TrackingRampSetup.svelte +++ b/src/lib/components/TrackingRampSetup.svelte @@ -1,7 +1,9 @@ From bec77083b7f1baf9879c132de165aea347767b81 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Fri, 10 Jan 2025 11:26:49 +0900 Subject: [PATCH 12/16] transition console.log statements to custom logger --- src/routes/b/[buildId]/+page.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/b/[buildId]/+page.svelte b/src/routes/b/[buildId]/+page.svelte index cfd2c6a..8b13973 100644 --- a/src/routes/b/[buildId]/+page.svelte +++ b/src/routes/b/[buildId]/+page.svelte @@ -52,6 +52,7 @@ import { phalanxWeapons } from "$lib/data/phalanx-weapons"; import { phalanxArmours } from "$lib/data/phalanx-armours.js"; import { phalanxPerks } from "$lib/data/phalanx-perks.js"; import { phalanxLanternCores } from "$lib/data/phalanx-lantern-cores.js"; +import logger from "$lib/utils/logger.js"; const { data } = $props(); @@ -65,8 +66,8 @@ let dialog: DialogProps = $state({ open: null, filters: {} }); const updateBuild = () => { data.build.flags = 0; // reset flags when user changes something - const buildId = serialize(data.build).unwrapOr(empty()); - console.log(buildId, data.build); + const buildId = serialize(data.build).unwrapOr(serialize(empty()).unwrapOr("this shouldnt happen")); + logger.info(buildId, { ...data.build }); goto(`/b/${buildId}`, { noScroll: true }); }; From 2466d16d35cbb2da7620ec776f8bea1d87f4ad0d Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Fri, 10 Jan 2025 12:10:33 +0900 Subject: [PATCH 13/16] readd simple unit --- src/lib/components/AdSpace.svelte | 72 +++++++++++++++++++++++++++++ src/routes/b/[buildId]/+page.svelte | 3 ++ 2 files changed, 75 insertions(+) create mode 100644 src/lib/components/AdSpace.svelte diff --git a/src/lib/components/AdSpace.svelte b/src/lib/components/AdSpace.svelte new file mode 100644 index 0000000..cdb2b6b --- /dev/null +++ b/src/lib/components/AdSpace.svelte @@ -0,0 +1,72 @@ + + +{#if adsEnabled && displayPlaceholders} +
    +
    +
    + +
    +
    +
    +{/if} + +{#if adsEnabled && !displayPlaceholders} +
    +
    +
    +{/if} diff --git a/src/routes/b/[buildId]/+page.svelte b/src/routes/b/[buildId]/+page.svelte index 8b13973..ba4751f 100644 --- a/src/routes/b/[buildId]/+page.svelte +++ b/src/routes/b/[buildId]/+page.svelte @@ -53,6 +53,7 @@ import { phalanxArmours } from "$lib/data/phalanx-armours.js"; import { phalanxPerks } from "$lib/data/phalanx-perks.js"; import { phalanxLanternCores } from "$lib/data/phalanx-lantern-cores.js"; import logger from "$lib/utils/logger.js"; +import AdSpace from "$lib/components/AdSpace.svelte"; const { data } = $props(); @@ -274,6 +275,8 @@ const gotoFinderPageUsingCurrentPerks = () => { + + {#if isCopyButtonVisible()}