diff --git a/.env.local b/.env.local new file mode 100644 index 00000000..55335f1a --- /dev/null +++ b/.env.local @@ -0,0 +1,99 @@ +######################################################## +### Runtime variables +######################################################## + +### Runtime variables are recognized when Umami is running. +### You can set your environment variables prior to starting the application. + +### +### Connection string for Umami's database. This is the only required variable. +### +DATABASE_URL=mysql://root:lemon@127.0.0.1/umami + +### +### You can provide a comma-delimited list of IP address to exclude from data collection. +### +IGNORE_IP= + +### +### This will redirect all requests from http to https in the Umami application. Note, this does not apply to the tracking script. +### +FORCE_SSL=1 + +### +### If you are running in development mode, this will log database queries to the console for debugging. +### +LOG_QUERY=1 + +### +### Removes the trailing slash from all incoming urls. +### +REMOVE_TRAILING_SLASH=1 + +### +### Allows you to assign a custom name to the tracker script different from the default umami. This is to help you avoid some ad-blockers. +### +### Note: If you update this, be sure to update the tracking code on your website to the new name. +### +TRACKER_SCRIPT_NAME=lemonsquare + +### +### Allows you to send metrics to a location different than the default /api/collect. This is to help you avoid some ad-blockers. +### +COLLECT_API_ENDPOINT=/api/collect + +### +### Disables the check for new versions of Umami. +### +DISABLE_UPDATES=1 + +### +### Disables the login page for the application. +### +# DISABLE_LOGIN=1 + +### +### Umami collects completely anonymous telemetry data in order help improve the application. +### You can choose to disable this if you don't want to participate. +### +# DISABLE_TELEMETRY=1 + +### +### A random string used to generate unique values. +### +HASH_SALT=lemonsquare + + +######################################################## +### Build time variables +######################################################## + +### Build time variables are only recognized during the build process. +### This also includes building custom Docker images. +### You need to set your environment variables prior to building the application. + +### +### The type of DB to be used. This is only required for the Docker build. +### +DATABASE_TYPE=mysql + +######################################################## +### Other variables +######################################################## + +### +### Skip db check flag. Uncomment this line if you want to skip database check. +### For more details see scripts/check-db.js +### +# SKIP_DB_CHECK=true + +### +### Maxmind commercial license key. You can get one here: https://www.maxmind.com/en/geoip2-city +### Used internally to get the country code (and city if commercial license is used) for the visitor. +### +# MAXMIND_LICENSE_KEY= + +### +### (Experimental) Enable below to share session id accross different domains. +### +CROSSDOMAIN_TRACKING=true diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..ef4dfbe9 --- /dev/null +++ b/TODO.md @@ -0,0 +1,53 @@ +# TODO List + +## General TODOs + +- [ ] Check all source code. +- [ ] Update this list. +- [ ] Extract all envs and create `.env.example`, `.env.local` and `.env` files +- [ ] Add simple documentation about hidden functionality. + +## CI/CD TODOs + +- [ ] Setup lemonsquare CI/CD. + +## Research TODOs + +- [x] What is the function of process.env.COLLECT_API_ENDPOINT? + +## Improvement TODOs + +- [ ] ~~Add process.env.MAXMIND_LICENSE_KEY for more accurate city geolocation ($100 / month)~~ +- [x] Add crossdomain support + +## About + +### Geolocation + +For geolocation in dev, we are using [this repo data](https://github.com/GitSquared/node-geolite2-redist) + +### Tracker + +#### script + +See [tracker script](/tracker/index.js) + +#### Tracker configuration + +| data-parameter | description | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| data-website-id | TODO | +| data-host-url | By default, Umami will send data to wherever the script is located. You can override this to send data to another location. | +| data-auto-track | By default, Umami tracks all pageviews and events for you automatically. You can disable this behavior and track events yourself using the tracker functions. | +| data-do-not-track | You can configure Umami to respect the visitor's Do Not Track setting. | +| data-cache | If you get a lot of pageviews from the same user, for example in a forum website, you can cache some data to improve the performance of the tracking script. | +| data-domains | If you want the tracker to only run on specific domains, you can add them to your tracker script. Helps if you are working in a staging/development environment. | +| data-css-events | Activate if you want to enable css events | + +For more details [see here](https://umami.is/docs/tracker-configuration) + +### References + +[Tracker functions](https://umami.is/docs/tracker-functions) + +[maxmind.com geoip city accuracy for Japan](https://www.maxmind.com/en/geoip2-city-accuracy-comparison?country=JP&resolution=50&cellular=all) diff --git a/db/mysql/schema.prisma b/db/mysql/schema.prisma index 9ad2620c..fac97143 100644 --- a/db/mysql/schema.prisma +++ b/db/mysql/schema.prisma @@ -69,6 +69,8 @@ model session { screen String? @db.VarChar(11) language String? @db.VarChar(35) country String? @db.Char(2) + ip String? @db.VarChar(255) + user_agent String? @db.Text website website @relation(fields: [website_id], references: [website_id]) event event[] pageview pageview[] diff --git a/lib/session.js b/lib/session.js index 1b79f316..b3cadfb2 100644 --- a/lib/session.js +++ b/lib/session.js @@ -47,7 +47,10 @@ export async function getSession(req) { const { userAgent, browser, os, ip, country, device } = await getClientInfo(req, payload); - const session_uuid = uuid(websiteId, hostname, ip, userAgent); + let session_uuid = uuid(websiteId, hostname, ip, userAgent); + if (process.env.CROSSDOMAIN_TRACKING) { + session_uuid = uuid(websiteId, ip, userAgent); + } let sessionCreated = false; let sessionId = null; @@ -76,6 +79,8 @@ export async function getSession(req) { language, country, device, + ip, + user_agent: userAgent, }); sessionId = session ? session.session_id : null; diff --git a/tracker/index.js b/tracker/index.js index 1eb54d63..4c4b9e11 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -86,7 +86,10 @@ return fetch(endpoint, { method: 'POST', body: JSON.stringify({ type, payload }), - headers: assign({ 'Content-Type': 'application/json' }, { ['x-umami-cache']: cache }), + headers: assign( + { 'Content-Type': 'application/json' }, + { ['x-umami-cache']: cache, ['x-lemonsquare-cache']: cache }, + ), }) .then(res => res.text()) .then(text => (cache = text)); @@ -194,6 +197,7 @@ umami.trackEvent = trackEvent; window.umami = umami; + window.lemonsquare = umami; } /* Start */ diff --git a/tracker/shopify.js b/tracker/shopify.js new file mode 100644 index 00000000..26070bb3 --- /dev/null +++ b/tracker/shopify.js @@ -0,0 +1,31 @@ +/* eslint-disable no-undef */ +const DOMAIN = 'http://localhost:3000'; +const TRACKER_SCRIPT_NAME = 'lemonsquare'; +const WEBSITE_ID = '21c0c2f5-ae71-47f2-a80a-05cc5052fec7'; +const AUTO_TRACK = 'false'; +const DO_NOT_TRACK = 'false'; +const CACHE = 'true'; + +const script = document.createElement('script'); +script.setAttribute('src', `${DOMAIN}/${TRACKER_SCRIPT_NAME}.js`); +script.setAttribute('data-website-id', WEBSITE_ID); +script.setAttribute('data-auto-track', AUTO_TRACK); +script.setAttribute('data-do-not-track', DO_NOT_TRACK); +script.setAttribute('data-cache', CACHE); +script.setAttribute('async', ''); +script.setAttribute('defer', ''); +// initialize script +document.head.appendChild(script); + +analytics.subscribe('page_viewed', async event => { + lemonsquare.trackView(event.url, event.referrer); +}); + +// analytics.subscribe('product_viewed', async event => { +// fbq('track', 'ViewContent', { +// content_ids: [event.data.productVariant.id], +// content_name: event.data.productVariant.title, +// currency: event.data.productVariant.price.currencyCode, +// value: event.data.productVariant.price.amount, +// }); +// });