diff --git a/_FLIPTO-README.md b/_FLIPTO-README.md new file mode 100644 index 000000000..0fb59385b --- /dev/null +++ b/_FLIPTO-README.md @@ -0,0 +1,25 @@ +This is a fork of the main repo to add support for in-memory domain user ids. +The main change is removing emptyIdCookie from id_cookie and index +to build a whitelabel build +https://docs.snowplow.io/docs/collecting-data/collecting-from-own-applications/javascript-trackers/web-tracker/hosting-the-javascript-tracker/creating-a-whitelabel-build/ + +updated tracker.lite.config.ts to contain plugins necessary + +HOW TO BUILD + +cd C:\Git\snowplow-javascript-tracker\ +rush update +rush build +cd .\trackers\javascript-tracker\ +rushx build --whitelabel=FliptoGlobalSnowplowNamespace + +-- WARNING! tag.js is broken with whitelabels! + +Output is in: +C:\Git\snowplow-javascript-tracker\trackers\javascript-tracker\dist +Take the code built for snowplow.lite and rename to ftsa.js and ftsa.js.map +Ensure you rename the mapping url and remove any header text from ftsa as well! +Publish to Azure Storage and clear CDN + +HOW TO COMMIT +Workaround gitleaks by using --no-verify i.e. git commit --no-verify -m "Adding cool new feature" \ No newline at end of file diff --git a/_FLIPTO_BUILD.ps1 b/_FLIPTO_BUILD.ps1 new file mode 100644 index 000000000..e03abf24b --- /dev/null +++ b/_FLIPTO_BUILD.ps1 @@ -0,0 +1,25 @@ +$distFolder = "C:\Git\snowplow-javascript-tracker\trackers\javascript-tracker\dist\" +$spLite = "sp.lite.js" +$ftSa = "ftsa.js" +$spLitePath = $distFolder + $spLite +$spLiteMapPath = $spLitePath + ".map" +$ftSaPath = $distFolder + $ftSa +$ftsaMapPath = $ftSaPath + ".map"; + +cd C:\Git\snowplow-javascript-tracker\ +rush build +if (Test-Path $ftSaPath) { + Remove-Item $ftSaPath +} +if (Test-Path $ftsaMapPath) { + Remove-Item $ftsaMapPath +} + +# rush update +cd .\trackers\javascript-tracker\ +rushx build --whitelabel=ftSpacetimeGlobalNamespace + +(Get-Content $spLitePath).Replace($spLite, $ftSa) | Set-Content $ftSaPath +(Get-Content $spLiteMapPath).Replace($spLite, $ftSa) | Set-Content $ftsaMapPath + +cd C:\Git\snowplow-javascript-tracker\ \ No newline at end of file diff --git a/common/autoinstallers/rush-prettier/pnpm-lock.yaml b/common/autoinstallers/rush-prettier/pnpm-lock.yaml index d0e063911..f81bc72ba 100644 --- a/common/autoinstallers/rush-prettier/pnpm-lock.yaml +++ b/common/autoinstallers/rush-prettier/pnpm-lock.yaml @@ -1,296 +1,263 @@ -lockfileVersion: 5.3 +lockfileVersion: '9.0' -specifiers: - prettier: ^2.5.1 - pretty-quick: ^3.1.3 +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false -dependencies: - prettier: 2.5.1 - pretty-quick: 3.1.3_prettier@2.5.1 +importers: + + .: + dependencies: + prettier: + specifier: ^2.5.1 + version: 2.8.8 + pretty-quick: + specifier: ^3.1.3 + version: 3.3.1(prettier@2.8.8) packages: - /@types/minimatch/3.0.5: - resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - dev: false + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: false - /array-differ/3.0.0: - resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} - dev: false - /array-union/2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: false - /arrify/2.0.1: - resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} - dev: false - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: false + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} - /chalk/3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: false - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: false + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@3.0.1: + resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} + engines: {node: '>=10'} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + pretty-quick@3.3.1: + resolution: {integrity: sha512-3b36UXfYQ+IXXqex6mCca89jC8u0mYLqFAN5eTQKoXO6oCQYcIVYZEB/5AlBHI7JPYygReM2Vv6Vom/Gln7fBg==} + engines: {node: '>=10.13'} + hasBin: true + peerDependencies: + prettier: ^2.0.0 - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} - /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} - dev: false + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} + hasBin: true + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + +snapshots: + + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: false - /end-of-stream/1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-of-stream@1.4.5: dependencies: once: 1.4.0 - dev: false - /execa/4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} + execa@4.1.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 5.2.0 human-signals: 1.1.1 is-stream: 2.0.1 merge-stream: 2.0.0 npm-run-path: 4.0.1 onetime: 5.1.2 - signal-exit: 3.0.6 + signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: false - /find-up/4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: false - /get-stream/5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} + get-stream@5.2.0: dependencies: - pump: 3.0.0 - dev: false - - /has-flag/4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: false + pump: 3.0.3 - /human-signals/1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} - dev: false + human-signals@1.1.1: {} - /ignore/5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} - engines: {node: '>= 4'} - dev: false + ignore@5.3.2: {} - /is-stream/2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: false + is-stream@2.0.1: {} - /isexe/2.0.0: - resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} - dev: false + isexe@2.0.0: {} - /locate-path/5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: false - - /merge-stream/2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: false - /mimic-fn/2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: false + merge-stream@2.0.0: {} - /minimatch/3.0.4: - resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} - dependencies: - brace-expansion: 1.1.11 - dev: false + mimic-fn@2.1.0: {} - /mri/1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: false + mri@1.2.0: {} - /multimatch/4.0.0: - resolution: {integrity: sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==} - engines: {node: '>=8'} - dependencies: - '@types/minimatch': 3.0.5 - array-differ: 3.0.0 - array-union: 2.1.0 - arrify: 2.0.1 - minimatch: 3.0.4 - dev: false - - /npm-run-path/4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 - dev: false - /once/1.4.0: - resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: false - /onetime/5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 - dev: false - /p-limit/2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: false - /p-locate/4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: false - /p-try/2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: false + p-try@2.2.0: {} - /path-exists/4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: false + path-exists@4.0.0: {} - /path-key/3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: false + path-key@3.1.1: {} - /prettier/2.5.1: - resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: false + picocolors@1.1.1: {} - /pretty-quick/3.1.3_prettier@2.5.1: - resolution: {integrity: sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==} - engines: {node: '>=10.13'} - hasBin: true - peerDependencies: - prettier: '>=2.0.0' + picomatch@3.0.1: {} + + prettier@2.8.8: {} + + pretty-quick@3.3.1(prettier@2.8.8): dependencies: - chalk: 3.0.0 execa: 4.1.0 find-up: 4.1.0 - ignore: 5.2.0 + ignore: 5.3.2 mri: 1.2.0 - multimatch: 4.0.0 - prettier: 2.5.1 - dev: false + picocolors: 1.1.1 + picomatch: 3.0.1 + prettier: 2.8.8 + tslib: 2.8.1 - /pump/3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + pump@3.0.3: dependencies: - end-of-stream: 1.4.4 + end-of-stream: 1.4.5 once: 1.4.0 - dev: false - /shebang-command/2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: false - /shebang-regex/3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: false + shebang-regex@3.0.0: {} - /signal-exit/3.0.6: - resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==} - dev: false + signal-exit@3.0.7: {} - /strip-final-newline/2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: false + strip-final-newline@2.0.0: {} - /supports-color/7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: false + tslib@2.8.1: {} - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: false - /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} - dev: false + wrappy@1.0.2: {} diff --git a/common/git-hooks/pre-commit b/common/git-hooks/pre-commit deleted file mode 100755 index 07b96ad6c..000000000 --- a/common/git-hooks/pre-commit +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. - -# Invoke the "rush prettier" custom command to reformat files whenever they -# are committed. The command is defined in common/config/rush/command-line.json -# and uses the "rush-prettier" autoinstaller. -node common/scripts/install-run-rush.js prettier || exit $? - -ERROR_COLOR='\033[0;31m' -WARNING_COLOR='\033[0;33m' -STOP_COLOR='\033[0m' - -if ! command -v gitleaks > /dev/null 2>&1 -then - echo "${ERROR_COLOR}\nGitleaks not found. To commit you safely, you need to install it per the instructions at https://github.com/gitleaks/gitleaks.${STOP_COLOR}" - exit 1 -elif [ "$SKIP" == "gitleaks" ] -then - echo "${WARNING_COLOR}\nGitleaks skipped for this commit.${STOP_COLOR}" -else - gitleaks protect -v --staged --report-path ./findings.json -fi diff --git a/libraries/browser-tracker-core/src/tracker/cookie_storage.ts b/libraries/browser-tracker-core/src/tracker/cookie_storage.ts index 8e329ae62..2d1fa431a 100644 --- a/libraries/browser-tracker-core/src/tracker/cookie_storage.ts +++ b/libraries/browser-tracker-core/src/tracker/cookie_storage.ts @@ -1,6 +1,5 @@ import { cookie, deleteCookie } from '../helpers'; - /** * Cookie storage interface for reading and writing cookies. */ @@ -60,7 +59,14 @@ export interface AsyncCookieStorage extends CookieStorage { interface Cookie { getValue: () => string; - setValue: (value?: string, ttl?: number, path?: string, domain?: string, samesite?: string, secure?: boolean) => boolean; + setValue: ( + value?: string, + ttl?: number, + path?: string, + domain?: string, + samesite?: string, + secure?: boolean + ) => boolean; deleteValue: (path?: string, domainName?: string, sameSite?: string, secure?: boolean) => void; flush: () => void; } @@ -81,7 +87,14 @@ function newCookie(name: string): Cookie { return cookie(name); } - function setValue(value?: string, ttl?: number, path?: string, domain?: string, samesite?: string, secure?: boolean): boolean { + function setValue( + value?: string, + ttl?: number, + path?: string, + domain?: string, + samesite?: string, + secure?: boolean + ): boolean { lastSetValueArgs = [value, ttl, path, domain, samesite, secure]; flushed = false; diff --git a/libraries/browser-tracker-core/src/tracker/id_cookie.ts b/libraries/browser-tracker-core/src/tracker/id_cookie.ts index 853721dc7..9644e870d 100644 --- a/libraries/browser-tracker-core/src/tracker/id_cookie.ts +++ b/libraries/browser-tracker-core/src/tracker/id_cookie.ts @@ -47,10 +47,6 @@ const cookieDisabledIndex = 0, firstEventTsInMsIndex = 9, eventIndexIndex = 10; -export function emptyIdCookie() { - const idCookie: ParsedIdCookie = ['1', '', 0, 0, 0, undefined, '', '', '', undefined, 0]; - return idCookie; -} /** * Parses the cookie values from its string representation. diff --git a/libraries/browser-tracker-core/src/tracker/index.ts b/libraries/browser-tracker-core/src/tracker/index.ts index 4bd868d8d..95b2d9fdf 100755 --- a/libraries/browser-tracker-core/src/tracker/index.ts +++ b/libraries/browser-tracker-core/src/tracker/index.ts @@ -1,73 +1,72 @@ import { - trackerCore, buildPagePing, buildPageView, CommonEventProperties, + LOG, PayloadBuilder, SelfDescribingJson, - LOG, + trackerCore, } from '@snowplow/tracker-core'; import hash from 'sha1'; import { v4 as uuid } from 'uuid'; import { - decorateQuerystring, - findRootDomain, - fixupDomain, - getReferrer, addEventListener, - getHostName, - attemptGetLocalStorage, - attemptWriteLocalStorage, attemptDeleteLocalStorage, - fixupTitle, - fromQuerystring, - isInteger, + attemptGetLocalStorage, attemptGetSessionStorage, + attemptWriteLocalStorage, attemptWriteSessionStorage, createCrossDomainParameterValue, + decorateQuerystring, + findRootDomain, + fixupDomain, + fixupTitle, + fromQuerystring, + getHostName, + getReferrer, getTimeZone, + isInteger, } from '../helpers'; +import { getBrowserProperties } from '../helpers/browser_props'; import { BrowserPlugin } from '../plugins'; -import { newOutQueue } from './out_queue'; import { fixupUrl } from '../proxies'; import { SharedState } from '../state'; +import { asyncCookieStorage, syncCookieStorage } from './cookie_storage'; +import { + clientSessionFromIdCookie, + cookiesEnabledInIdCookie, + domainUserIdFromIdCookie, + eventIndexFromIdCookie, + incrementEventIndexInIdCookie, + initializeDomainUserId, + parseIdCookie, + serializeIdCookie, + sessionIdFromIdCookie, + startNewIdCookieSession, + updateFirstEventInIdCookie, + updateNowTsInIdCookie, + visitCountFromIdCookie, +} from './id_cookie'; +import { newOutQueue } from './out_queue'; +import { APPLICATION_CONTEXT_SCHEMA, BROWSER_CONTEXT_SCHEMA, CLIENT_SESSION_SCHEMA, WEB_PAGE_SCHEMA } from './schemata'; import { - PageViewEvent, ActivityCallback, ActivityCallbackData, - TrackerConfiguration, - BrowserTracker, ActivityTrackingConfiguration, ActivityTrackingConfigurationCallback, - DisableAnonymousTrackingConfiguration, - EnableAnonymousTrackingConfiguration, - FlushBufferConfiguration, BrowserPluginConfiguration, + BrowserTracker, ClearUserDataConfiguration, ClientSession, + DisableAnonymousTrackingConfiguration, + EnableAnonymousTrackingConfiguration, ExtendedCrossDomainLinkerOptions, + FlushBufferConfiguration, + PageViewEvent, ParsedIdCookie, PreservePageViewIdForUrl, + TrackerConfiguration, } from './types'; -import { - parseIdCookie, - initializeDomainUserId, - startNewIdCookieSession, - updateNowTsInIdCookie, - serializeIdCookie, - sessionIdFromIdCookie, - domainUserIdFromIdCookie, - updateFirstEventInIdCookie, - visitCountFromIdCookie, - cookiesEnabledInIdCookie, - clientSessionFromIdCookie, - incrementEventIndexInIdCookie, - emptyIdCookie, - eventIndexFromIdCookie, -} from './id_cookie'; -import { CLIENT_SESSION_SCHEMA, WEB_PAGE_SCHEMA, BROWSER_CONTEXT_SCHEMA, APPLICATION_CONTEXT_SCHEMA } from './schemata'; -import { getBrowserProperties } from '../helpers/browser_props'; -import { asyncCookieStorage, syncCookieStorage } from './cookie_storage'; declare global { interface Navigator { @@ -496,10 +495,12 @@ export function Tracker( const fullName = getSnowplowCookieName(cookieName); if (configStateStorageStrategy == 'localStorage') { return attemptGetLocalStorage(fullName); - } else if (configStateStorageStrategy == 'cookie' || configStateStorageStrategy == 'cookieAndLocalStorage') { - return cookieStorage.getCookie(fullName); } - return undefined; + // BOHDAN KIRII / KEVIN TILLER - It always makes sense to READ a cookie that pre-exists in case of + // configurations where each page starts with no consent, then "updates" availability + // as third-party consent management widgets load + // fallback to localstorage if cookie doesn't exist + return cookieStorage.getCookie(fullName) || attemptGetLocalStorage(fullName); } /* @@ -624,6 +625,8 @@ export function Tracker( if (configStateStorageStrategy == 'localStorage') { return attemptWriteLocalStorage(name, value, timeout); } else if (configStateStorageStrategy == 'cookie' || configStateStorageStrategy == 'cookieAndLocalStorage') { + // BOHDAN KIRII / KEVIN TILLER Add local storage backup when writing to cookie + attemptWriteLocalStorage(name, value, timeout); return cookieStorage.setCookie( name, value, @@ -729,9 +732,10 @@ export function Tracker( * Load visitor ID cookie */ function loadDomainUserIdCookie() { - if (configStateStorageStrategy == 'none') { - return emptyIdCookie(); - } + // KEVIN TILLER - Removing this so we can have in-memory domainuserid when cookies are disallowed. + // if (configStateStorageStrategy == 'none') { + // return emptyIdCookie(); + // } const id = getSnowplowCookieValue('id') || undefined; return parseIdCookie(id, domainUserId, memorizedSessionId, memorizedVisitCount); } @@ -1434,6 +1438,8 @@ export function Tracker( }, }; + // KEVIN TILLER - Workaround until getDomainUserId works from GTM + ((window as any).fliptoDataLayer = (window as any).fliptoDataLayer || []).snowplow = tracker; // Initialise each plugin with the tracker browserPlugins.forEach((p) => { p.activateBrowserPlugin?.(tracker); diff --git a/libraries/browser-tracker-core/src/tracker/local_storage_event_store.ts b/libraries/browser-tracker-core/src/tracker/local_storage_event_store.ts index b6e554aa4..b3fcf8279 100644 --- a/libraries/browser-tracker-core/src/tracker/local_storage_event_store.ts +++ b/libraries/browser-tracker-core/src/tracker/local_storage_event_store.ts @@ -1,4 +1,4 @@ -import { EventStore, newInMemoryEventStore, EventStorePayload } from '@snowplow/tracker-core'; +import { EventStore, EventStorePayload, newInMemoryEventStore } from '@snowplow/tracker-core'; import { LocalStorageEventStoreConfigurationBase } from './types'; export interface LocalStorageEventStoreConfiguration extends LocalStorageEventStoreConfigurationBase { @@ -17,7 +17,9 @@ export function newLocalStorageEventStore({ maxLocalStorageQueueSize = 1000, useLocalStorage = true, }: LocalStorageEventStoreConfiguration): LocalStorageEventStore { - const queueName = `snowplowOutQueue_${trackerId}`; + // KEVIN TILLER + // Remove the name snowplow from our queue + const queueName = `ftOutQueue_${trackerId}`; function newInMemoryEventStoreFromLocalStorage() { if (useLocalStorage) { @@ -65,6 +67,12 @@ export function newLocalStorageEventStore({ getAllPayloads, setUseLocalStorage: (use: boolean) => { useLocalStorage = use; + // KEVIN TILLER + // If we lost permission to access the local storage, delete the queues. This prevents duplicate + // of page views when we have initial access, but lose access before the queue can be purged. + if (!useLocalStorage) { + window.localStorage.removeItem(queueName); + } }, }; } diff --git a/libraries/browser-tracker-core/test/tracker/application_context.test.ts b/libraries/browser-tracker-core/test/tracker/application_context.test.ts index f490dd262..582e16bf1 100644 --- a/libraries/browser-tracker-core/test/tracker/application_context.test.ts +++ b/libraries/browser-tracker-core/test/tracker/application_context.test.ts @@ -33,7 +33,7 @@ describe('Application context:', () => { ); expect(applicationContext).toBeUndefined(); done(); - return false + return false; }, }, ], diff --git a/libraries/browser-tracker-core/test/tracker/local_storage_event_store.test.ts b/libraries/browser-tracker-core/test/tracker/local_storage_event_store.test.ts index 2c1ceebcf..c652e3597 100644 --- a/libraries/browser-tracker-core/test/tracker/local_storage_event_store.test.ts +++ b/libraries/browser-tracker-core/test/tracker/local_storage_event_store.test.ts @@ -99,7 +99,7 @@ describe('LocalStorageEventStore', () => { }); const event = { payload: { e: 'pv', eid: 'test-event-id' } }; - + // Should not throw an error, even though setItem fails await expect(eventStore.add(event)).resolves.toBeDefined(); @@ -112,7 +112,7 @@ describe('LocalStorageEventStore', () => { it('should gracefully handle errors when both getItem and setItem throw SecurityError', async () => { const originalGetItem = Storage.prototype.getItem; const originalSetItem = Storage.prototype.setItem; - + Storage.prototype.getItem = jest.fn(() => { throw new DOMException('The operation is insecure.', 'SecurityError'); }); diff --git a/libraries/tracker-core/src/core.ts b/libraries/tracker-core/src/core.ts index cbe78a044..24b97c5be 100644 --- a/libraries/tracker-core/src/core.ts +++ b/libraries/tracker-core/src/core.ts @@ -569,7 +569,7 @@ export function trackerCore(configuration: CoreConfiguration = {}): TrackerCore }); plugins.length = 0; active = false; - } + }, }; plugins?.forEach((plugin) => { diff --git a/libraries/tracker-core/test/core.ts b/libraries/tracker-core/test/core.ts index 226e9dc7e..bfb833ee9 100644 --- a/libraries/tracker-core/test/core.ts +++ b/libraries/tracker-core/test/core.ts @@ -1014,7 +1014,7 @@ test('filter is passed full payload including dynamic context', (t) => { userName: 'Jon', }, }, - ] + ]; }, filter: (payload) => { return (payload.co as string).includes('com.acme'); @@ -1073,7 +1073,7 @@ test('deactivates plugins on deactivated tracker', (t) => { { deactivatePlugin: () => { pluginDeactivated = true; - } + }, }, ], }); diff --git a/plugins/browser-plugin-link-click-tracking/src/index.ts b/plugins/browser-plugin-link-click-tracking/src/index.ts index b7c060993..2e4fd7066 100644 --- a/plugins/browser-plugin-link-click-tracking/src/index.ts +++ b/plugins/browser-plugin-link-click-tracking/src/index.ts @@ -190,7 +190,7 @@ export function trackLinkClick( /** * Process a clicked element into a link_click event payload. - * + * * In case the href of the element is empty, "about:invalid" is used as the target URL. * * @param sourceElement The trackable element to be used to build the payload diff --git a/plugins/browser-plugin-screen-tracking/src/api.ts b/plugins/browser-plugin-screen-tracking/src/api.ts index de006c8a9..daa35e6b7 100644 --- a/plugins/browser-plugin-screen-tracking/src/api.ts +++ b/plugins/browser-plugin-screen-tracking/src/api.ts @@ -210,7 +210,7 @@ export function ScreenTrackingPlugin({ /** * Track a screen view event. * If screen engagement tracking is enabled, will also track a `screen_end` event with the screen summary information of the previous screen view. - * + * * Schema: `iglu:com.snowplowanalytics.mobile/screen_view/jsonschema/1-0-0` * * @param props - The properties of the screen view event @@ -234,7 +234,7 @@ export function trackScreenView( /** * Event tracking the view of an item in a list. * If screen engagement tracking is enabled, the list item view events will be aggregated into a `screen_summary` entity. - * + * * Schema: `iglu:com.snowplowanalytics.mobile/list_item_view/jsonschema/1-0-0` * * @param props - The properties of the event @@ -254,9 +254,9 @@ export function trackListItemView( /** * Event tracked when a scroll view's scroll position changes. * If screen engagement tracking is enabled, the scroll changed events will be aggregated into a `screen_summary` entity. - * + * * Schema: `iglu:com.snowplowanalytics.mobile/scroll_changed/jsonschema/1-0-0` - * + * * @param props - The properties of the event * @param trackers - The tracker identifiers which the event will be sent to */ diff --git a/plugins/browser-plugin-screen-tracking/src/core.ts b/plugins/browser-plugin-screen-tracking/src/core.ts index 3cbba124d..c3b925241 100644 --- a/plugins/browser-plugin-screen-tracking/src/core.ts +++ b/plugins/browser-plugin-screen-tracking/src/core.ts @@ -1,5 +1,12 @@ import { buildSelfDescribingEvent } from '@snowplow/tracker-core'; -import { LIST_ITEM_VIEW_EVENT_SCHEMA, SCREEN_END_EVENT_SCHEMA, SCREEN_ENTITY_SCHEMA, SCREEN_SUMMARY_ENTITY_SCHEMA, SCREEN_VIEW_EVENT_SCHEMA, SCROLL_CHANGED_EVENT_SCHEMA } from './schemata'; +import { + LIST_ITEM_VIEW_EVENT_SCHEMA, + SCREEN_END_EVENT_SCHEMA, + SCREEN_ENTITY_SCHEMA, + SCREEN_SUMMARY_ENTITY_SCHEMA, + SCREEN_VIEW_EVENT_SCHEMA, + SCROLL_CHANGED_EVENT_SCHEMA, +} from './schemata'; import { ListItemViewProps, ScreenProps, ScreenSummaryProps, ScreenViewProps, ScrollChangedProps } from './types'; export function buildScreenViewEvent(event: ScreenViewProps) { diff --git a/plugins/browser-plugin-screen-tracking/test/screen_summary.test.ts b/plugins/browser-plugin-screen-tracking/test/screen_summary.test.ts index f86454980..225b1f6c4 100644 --- a/plugins/browser-plugin-screen-tracking/test/screen_summary.test.ts +++ b/plugins/browser-plugin-screen-tracking/test/screen_summary.test.ts @@ -1,7 +1,12 @@ import { addTracker, SharedState, EventStore, BrowserTracker } from '@snowplow/browser-tracker-core'; import { ScreenTrackingPlugin, trackListItemView, trackScreenView, trackScrollChanged } from '../src'; import { buildSelfDescribingEvent, newInMemoryEventStore } from '@snowplow/tracker-core'; -import { BACKGROUND_EVENT_SCHEMA, SCREEN_END_EVENT_SCHEMA, SCREEN_SUMMARY_ENTITY_SCHEMA, SCREEN_VIEW_EVENT_SCHEMA } from '../src/schemata'; +import { + BACKGROUND_EVENT_SCHEMA, + SCREEN_END_EVENT_SCHEMA, + SCREEN_SUMMARY_ENTITY_SCHEMA, + SCREEN_VIEW_EVENT_SCHEMA, +} from '../src/schemata'; describe('Screen summary tracking', () => { let idx = 1; diff --git a/plugins/browser-plugin-web-vitals/rollup.config.js b/plugins/browser-plugin-web-vitals/rollup.config.js index 48d2287f5..d8fc0d682 100644 --- a/plugins/browser-plugin-web-vitals/rollup.config.js +++ b/plugins/browser-plugin-web-vitals/rollup.config.js @@ -1,12 +1,11 @@ -import { nodeResolve } from '@rollup/plugin-node-resolve'; +import compiler from '@ampproject/rollup-plugin-closure-compiler'; import commonjs from '@rollup/plugin-commonjs'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import { builtinModules } from 'module'; +import { terser } from 'rollup-plugin-terser'; import ts from 'rollup-plugin-ts'; // Preferred over @rollup/plugin-typescript as it bundles .d.ts files import { banner } from '../../banner'; -import compiler from '@ampproject/rollup-plugin-closure-compiler'; -import { terser } from 'rollup-plugin-terser'; -import cleanup from 'rollup-plugin-cleanup'; import pkg from './package.json'; -import { builtinModules } from 'module'; const umdPlugins = [nodeResolve({ browser: true }), commonjs(), ts()]; const umdName = 'snowplowWebVitals'; @@ -21,7 +20,7 @@ export default [ }, { input: './src/index.ts', - plugins: [...umdPlugins, compiler(), terser(), cleanup({ comments: 'none' }), banner()], + plugins: [...umdPlugins, compiler(), terser(), banner()], treeshake: { moduleSideEffects: ['sha1'] }, output: [{ file: pkg.main.replace('.js', '.min.js'), format: 'umd', sourcemap: true, name: umdName }], }, diff --git a/plugins/browser-plugin-web-vitals/src/index.ts b/plugins/browser-plugin-web-vitals/src/index.ts index e7e86f72f..edcf667e4 100644 --- a/plugins/browser-plugin-web-vitals/src/index.ts +++ b/plugins/browser-plugin-web-vitals/src/index.ts @@ -1,36 +1,28 @@ import { BrowserPlugin, BrowserTracker, dispatchToTrackersInCollection } from '@snowplow/browser-tracker-core'; -import { DynamicContext, buildSelfDescribingEvent, resolveDynamicContext } from '@snowplow/tracker-core'; +import { buildSelfDescribingEvent, DynamicContext, resolveDynamicContext } from '@snowplow/tracker-core'; import { WEB_VITALS_SCHEMA } from './schemata'; -import { attachWebVitalsPageListeners, createWebVitalsScript, webVitalsListener } from './utils'; +import { attachWebVitalsPageListeners, webVitalsListener } from './utils'; const _trackers: Record = {}; -const WEB_VITALS_SOURCE = 'https://unpkg.com/web-vitals@4/dist/web-vitals.iife.js'; let listenersAttached = false; - interface WebVitalsPluginOptions { loadWebVitalsScript?: boolean; webVitalsSource?: string; context?: DynamicContext; } - const defaultPluginOptions = { - loadWebVitalsScript: true, - webVitalsSource: WEB_VITALS_SOURCE, context: [], }; /** * Adds Web Vitals measurement events * - * @param pluginOptions.loadWebVitalsScript - Should the plugin immediately load the Core Web Vitals measurement script from UNPKG CDN. - * @param pluginOptions.webVitalsSource - The URL endpoint the Web Vitals script should be loaded from. Defaults to the UNPKG CDN. * @remarks */ export function WebVitalsPlugin(pluginOptions: WebVitalsPluginOptions = defaultPluginOptions): BrowserPlugin { const webVitalsObject: Record = {}; const options = { ...defaultPluginOptions, ...pluginOptions }; let trackerId: string; - let webVitalsScript: HTMLScriptElement | undefined; return { activateBrowserPlugin: (tracker) => { trackerId = tracker.id; @@ -53,20 +45,12 @@ export function WebVitalsPlugin(pluginOptions: WebVitalsPluginOptions = defaultP }); } - if (options.loadWebVitalsScript) { - webVitalsScript = createWebVitalsScript(options.webVitalsSource); - } - /* * Attach page listeners only once per page. * Prevent multiple trackers from attaching listeners multiple times. */ if (!listenersAttached) { - if (webVitalsScript) { - webVitalsScript.addEventListener('load', () => webVitalsListener(webVitalsObject)); - } else { - webVitalsListener(webVitalsObject); - } + webVitalsListener(webVitalsObject); attachWebVitalsPageListeners(sendWebVitals); listenersAttached = true; } diff --git a/plugins/browser-plugin-web-vitals/src/utils.ts b/plugins/browser-plugin-web-vitals/src/utils.ts index 0434e378b..7ae6fce7d 100644 --- a/plugins/browser-plugin-web-vitals/src/utils.ts +++ b/plugins/browser-plugin-web-vitals/src/utils.ts @@ -1,4 +1,4 @@ -import { LOG } from '@snowplow/tracker-core'; +import { onCLS, onFCP, onFID, onINP, onLCP, onTTFB } from 'web-vitals'; import { MetricType } from './types'; /** @@ -27,23 +27,6 @@ export function attachWebVitalsPageListeners(callback: () => void) { } } -/** - * - * @param {string} webVitalsSource Web Vitals script source. - * @returns {string} The script element of the Web Vitals script. Used for attaching listeners on it. - */ -export function createWebVitalsScript(webVitalsSource: string) { - const webVitalsScript = document.createElement('script'); - webVitalsScript.setAttribute('src', webVitalsSource); - webVitalsScript.setAttribute('async', '1'); - webVitalsScript.addEventListener('error', () => { - LOG.error(`Failed to load ${webVitalsSource}`); - }); - - document.head.appendChild(webVitalsScript); - return webVitalsScript; -} - /** * * Adds the Web Vitals measurements on the object used by the trackers to store metric properties. @@ -57,17 +40,10 @@ export function webVitalsListener(webVitalsObject: Record) { webVitalsObject.navigationType = arg.navigationType; }; } - - const webVitals = window.webVitals; - if (!webVitals) { - LOG.warn('The window.webVitals API is currently unavailable. web_vitals events will not be collected.'); - return; - } - - webVitals.onCLS?.(addWebVitalsMeasurement('cls')); - webVitals.onFID?.(addWebVitalsMeasurement('fid')); - webVitals.onLCP?.(addWebVitalsMeasurement('lcp')); - webVitals.onFCP?.(addWebVitalsMeasurement('fcp')); - webVitals.onINP?.(addWebVitalsMeasurement('inp')); - webVitals.onTTFB?.(addWebVitalsMeasurement('ttfb')); + onCLS(addWebVitalsMeasurement('cls')); + onFID(addWebVitalsMeasurement('fid')); + onLCP(addWebVitalsMeasurement('lcp')); + onFCP(addWebVitalsMeasurement('fcp')); + onINP(addWebVitalsMeasurement('inp')); + onTTFB(addWebVitalsMeasurement('ttfb')); } diff --git a/trackers/javascript-tracker/rollup.config.js b/trackers/javascript-tracker/rollup.config.js index 6b7c7ddf2..80d74c736 100644 --- a/trackers/javascript-tracker/rollup.config.js +++ b/trackers/javascript-tracker/rollup.config.js @@ -28,18 +28,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import ts from 'rollup-plugin-ts'; // Prefered over @rollup/plugin-typescript as it bundles .d.ts files +import compiler from '@ampproject/rollup-plugin-closure-compiler'; +import alias from '@rollup/plugin-alias'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import filesize from 'rollup-plugin-filesize'; +import sizes from 'rollup-plugin-sizes'; +import { terser } from 'rollup-plugin-terser'; +import ts from 'rollup-plugin-ts'; // Prefered over @rollup/plugin-typescript as it bundles .d.ts files import { banner } from '../../banner'; import { whitelabelBuild } from './build-config/index'; -import compiler from '@ampproject/rollup-plugin-closure-compiler'; -import { terser } from 'rollup-plugin-terser'; -import cleanup from 'rollup-plugin-cleanup'; -import sizes from 'rollup-plugin-sizes'; -import filesize from 'rollup-plugin-filesize'; -import alias from '@rollup/plugin-alias'; import pkg from './package.json'; export default (cmdlineArgs) => { @@ -50,7 +49,7 @@ export default (cmdlineArgs) => { ts(), compiler(), terser(), - cleanup({ comments: 'none' }), + // cleanup({ comments: 'none' }), banner(), sizes(), filesize({ showMinifiedSize: false, showBeforeSizes: 'build' }), diff --git a/trackers/javascript-tracker/src/index.ts b/trackers/javascript-tracker/src/index.ts index c5fae6eda..9dd91e678 100644 --- a/trackers/javascript-tracker/src/index.ts +++ b/trackers/javascript-tracker/src/index.ts @@ -42,7 +42,10 @@ declare global { } const functionName = window.GlobalSnowplowNamespace.shift() as string, - queue = window[functionName] as { q: Queue | Array }; + queue = window[functionName] as { q: Queue | Array | null }; // Now replace initialization array with queue manager object -queue.q = InQueueManager(functionName, queue.q as Array); +// KEVIN TILLER - Fix error when running tracker script twice +if (queue) { + queue.q = InQueueManager(functionName, queue.q as Array); +} diff --git a/trackers/javascript-tracker/tags/tag.js b/trackers/javascript-tracker/tags/tag.js index e0eea9ea8..c32d549d7 100644 --- a/trackers/javascript-tracker/tags/tag.js +++ b/trackers/javascript-tracker/tags/tag.js @@ -45,11 +45,11 @@ // Stop if the Snowplow namespace i already exists if (!p[i]) { - // Initialise the 'GlobalSnowplowNamespace' array - p['GlobalSnowplowNamespace'] = p['GlobalSnowplowNamespace'] || []; + // Initialise the 'FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace' array + p['FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace'] = p['FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace'] || []; // Add the new Snowplow namespace to the global array so sp.js can find it - p['GlobalSnowplowNamespace'].push(i); + p['FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace'].push(i); // Create the Snowplow function p[i] = function() { diff --git a/trackers/javascript-tracker/tags/tag.min.js b/trackers/javascript-tracker/tags/tag.min.js index 076a35071..4bb3d162c 100644 --- a/trackers/javascript-tracker/tags/tag.min.js +++ b/trackers/javascript-tracker/tags/tag.min.js @@ -27,4 +27,4 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[]; p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments) };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1; n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,'script','//{{url}}/sp.js','new_name_here')); +;(function(p,l,o,w,i,n,g){if(!p[i]){p.FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace=p.FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace||[]; p.FliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoFliptoftSaGlobalNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments) };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1; n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,'script','//{{url}}/sp.js','new_name_here')); diff --git a/trackers/javascript-tracker/test/pages/multi_page_cookies/index.html b/trackers/javascript-tracker/test/pages/multi_page_cookies/index.html index b5da19e21..a8d815255 100644 --- a/trackers/javascript-tracker/test/pages/multi_page_cookies/index.html +++ b/trackers/javascript-tracker/test/pages/multi_page_cookies/index.html @@ -1,21 +1,19 @@ + + Cookies test page + - - Cookies test page - - - - - - + + + diff --git a/trackers/javascript-tracker/tracker.lite.config.ts b/trackers/javascript-tracker/tracker.lite.config.ts index 4bc2a4227..d3e1e2482 100644 --- a/trackers/javascript-tracker/tracker.lite.config.ts +++ b/trackers/javascript-tracker/tracker.lite.config.ts @@ -1,14 +1,14 @@ export const performanceTiming = false; -export const performanceNavigationTiming = false; -export const gaCookies = false; +export const performanceNavigationTiming = true; +export const gaCookies = true; export const geolocation = false; export const optimizelyX = false; -export const clientHints = false; +export const clientHints = true; export const linkClickTracking = false; export const formTracking = false; -export const errorTracking = false; +export const errorTracking = true; export const timezone = false; -export const enhancedEcommerce = false; +export const enhancedEcommerce = true; export const adTracking = false; export const siteTracking = false; export const snowplowEcommerceTracking = false; @@ -20,5 +20,5 @@ export const vimeoTracking = false; export const privacySandbox = false; export const buttonClickTracking = false; export const eventSpecifications = false; -export const webVitals = false; +export const webVitals = true; export const elementTracking = false; diff --git a/trackers/react-native-tracker/babel.config.js b/trackers/react-native-tracker/babel.config.js index 29f3a6069..e75f9f1ec 100644 --- a/trackers/react-native-tracker/babel.config.js +++ b/trackers/react-native-tracker/babel.config.js @@ -1,5 +1,3 @@ module.exports = { - presets: [ - ['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }], - ], + presets: [['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }]], }; diff --git a/trackers/react-native-tracker/src/__mocks__/@react-native-async-storage/async-storage.js b/trackers/react-native-tracker/src/__mocks__/@react-native-async-storage/async-storage.js index 125233a46..b7779faa3 100644 --- a/trackers/react-native-tracker/src/__mocks__/@react-native-async-storage/async-storage.js +++ b/trackers/react-native-tracker/src/__mocks__/@react-native-async-storage/async-storage.js @@ -1,2 +1,2 @@ -import AsyncStorage from "@react-native-async-storage/async-storage/jest/async-storage-mock"; +import AsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; export default AsyncStorage; diff --git a/trackers/react-native-tracker/src/constants.ts b/trackers/react-native-tracker/src/constants.ts index 5c1fbb0d7..363b59c8d 100644 --- a/trackers/react-native-tracker/src/constants.ts +++ b/trackers/react-native-tracker/src/constants.ts @@ -2,9 +2,10 @@ export const FOREGROUND_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/appl export const BACKGROUND_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/application_background/jsonschema/1-0-0'; export const DEEP_LINK_RECEIVED_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.mobile/deep_link_received/jsonschema/1-0-0'; export const SCREEN_VIEW_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.mobile/screen_view/jsonschema/1-0-0'; -export const APPLICATION_INSTALL_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.mobile/application_install/jsonschema/1-0-0'; +export const APPLICATION_INSTALL_EVENT_SCHEMA = + 'iglu:com.snowplowanalytics.mobile/application_install/jsonschema/1-0-0'; -export const CLIENT_SESSION_ENTITY_SCHEMA ='iglu:com.snowplowanalytics.snowplow/client_session/jsonschema/1-0-2' +export const CLIENT_SESSION_ENTITY_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/client_session/jsonschema/1-0-2'; export const MOBILE_CONTEXT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/mobile_context/jsonschema/1-0-3'; export const DEEP_LINK_ENTITY_SCHEMA = 'iglu:com.snowplowanalytics.mobile/deep_link/jsonschema/1-0-0'; export const LIFECYCLE_CONTEXT_SCHEMA = 'iglu:com.snowplowanalytics.mobile/application_lifecycle/jsonschema/1-0-0'; diff --git a/trackers/react-native-tracker/src/plugins/app_context/index.ts b/trackers/react-native-tracker/src/plugins/app_context/index.ts index 417020df2..0c64f9597 100644 --- a/trackers/react-native-tracker/src/plugins/app_context/index.ts +++ b/trackers/react-native-tracker/src/plugins/app_context/index.ts @@ -5,7 +5,7 @@ import { APPLICATION_CONTEXT_SCHEMA, MOBILE_APPLICATION_CONTEXT_SCHEMA } from '. /** * Tracks the application context entity with information about the app version. * If appBuild is provided, a mobile application context is tracked, otherwise the Web equivalent is tracked. - * + * * Entity schema if `appBuild` property is set: `iglu:com.snowplowanalytics.mobile/application/jsonschema/1-0-0` * Entity schema if `appBuild` property is not set: `iglu:com.snowplowanalytics.snowplow/application/jsonschema/1-0-0` */ diff --git a/trackers/react-native-tracker/src/plugins/deep_links/index.ts b/trackers/react-native-tracker/src/plugins/deep_links/index.ts index d3370e854..71a0902c5 100644 --- a/trackers/react-native-tracker/src/plugins/deep_links/index.ts +++ b/trackers/react-native-tracker/src/plugins/deep_links/index.ts @@ -1,6 +1,12 @@ import { buildSelfDescribingEvent, CorePluginConfiguration, PayloadBuilder, TrackerCore } from '@snowplow/tracker-core'; import { DeepLinkConfiguration, DeepLinkReceivedProps, EventContext } from '../../types'; -import { DEEP_LINK_ENTITY_SCHEMA, DEEP_LINK_RECEIVED_EVENT_SCHEMA, PAGE_REFERRER_PROPERTY, PAGE_URL_PROPERTY, SCREEN_VIEW_EVENT_SCHEMA } from '../../constants'; +import { + DEEP_LINK_ENTITY_SCHEMA, + DEEP_LINK_RECEIVED_EVENT_SCHEMA, + PAGE_REFERRER_PROPERTY, + PAGE_URL_PROPERTY, + SCREEN_VIEW_EVENT_SCHEMA, +} from '../../constants'; import { getUsefulSchema } from '../../utils'; interface DeepLinksPlugin extends CorePluginConfiguration { diff --git a/trackers/react-native-tracker/test/ecommerce.test.ts b/trackers/react-native-tracker/test/ecommerce.test.ts index 7fbc06ee5..5f88ad48e 100644 --- a/trackers/react-native-tracker/test/ecommerce.test.ts +++ b/trackers/react-native-tracker/test/ecommerce.test.ts @@ -1,5 +1,9 @@ import { newTracker } from '../src'; -import { setEcommerceUser, SnowplowEcommercePlugin, trackProductView } from '@snowplow/browser-plugin-snowplow-ecommerce'; +import { + setEcommerceUser, + SnowplowEcommercePlugin, + trackProductView, +} from '@snowplow/browser-plugin-snowplow-ecommerce'; function createMockFetch(status: number, requests: Request[]) { return async (input: Request) => { @@ -37,7 +41,7 @@ describe('Tracking ecommerce events using the ecomerce plugin', () => { category: 'my-category', price: 100, currency: 'USD', - }) + }); await tracker.flush(); expect(requests.length).toBe(1); diff --git a/trackers/react-native-tracker/test/web_view_interface.test.ts b/trackers/react-native-tracker/test/web_view_interface.test.ts index da33775af..d606398a9 100644 --- a/trackers/react-native-tracker/test/web_view_interface.test.ts +++ b/trackers/react-native-tracker/test/web_view_interface.test.ts @@ -177,7 +177,6 @@ describe('WebView interface', () => { }); describe('WebView event tracking', () => { - it('tracks a page view event', async () => { const tracker = await newTracker({ namespace: 'test', @@ -185,7 +184,7 @@ describe('WebView interface', () => { endpoint: 'http://localhost:9090', customFetch: mockFetch, }); - + const webViewInterface = getWebViewCallback(); webViewInterface({ nativeEvent: { @@ -200,14 +199,14 @@ describe('WebView interface', () => { }), }, }); - + await tracker.flush(); expect(requests.length).toBe(1); - + const [request] = requests; const payload = await request?.json(); expect(payload.data.length).toBe(1); - + const [event] = payload.data; expect(event.e).toBe('pv'); expect(event.url).toBe('http://localhost:9090'); @@ -223,7 +222,7 @@ describe('WebView interface', () => { customFetch: mockFetch, encodeBase64: false, }); - + const webViewInterface = getWebViewCallback(); webViewInterface({ nativeEvent: { @@ -240,14 +239,14 @@ describe('WebView interface', () => { }), }, }); - + await tracker.flush(); expect(requests.length).toBe(1); - + const [request] = requests; const payload = await request?.json(); expect(payload.data.length).toBe(1); - + const [event] = payload.data; const { e, ue_pr } = event; expect(e).toBe('ue'); @@ -264,7 +263,7 @@ describe('WebView interface', () => { endpoint: 'http://localhost:9090', customFetch: mockFetch, }); - + const webViewInterface = getWebViewCallback(); webViewInterface({ nativeEvent: { @@ -281,14 +280,14 @@ describe('WebView interface', () => { }), }, }); - + await tracker.flush(); expect(requests.length).toBe(1); - + const [request] = requests; const payload = await request?.json(); expect(payload.data.length).toBe(1); - + const [event] = payload.data; const { e, se_ca, se_ac, se_la, se_pr, se_va } = event; expect(e).toBe('se'); @@ -306,7 +305,7 @@ describe('WebView interface', () => { endpoint: 'http://localhost:9090', customFetch: mockFetch, }); - + const webViewInterface = getWebViewCallback(); webViewInterface({ nativeEvent: { @@ -325,14 +324,14 @@ describe('WebView interface', () => { }), }, }); - + await tracker.flush(); expect(requests.length).toBe(1); - + const [request] = requests; const payload = await request?.json(); expect(payload.data.length).toBe(1); - + const [event] = payload.data; expect(event.e).toBe('pp'); expect(event.url).toBe('http://localhost:9090');