teacupnet-lib 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,62 @@ const data = {
3
3
  form: [],
4
4
  page: [],
5
5
  };
6
+ const prevData = {
7
+ button: [],
8
+ form: [],
9
+ page: [],
10
+ };
11
+ const clearData = () => {
12
+ prevData.button = [...data.button];
13
+ prevData.form = [...data.form];
14
+ prevData.page = [...data.page];
15
+ data.button = [];
16
+ data.form = [];
17
+ data.page = [];
18
+ };
19
+
20
+ const getNewData = () => {
21
+ const newData = {
22
+ button: [],
23
+ form: [],
24
+ page: [],
25
+ };
26
+
27
+ // Compare buttons - only include if not in prevData
28
+ data.button.forEach((btn) => {
29
+ const isDuplicate = prevData.button.some(
30
+ (prevBtn) => prevBtn.button === btn.button && prevBtn.page === btn.page
31
+ );
32
+ if (!isDuplicate) {
33
+ newData.button.push(btn);
34
+ }
35
+ });
36
+
37
+ // Compare pages - only include if page+percentage combo not in prevData
38
+ data.page.forEach((pg) => {
39
+ const isDuplicate = prevData.page.some(
40
+ (prevPg) =>
41
+ prevPg.page === pg.page && prevPg.percentage === pg.percentage
42
+ );
43
+ if (!isDuplicate) {
44
+ newData.page.push(pg);
45
+ }
46
+ });
47
+
48
+ // Compare forms - only include if form+percent combo not in prevData
49
+ data.form.forEach((frm) => {
50
+ const isDuplicate = prevData.form.some(
51
+ (prevFrm) =>
52
+ prevFrm.form === frm.form && prevFrm.percent === frm.percent
53
+ );
54
+ if (!isDuplicate) {
55
+ newData.form.push(frm);
56
+ }
57
+ });
58
+
59
+ return newData;
60
+ };
61
+
6
62
  const setData = (type, result) => {
7
63
  if (type === 'page') {
8
64
  // Find existing page entry
@@ -50,4 +106,4 @@ const setData = (type, result) => {
50
106
  return data;
51
107
  };
52
108
 
53
- export default { setData, data };
109
+ export default { setData, data, clearData, getNewData };
@@ -0,0 +1,25 @@
1
+ const FINGERPRINT_KEY = 'teacupnet_fingerprint';
2
+
3
+ export default function fingerprint() {
4
+ // Check if fingerprint already exists in localStorage
5
+ const existingFingerprint = localStorage.getItem(FINGERPRINT_KEY);
6
+
7
+ if (existingFingerprint) {
8
+ return existingFingerprint;
9
+ }
10
+
11
+ // Generate new fingerprint if not found
12
+ const canvas = document.createElement('canvas');
13
+ canvas.width = 20;
14
+ canvas.height = 2220;
15
+ const ctx = canvas.getContext('2d');
16
+ ctx.fillText('Hello', 10, 10);
17
+
18
+ const data = canvas.toDataURL();
19
+ const newFingerprint = data.slice(-32);
20
+
21
+ // Store in localStorage for future use
22
+ localStorage.setItem(FINGERPRINT_KEY, newFingerprint);
23
+
24
+ return newFingerprint;
25
+ }
package/Analytics/save.js CHANGED
@@ -1,14 +1,27 @@
1
1
  import fetchAPI from '../Functions/FetchAPI';
2
- import fingerprint from './fingerprint';
2
+ import fingerprint from './identity';
3
3
  import data from './data.controller';
4
4
  import { initial } from '..';
5
5
 
6
6
  export default function save() {
7
7
  setInterval(() => {
8
- fetchAPI('api/analytics', 'POST', {
9
- data: data.data,
10
- initial: initial,
11
- fingerprint: fingerprint(),
12
- });
8
+ const newData = data.getNewData();
9
+
10
+ // Check if there's any new data to send
11
+ const hasNewData =
12
+ newData.button.length > 0 ||
13
+ newData.form.length > 0 ||
14
+ newData.page.length > 0;
15
+
16
+ if (hasNewData) {
17
+ fetchAPI('api/analytics', 'POST', {
18
+ data: newData,
19
+ initial: initial,
20
+ fingerprint: fingerprint(),
21
+ });
22
+
23
+ // Clear data after sending
24
+ data.clearData();
25
+ }
13
26
  }, 5000);
14
27
  }
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+
9
+ ## [1.1.0] - 2025-12-26
10
+
11
+ ### Added
12
+ - **Duplicate Prevention System**: Analytics data is now compared with previously sent data to prevent duplicates from being stored in the database
13
+ - **LocalStorage Fingerprint**: Visitor fingerprint now persists in localStorage across browser sessions for consistent identification
14
+ - `getNewData()` function in data controller that filters out duplicate analytics before sending
15
+
16
+ ### Changed
17
+ - Fingerprint generation now happens only once per browser and is stored in localStorage with key `teacupnet_fingerprint`
18
+ - Analytics save function now only sends API requests when there is new data to transmit
19
+ - Data comparison logic ensures button clicks, page views, and form interactions are only sent once
20
+
21
+ ### Fixed
22
+ - Duplicate button clicks on the same page are no longer sent multiple times
23
+ - Same page scroll percentages are no longer duplicated in database
24
+ - Form completion percentages only update when they change
25
+ - Reduced unnecessary API calls when no new analytics data is available
26
+
27
+ ### Performance
28
+ - Reduced database writes by filtering duplicates before transmission
29
+ - Reduced network requests by skipping empty data intervals
30
+ - Fingerprint generation optimized to run only once per browser session
31
+
8
32
  ## [1.0.0] - 2025-12-17
9
33
 
10
34
  ### Added
@@ -7,10 +7,10 @@ export default async function fetchAPI(path, method = 'GET', body = null) {
7
7
  body: JSON.stringify(body),
8
8
  };
9
9
  if (method === 'GET') delete req.body;
10
-
11
- try {
12
- const data = await fetch(`https://teacupnet-backend.vercel.app/${path}`, req);
13
10
 
11
+ try {
12
+ // const data = await fetch(`https://teacupnet-backend.vercel.app/${path}`, req);
13
+ const data = await fetch(`http://localhost:3000/${path}`, req);
14
14
  return await data.json();
15
15
  } catch (error) {
16
16
  console.log(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teacupnet-lib",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A powerful JavaScript library for integrating TeacupNet analytics and data management. Track user interactions, page views, form completions, and seamlessly connect to the TeacupNet backend.",
5
5
  "keywords": [
6
6
  "analytics",
@@ -1,10 +0,0 @@
1
- export default function fingerprint() {
2
- const canvas = document.createElement('canvas');
3
- canvas.width = 20;
4
- canvas.height = 2220;
5
- const ctx = canvas.getContext('2d');
6
- ctx.fillText('Hello', 10, 10);
7
-
8
- const data = canvas.toDataURL();
9
- return data.slice(-32);
10
- }