@imrankhanjoya/visit-analytics 1.0.0 → 1.0.1
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.
- package/README.md +119 -0
- package/package.json +6 -3
- package/src/index.js +4 -1
- package/src/trackVisit.js +52 -7
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @imrankhanjoya/visit-analytics
|
|
2
|
+
|
|
3
|
+
Simple MongoDB and Mongoose-based visit analytics package for Next.js and Node.js applications.
|
|
4
|
+
|
|
5
|
+
Track page visits, profile visits, post visits, unique visitors, and retrieve visitor details with minimal setup.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
bash npm install @imrankhanjoya/visit-analytics
|
|
10
|
+
|
|
11
|
+
or
|
|
12
|
+
|
|
13
|
+
bash pnpm add @imrankhanjoya/visit-analytics
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Install Mongoose and connect to MongoDB before using this package.
|
|
18
|
+
|
|
19
|
+
bash npm install mongoose
|
|
20
|
+
|
|
21
|
+
javascript import mongoose from "mongoose"; await mongoose.connect(process.env.MONGODB_URI);
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Exports
|
|
26
|
+
|
|
27
|
+
The package exports:
|
|
28
|
+
|
|
29
|
+
javascript import { Visit, saveVisit, getVisits, getVisitMembers, } from "@imrankhanjoya/visit-analytics";
|
|
30
|
+
|
|
31
|
+
## Visit Model
|
|
32
|
+
|
|
33
|
+
A ready-to-use Mongoose model.
|
|
34
|
+
|
|
35
|
+
javascript import { Visit } from "@imrankhanjoya/visit-analytics"; const visits = await Visit.find();
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## saveVisit()
|
|
40
|
+
|
|
41
|
+
Create or record a visit.
|
|
42
|
+
|
|
43
|
+
### Example
|
|
44
|
+
|
|
45
|
+
javascript import { saveVisit } from "@imrankhanjoya/visit-analytics"; await saveVisit({ path: "john-doe", type: "profile", token: "visitor-token", ip: "127.0.0.1", userinfo: [ { username: "imran", image: "https://example.com/profile.jpg", }, ], });
|
|
46
|
+
|
|
47
|
+
### Parameters
|
|
48
|
+
|
|
49
|
+
| Property | Type | Required |
|
|
50
|
+
|----------|------|----------|
|
|
51
|
+
| path | string | Yes |
|
|
52
|
+
| type | string | Yes |
|
|
53
|
+
| token | string | Yes |
|
|
54
|
+
| ip | string | No |
|
|
55
|
+
| userinfo | array | No |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## getVisits()
|
|
60
|
+
|
|
61
|
+
Returns total visits for a path.
|
|
62
|
+
|
|
63
|
+
### Example
|
|
64
|
+
|
|
65
|
+
javascript import { getVisits } from "@imrankhanjoya/visit-analytics"; const totalVisits = await getVisits( "john-doe", "profile" ); console.log(totalVisits);
|
|
66
|
+
|
|
67
|
+
### Response
|
|
68
|
+
|
|
69
|
+
javascript 25
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## getVisitMembers()
|
|
74
|
+
|
|
75
|
+
Returns visitor records for a path.
|
|
76
|
+
|
|
77
|
+
### Example
|
|
78
|
+
|
|
79
|
+
javascript import { getVisitMembers } from "@imrankhanjoya/visit-analytics"; const visitors = await getVisitMembers( "john-doe", "profile" ); console.log(visitors);
|
|
80
|
+
|
|
81
|
+
### Example Response
|
|
82
|
+
|
|
83
|
+
javascript [ { token: "abc123", path: "john-doe", type: "profile", ip: "127.0.0.1", userinfo: [ { username: "imran" } ] } ]
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
# Next.js Example
|
|
88
|
+
|
|
89
|
+
## Record Visit
|
|
90
|
+
|
|
91
|
+
javascript import { saveVisit } from "@imrankhanjoya/visit-analytics"; export async function POST(request) { const body = await request.json(); await saveVisit({ path: body.path, type: body.type, token: body.token, ip: body.ip, }); return Response.json({ success: true, }); }
|
|
92
|
+
|
|
93
|
+
## Get Visit Count
|
|
94
|
+
|
|
95
|
+
javascript import { getVisits } from "@imrankhanjoya/visit-analytics"; const count = await getVisits( "john-doe", "profile" );
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
# Supported Types
|
|
100
|
+
|
|
101
|
+
javascript "profile" "post" "page" "custom"
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
# Visit Document Structure
|
|
106
|
+
|
|
107
|
+
javascript { token: "visitor-token", path: "john-doe", type: "profile", ip: "127.0.0.1", date: "2026-06-05", userinfo: [], createdAt: Date, updatedAt: Date }
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
# License
|
|
112
|
+
|
|
113
|
+
MIT
|
|
114
|
+
|
|
115
|
+
# Author
|
|
116
|
+
|
|
117
|
+
Imran Khan
|
|
118
|
+
|
|
119
|
+
Package: @imrankhanjoya/visit-analytics
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imrankhanjoya/visit-analytics",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js"
|
|
8
|
+
},
|
|
6
9
|
"scripts": {
|
|
7
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
11
|
},
|
|
9
12
|
"keywords": [],
|
|
10
13
|
"author": "",
|
|
11
14
|
"license": "ISC",
|
|
12
|
-
"type": "
|
|
15
|
+
"type": "module"
|
|
13
16
|
}
|
package/src/index.js
CHANGED
package/src/trackVisit.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import Visit from "./models/Visit.js"
|
|
3
2
|
|
|
4
3
|
export const saveVisit = async (visitData) => {
|
|
5
4
|
try {
|
|
6
|
-
const data = {token:token,ip:headersList,path:path,type:type,date:date,userinfo:[{username:username,image:image}]};
|
|
7
5
|
|
|
8
|
-
console.log("Visit saved successfully");
|
|
9
6
|
try{
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
|
|
8
|
+
const val = await Visit.create(visitData)
|
|
9
|
+
return val
|
|
12
10
|
}catch(e){
|
|
13
11
|
return e
|
|
14
12
|
}
|
|
@@ -20,9 +18,56 @@ export const saveVisit = async (visitData) => {
|
|
|
20
18
|
export const getVisits = async (path) => {
|
|
21
19
|
try {
|
|
22
20
|
const visits = await Visit.find({ path }).sort({ date: -1 });
|
|
23
|
-
return visits;
|
|
21
|
+
return {visits, count: visits.length};
|
|
24
22
|
} catch (error) {
|
|
25
23
|
console.error("Error retrieving visits:", error);
|
|
24
|
+
return {visits: [], count: 0};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export const getVisitMembers = async (path,type) => {
|
|
30
|
+
|
|
31
|
+
const data = {path:path,type:type}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
try{
|
|
37
|
+
const val = await Visit.aggregate([
|
|
38
|
+
{ $match: data },
|
|
39
|
+
{ $unwind: "$userinfo" },
|
|
40
|
+
{ $match: { "userinfo.username": { $exists: true, $ne: "" } } },
|
|
41
|
+
{ $sort: { createdAt: -1 } },
|
|
42
|
+
{ $group: {
|
|
43
|
+
_id: "$userinfo.username",
|
|
44
|
+
userinfo: { $first: "$userinfo" },
|
|
45
|
+
createdAt: { $first: "$createdAt" }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{ $project: {
|
|
49
|
+
_id: 0,
|
|
50
|
+
userinfo: 1,
|
|
51
|
+
createdAt: 1
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{ $sort: { createdAt: -1 } },
|
|
55
|
+
{ $limit: 10 }
|
|
56
|
+
]).exec();
|
|
57
|
+
|
|
58
|
+
// Add anonymous user entry with pixel art image from text
|
|
59
|
+
const anonymousImageUrl = `https://api.dicebear.com/7.x/pixel-art/svg?seed=anonymous`;
|
|
60
|
+
val.push({
|
|
61
|
+
userinfo: {
|
|
62
|
+
username: "anonymous",
|
|
63
|
+
image: anonymousImageUrl
|
|
64
|
+
},
|
|
65
|
+
createdAt: new Date()
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return val;
|
|
69
|
+
}catch(e){
|
|
26
70
|
return [];
|
|
71
|
+
|
|
27
72
|
}
|
|
28
73
|
}
|