chore: add files
This commit is contained in:
commit
9a8de0352d
8 changed files with 2283 additions and 0 deletions
36
.github/workflows/npm-publish-github-packages.yml
vendored
Normal file
36
.github/workflows/npm-publish-github-packages.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
||||
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
||||
|
||||
name: Node.js Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
publish-gpr:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: https://npm.pkg.github.com/
|
||||
- run: npm ci
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
33
.github/workflows/npm-publish.yml
vendored
Normal file
33
.github/workflows/npm-publish.yml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
||||
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
||||
|
||||
name: Node.js Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
publish-npm:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Abdullah Basheer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
216
README.md
Normal file
216
README.md
Normal file
|
@ -0,0 +1,216 @@
|
|||
# UmamiClient
|
||||
> Note: For self-hosted instances only. For Umami Cloud, consider using the official [Umami API Client](https://github.com/umami-software/api-client/).
|
||||
|
||||
> Documentation generated with the assistance of ChatGPT. Please report any inaccuracies.
|
||||
|
||||
The `UmamiClient` is a JavaScript ~class~ library designed to simplify interaction with the [Umami Analytics API](https://umami.is/docs/api). It provides methods for user authentication, website management, session analysis, event tracking, and data retrieval. This ~client~ library streamlines the process of fetching statistics, sessions, and events from a self-hosted Umami instance for use in applications or reporting dashboards. ~The class definition resides in the `umami.js` file.~
|
||||
|
||||
## [FULL DOCUMENTATION](./DOCS.md)
|
||||
|
||||
~This is not a published library; it's a standalone class intended for direct integration into projects.~ This is now a published library. It was developed to address specific needs and provide clearer documentation compared to the existing `@umami/api-client`.
|
||||
|
||||
## Table of Contents
|
||||
- [Key Features](#key-features-of-umamiclient)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Authentication](#authentication)
|
||||
- [User Management](#user-management)
|
||||
- [Team Management](#team-management)
|
||||
- [Website Management](#website-management)
|
||||
- [Session Analysis](#session-analysis)
|
||||
- [Event Tracking and Data Retrieval](#event-tracking-and-data-retrieval)
|
||||
- [Examples](#examples)
|
||||
- [Type Definitions](#type-definitions)
|
||||
|
||||
## Key Features of UmamiClient
|
||||
|
||||
### 1. Automatic Authentication and Token Management
|
||||
|
||||
- `authenticate()` initiates the login process and retrieves an authentication token.
|
||||
- `#ensureValidToken()` (private method) automatically checks token validity before each API request and refreshes it if expired, eliminating manual token management.
|
||||
|
||||
### 2. Private Helper Methods for Code Consistency
|
||||
|
||||
- Private methods like `#makeAuthenticatedRequest()` and `#formatQueryParams()` handle common tasks:
|
||||
- Making authenticated requests.
|
||||
- Injecting authorization tokens into headers.
|
||||
- Formatting query parameters for clean URL construction.
|
||||
- This abstraction ensures consistent request structure, headers, and error handling for improved robustness.
|
||||
|
||||
### 3. Modular API Endpoint Coverage
|
||||
|
||||
- `UmamiClient` provides methods for various Umami API endpoints, grouped by functionality:
|
||||
- **Authentication:** `authenticate()`, `verifyToken()`
|
||||
- **User Management:** `createUser()`, `getUsers()`, `getUser()`, `updateUser()`, `deleteUser()`, `getUserWebsites()`, `getUserTeams()`
|
||||
- **Team Management:** `createTeam()`, `getTeams()`, `joinTeam()`, `getTeam()`, `updateTeam()`, `deleteTeam()`, `getTeamUsers()`, `addUserToTeam()`, `getTeamUser()`, `updateTeamUserRole()`, `removeUserFromTeam()`, `getTeamWebsites()`
|
||||
- **Website Management:** `getWebsites()`, `createWebsite()`, `getWebsite()`, `updateWebsite()`, `deleteWebsite()`, `resetWebsite()`
|
||||
- **Session Analysis:** `getSessions()`, `getSessionStats()`, `getSession()`, `getSessionActivity()`, `getSessionProperties()`, `getSessionDataProperties()`, `getSessionDataValues()`
|
||||
- **Event Tracking:** `getEventsSeries()`, `getWebsiteEvents()`, `getWebsiteStats()`, `getEventDataEvents()`, `getEventDataFields()`, `getEventDataValues()`, `getEventDataStats()`, `getPageviews()`, `getMetrics()`, `sendEvent()` , `getActiveUsers()`
|
||||
- This modularity simplifies using the client for specific tasks.
|
||||
|
||||
|
||||
### 4. Flexible Query Parameter Handling
|
||||
|
||||
- `#formatQueryParams()` handles a wide range of query parameters, omitting undefined values for flexibility.
|
||||
- This allows precise control over filtering, pagination, and sorting without manual query string formatting.
|
||||
|
||||
### 5. Robust Error Handling
|
||||
|
||||
- `#makeAuthenticatedRequest()` and `authenticate()` include error handling, throwing descriptive errors for authentication failures or network issues to aid debugging.
|
||||
|
||||
### 6. Frontend Compatibility
|
||||
|
||||
- `sendEvent()` automatically detects frontend context (e.g., `navigator.language`, `document.referrer`) for seamless event tracking in web applications.
|
||||
|
||||
### 7. Typed Responses with JSDoc
|
||||
|
||||
- Methods return specific data structures (e.g., `Session`, `SessionStats`, `PropertyCount`) or pagination information for predictable and easy-to-use responses. These types are documented using JSDoc typedefs.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install easy-umami-js
|
||||
```
|
||||
|
||||
### Basic Setup
|
||||
|
||||
#### ES6 Import
|
||||
```javascript
|
||||
import UmamiClient from 'easy-umami-js';
|
||||
|
||||
const client = new UmamiClient({
|
||||
baseUrl: 'https://your-umami-instance.com', // Your Umami instance URL (no trailing slash)
|
||||
username: 'your-username', // superadmin username
|
||||
password: 'your-password' // superadmin password
|
||||
});
|
||||
```
|
||||
|
||||
#### CJS
|
||||
```javascript
|
||||
const UmamiClient = require('easy-umami-js');
|
||||
|
||||
const client = new UmamiClient({
|
||||
baseUrl: 'https://your-umami-instance.com', // Your Umami instance URL (no trailing slash)
|
||||
username: 'your-username', // superadmin username
|
||||
password: 'your-password' // superadmin password
|
||||
});
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
- **`authenticate()`**: Authenticates with the Umami API and stores the token.
|
||||
- **`verifyToken()`**: Verifies the current token and returns user information.
|
||||
|
||||
|
||||
## User Management
|
||||
|
||||
- **`createUser(params)`**: Creates a new user. Requires admin privileges.
|
||||
- **`getUsers()`**: Retrieves all users. Requires admin privileges.
|
||||
- **`getUser(userId)`**: Retrieves a specific user by ID.
|
||||
- **`updateUser(userId, params)`**: Updates a user's information.
|
||||
- **`deleteUser(userId)`**: Deletes a user by ID. Requires admin privileges.
|
||||
- **`getUserWebsites(userId, params)`**: Retrieves websites associated with a user.
|
||||
- **`getUserTeams(userId, params)`**: Retrieves teams associated with a user.
|
||||
|
||||
|
||||
## Team Management
|
||||
|
||||
- **`createTeam(params)`**: Creates a new team.
|
||||
- **`getTeams(params)`**: Retrieves all teams.
|
||||
- **`joinTeam(params)`**: Joins a team using an access code.
|
||||
- **`getTeam(teamId)`**: Retrieves a specific team by ID.
|
||||
- **`updateTeam(teamId, params)`**: Updates a team's information.
|
||||
- **`deleteTeam(teamId)`**: Deletes a team by ID.
|
||||
- **`getTeamUsers(teamId, params)`**: Retrieves users belonging to a team.
|
||||
- **`addUserToTeam(teamId, params)`**: Adds a user to a team.
|
||||
- **`getTeamUser(teamId, userId)`**: Retrieves details of a user within a team.
|
||||
- **`updateTeamUserRole(teamId, userId, params)`**: Updates a user's role within a team.
|
||||
- **`removeUserFromTeam(teamId, userId)`**: Removes a user from a team.
|
||||
- **`getTeamWebsites(teamId, params)`**: Retrieves websites associated with a team.
|
||||
|
||||
## Website Management
|
||||
|
||||
- **`getWebsites(params)`**: Retrieves all websites.
|
||||
- **`createWebsite(params)`**: Creates a new website.
|
||||
- **`getWebsite(websiteId)`**: Retrieves a specific website by ID.
|
||||
- **`updateWebsite(websiteId, params)`**: Updates website information.
|
||||
- **`deleteWebsite(websiteId)`**: Deletes a website by ID.
|
||||
- **`resetWebsite(websiteId)`**: Resets all data for a website.
|
||||
|
||||
|
||||
## Session Analysis
|
||||
|
||||
- **`getSessions(websiteId, params)`**: Retrieves sessions for a website within a time range.
|
||||
- **`getSessionStats(websiteId, params)`**: Retrieves summarized session statistics for a website.
|
||||
- **`getSession(websiteId, sessionId)`**: Retrieves a specific session by ID.
|
||||
- **`getSessionActivity(websiteId, sessionId, params)`**: Retrieves activity details for a session.
|
||||
- **`getSessionProperties(websiteId, sessionId)`**: Retrieves properties associated with a session.
|
||||
- **`getSessionDataProperties(websiteId, params)`**: Retrieves session data counts by property name.
|
||||
- **`getSessionDataValues(websiteId, params)`**: Retrieves session data counts for a given property.
|
||||
|
||||
|
||||
## Event Tracking and Data Retrieval
|
||||
|
||||
- **`getActiveUsers(websiteId)`**: Gets the number of active users on a website.
|
||||
- **`getEventsSeries(websiteId, params)`**: Retrieves event series data for a website.
|
||||
- **`getWebsiteEvents(websiteId, params)`**: Retrieves detailed event data for a website.
|
||||
- **`getWebsiteStats(websiteId, params)`**: Retrieves summarized website statistics.
|
||||
- **`getEventDataEvents(websiteId, params)`**: Retrieves event data summaries (names, properties, counts).
|
||||
- **`getEventDataFields(websiteId, params)`**: Retrieves event data property and value counts.
|
||||
- **`getEventDataValues(websiteId, params)`**: Retrieves event data counts for a specific event and property.
|
||||
- **`getEventDataStats(websiteId, params)`**: Retrieves summarized event data (events, fields, records).
|
||||
- **`getPageviews(websiteId, params)`**: Retrieves pageview data for a website.
|
||||
- **`getMetrics(websiteId, params)`**: Retrieves various website metrics (e.g., URLs, referrers, browsers).
|
||||
- **`sendEvent(payload)`**: Sends a custom event to Umami.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Authentication and Session Retrieval
|
||||
|
||||
```javascript
|
||||
async function getSessions() {
|
||||
try {
|
||||
const authResponse = await client.authenticate();
|
||||
console.log("Authentication successful:", authResponse);
|
||||
|
||||
const sessions = await client.getSessions('your-website-id', {
|
||||
startAt: Date.now() - 7 * 24 * 60 * 60 * 1000, // Last 7 days
|
||||
endAt: Date.now()
|
||||
});
|
||||
console.log("Sessions:", sessions);
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
getSessions();
|
||||
```
|
||||
|
||||
### Sending a Custom Event
|
||||
|
||||
```javascript
|
||||
client.sendEvent({
|
||||
website: 'your-website-id',
|
||||
name: 'product_view',
|
||||
data: { product_id: '12345' }
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Type Definitions
|
||||
|
||||
Refer to the JSDoc typedefs within the `umami.js` file for detailed information on the structure of objects like `User`, `GetTokenResponse`, `EventPayload`, `Session`, `SessionStats`, `SessionActivity`, `SessionProperty`, `PropertyCount`, and `PropertyValue`. These definitions provide clear documentation of the expected data structures for requests and responses. There's an documentation generated with jsdoc2md [here](./DOCS.md)
|
||||
|
||||
|
||||
---
|
||||
|
||||
For complete API details and query parameter options, refer to the official [Umami Analytics API Documentation](https://umami.is/docs/api).
|
||||
|
||||
## TODO to v1:
|
||||
- [ ] Test all the endpoints
|
||||
- [ ] Add [`async-retry`](https://www.npmjs.com/package/async-retry) and add a `retries` parameter to class config and individual methods.
|
||||
- [ ] Add a `timeout` parameter to class config and individual methods.
|
||||
- [ ] Allow passing the `opts` type directly to class config and individual methods.
|
19
package.json
Normal file
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "easy-umami-js",
|
||||
"version": "0.8.1",
|
||||
"main": "umami.js",
|
||||
"type": "module",
|
||||
"description": "A JavaScript client for interacting with the Umami analytics API.",
|
||||
"keywords": ["umami", "analytics", "api", "client"],
|
||||
"author": "digitaldrreamer",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
"require": "./umami.cjs.js",
|
||||
"import": "./umami.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/digitaldrreamer/easy-umami-js.git"
|
||||
},
|
||||
"homepage": "https://github.com/digitaldrreamer/easy-umami-js#readme"
|
||||
}
|
2
umami.cjs.js
Normal file
2
umami.cjs.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
const UmamiClient = require('./umami.js');
|
||||
module.exports = UmamiClient;
|
936
umami.js
Normal file
936
umami.js
Normal file
|
@ -0,0 +1,936 @@
|
|||
/**
|
||||
* @typedef {Object} User
|
||||
* @property {string} id - The user's unique identifier
|
||||
* @property {string} username - The user's username
|
||||
* @property {string} role - The user's role
|
||||
* @property {Date} createdAt - When the user was created
|
||||
* @property {boolean} isAdmin - Whether the user has admin privileges
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GetTokenResponse
|
||||
* @property {string} token - Authentication token
|
||||
* @property {User} user - User information
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EventPayload
|
||||
* @property {string} hostname - Name of host
|
||||
* @property {string} language - Language of visitor (e.g., "en-US")
|
||||
* @property {string} referrer - Referrer URL
|
||||
* @property {string} screen - Screen resolution (e.g., "1920x1080")
|
||||
* @property {string} title - Page title
|
||||
* @property {string} url - Page URL
|
||||
* @property {string} website - Website ID
|
||||
* @property {string} name - Name of the event
|
||||
* @property {Object} [data] - Optional additional data for the event
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Session
|
||||
* @property {string} id - Session ID
|
||||
* @property {string} websiteId - Website ID
|
||||
* @property {string} hostname - Hostname
|
||||
* @property {string} browser - Browser name
|
||||
* @property {string} os - Operating system
|
||||
* @property {string} device - Device type
|
||||
* @property {string} screen - Screen resolution
|
||||
* @property {string} language - Language code
|
||||
* @property {string} country - Country code
|
||||
* @property {string} subdivision1 - Region/state code
|
||||
* @property {string} city - City name
|
||||
* @property {string} firstAt - First activity timestamp
|
||||
* @property {string} lastAt - Last activity timestamp
|
||||
* @property {number} visits - Number of visits
|
||||
* @property {number} views - Number of page views
|
||||
* @property {string} createdAt - Creation timestamp
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SessionStats
|
||||
* @property {{ value: number }} pageviews - Pages hits
|
||||
* @property {{ value: number }} visitors - Number of unique visitors
|
||||
* @property {{ value: number }} visits - Number of sessions
|
||||
* @property {{ value: number }} countries - Number of unique countries
|
||||
* @property {{ value: number }} events - Number of custom events
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SessionActivity
|
||||
* @property {string} createdAt - Activity timestamp
|
||||
* @property {string} urlPath - URL path
|
||||
* @property {string} urlQuery - URL query parameters
|
||||
* @property {string} referrerDomain - Referrer domain
|
||||
* @property {string} eventId - Event ID
|
||||
* @property {number} eventType - Event type
|
||||
* @property {string} eventName - Event name
|
||||
* @property {string} visitId - Visit ID
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SessionProperty
|
||||
* @property {string} websiteId - Website ID
|
||||
* @property {string} sessionId - Session ID
|
||||
* @property {string} dataKey - Property key
|
||||
* @property {number} dataType - Data type
|
||||
* @property {string|null} stringValue - String value
|
||||
* @property {number|null} numberValue - Number value
|
||||
* @property {string|null} dateValue - Date value
|
||||
* @property {string} createdAt - Creation timestamp
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PropertyCount
|
||||
* @property {string} propertyName - Name of the property
|
||||
* @property {number} total - Total count
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PropertyValue
|
||||
* @property {string} value - Property value
|
||||
* @property {number} total - Total count
|
||||
*/
|
||||
|
||||
class UmamiClient {
|
||||
/**
|
||||
* Creates a new UmamiClient instance
|
||||
* @param {Object} config - Configuration options
|
||||
* @param {string} config.baseUrl - Base URL for the Umami API
|
||||
* @param {string} config.username - Umami username
|
||||
* @param {string} config.password - Umami password
|
||||
*/
|
||||
constructor({ baseUrl, username, password }) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.token = null;
|
||||
this.tokenExpiry = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an authenticated API request
|
||||
* @private
|
||||
* @param {string} endpoint - API endpoint
|
||||
* @param {Object} options - Fetch options
|
||||
* @returns {Promise<any>} - API response
|
||||
*/
|
||||
async #makeAuthenticatedRequest(endpoint, options = {}) {
|
||||
await this.#ensureValidToken();
|
||||
|
||||
const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
...options.headers,
|
||||
'Authorization': `Bearer ${this.token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`API request failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a valid authentication token exists, obtaining a new one if necessary
|
||||
* @private
|
||||
*/
|
||||
async #ensureValidToken() {
|
||||
const tokenLifespan = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
||||
const isTokenExpired = !this.tokenExpiry || Date.now() > this.tokenExpiry;
|
||||
|
||||
if (!this.token || isTokenExpired) {
|
||||
await this.authenticate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats query parameters for URL
|
||||
* @private
|
||||
* @param {Object} params - Query parameters
|
||||
* @returns {string} - Formatted query string
|
||||
*/
|
||||
#formatQueryParams(params) {
|
||||
return Object.entries(params)
|
||||
.filter(([_, value]) => value !== undefined)
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates with the Umami API
|
||||
* @returns {Promise<GetTokenResponse>} Authentication response
|
||||
* @throws {Error} If authentication fails
|
||||
*/
|
||||
async authenticate() {
|
||||
const response = await fetch(`${this.baseUrl}/api/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: this.username,
|
||||
password: this.password,
|
||||
}),
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
throw new Error('Authentication failed: Incorrect username or password');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Authentication failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data)
|
||||
this.token = data.token;
|
||||
this.tokenExpiry = Date.now() + (24 * 60 * 60 * 1000); // Set expiry to 24 hours from now
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the current authentication token
|
||||
* @returns {Promise<User>} User information if token is valid
|
||||
*/
|
||||
async verifyToken() {
|
||||
return this.#makeAuthenticatedRequest('/api/auth/verify');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new user.
|
||||
* @param {Object} params - Parameters for creating a user.
|
||||
* @param {string} params.username - The user's username.
|
||||
* @param {string} params.password - The user's password.
|
||||
* @param {string} params.role - The user's role, either 'admin' or 'user'.
|
||||
* @returns {Promise<{ id: string, username: string, role: string, createdAt: string }>} Created user details.
|
||||
*/
|
||||
async createUser(params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/users`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all users. Admin access is required.
|
||||
* @returns {Promise<Array<{ id: string, username: string, role: string, createdAt: string }>>} List of users.
|
||||
*/
|
||||
async getUsers() {
|
||||
return this.#makeAuthenticatedRequest(`/api/admin/users`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details of a specific user by ID.
|
||||
* @param {string} userId - The ID of the user.
|
||||
* @returns {Promise<{ id: string, username: string, role: string }>} User details.
|
||||
*/
|
||||
async getUser(userId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/users/${userId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates details of a user.
|
||||
* @param {string} userId - The ID of the user.
|
||||
* @param {Object} params - Update parameters.
|
||||
* @param {string} [params.username] - The user's new username (optional).
|
||||
* @param {string} [params.password] - The user's new password (optional).
|
||||
* @param {string} [params.role] - The user's role, either 'admin' or 'user' (optional).
|
||||
* @returns {Promise<{ id: string, username: string, role: string, createdAt: string }>} Updated user details.
|
||||
*/
|
||||
async updateUser(userId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/users/${userId}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user.
|
||||
* @param {string} userId - The ID of the user.
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async deleteUser(userId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all websites that belong to a user.
|
||||
* @param {string} userId - The ID of the user.
|
||||
* @param {Object} [params] - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array<{ id: string, userId: string, domain: string, name: string, shareId: string | null, createdAt: string, updatedAt: string | null, deletedAt: string | null, resetAt: string | null }>>} List of websites belonging to the user.
|
||||
*/
|
||||
async getUserWebsites(userId, params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/users/${userId}/websites?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all teams that belong to a user.
|
||||
* @param {string} userId - The ID of the user.
|
||||
* @param {Object} [params] - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array<{ id: string, name: string, createdAt: string, updatedAt: string | null, deletedAt: string | null }>>} List of teams belonging to the user.
|
||||
*/
|
||||
async getUserTeams(userId, params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/users/${userId}/teams?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new team.
|
||||
* @param {Object} params - Parameters for creating a team.
|
||||
* @param {string} params.name - The team's name.
|
||||
* @returns {Promise<{ accessCode: string, createdAt: string, id: string, name: string, updatedAt: string | null }>} Created team details.
|
||||
*/
|
||||
async createTeam(params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all teams.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array>} List of all teams with team user information.
|
||||
*/
|
||||
async getTeams(params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/teams?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a team using an access code.
|
||||
* @param {Object} params - Parameters for joining a team.
|
||||
* @param {string} params.accessCode - The team's access code.
|
||||
* @returns {Promise<Object>} Joined team details.
|
||||
*/
|
||||
async joinTeam(params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/join`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details of a specific team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @returns {Promise<Object>} Team details.
|
||||
*/
|
||||
async getTeam(teamId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates team details.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {Object} params - Update parameters.
|
||||
* @param {string} [params.name] - The team's name (optional).
|
||||
* @param {string} [params.accessCode] - The team's access code (optional).
|
||||
* @returns {Promise<Object>} Updated team details.
|
||||
*/
|
||||
async updateTeam(teamId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async deleteTeam(teamId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all users that belong to a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {Object} [params] - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array>} List of team users.
|
||||
*/
|
||||
async getTeamUsers(teamId, params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/users?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a user to a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {Object} params - Parameters for adding a user to the team.
|
||||
* @param {string} params.userId - The user's ID.
|
||||
* @param {string} params.role - The role to assign (e.g., 'member' or 'view-only').
|
||||
* @returns {Promise<Object>} Added team user details.
|
||||
*/
|
||||
async addUserToTeam(teamId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/users`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details of a user in a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {string} userId - The user's ID.
|
||||
* @returns {Promise<Object>} Team user details.
|
||||
*/
|
||||
async getTeamUser(teamId, userId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/users/${userId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a user's role in a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {string} userId - The user's ID.
|
||||
* @param {Object} params - Parameters for updating user role.
|
||||
* @param {string} params.role - The new role (e.g., 'member' or 'view-only').
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async updateTeamUserRole(teamId, userId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/users/${userId}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user from a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {string} userId - The user's ID.
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async removeUserFromTeam(teamId, userId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all tracked websites.
|
||||
* @param {Object} [params] - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array<{ id: string, name: string, domain: string, shareId: string | null, resetAt: string | null, createdAt: string, updatedAt: string | null, deletedAt: string | null }>>} List of websites.
|
||||
*/
|
||||
async getWebsites(params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new website.
|
||||
* @param {Object} params - Website parameters.
|
||||
* @param {string} params.domain - The full domain of the tracked website.
|
||||
* @param {string} params.name - The name of the website in Umami.
|
||||
* @param {string} [params.shareId] - A unique string to enable a share URL (optional).
|
||||
* @param {string} [params.teamId] - The ID of the team the website will be created under (optional).
|
||||
* @returns {Promise<{ id: number, websiteUuid: string, websiteId: number, name: string, domain: string, shareId: string | null, createdAt: string }>} Details of the created website.
|
||||
*/
|
||||
async createWebsite(params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details of a specific website by ID.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @returns {Promise<{ id: string, name: string, domain: string, shareId: string | null, resetAt: string | null, userId: string, createdAt: string, updatedAt: string | null, deletedAt: string | null }>} Website details.
|
||||
*/
|
||||
async getWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates details of a website.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Update parameters.
|
||||
* @param {string} [params.name] - The name of the website in Umami (optional).
|
||||
* @param {string} [params.domain] - The full domain of the tracked website (optional).
|
||||
* @param {string} [params.shareId] - A unique string to enable a share URL or null to unshare (optional).
|
||||
* @returns {Promise<{ id: string, name: string, domain: string, shareId: string | null, resetAt: string | null, userId: string, createdAt: string, updatedAt: string | null, deletedAt: string | null }>} Updated website details.
|
||||
*/
|
||||
async updateWebsite(websiteId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a website.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async deleteWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a website by removing all data related to it.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @returns {Promise<string>} Confirmation message.
|
||||
*/
|
||||
async resetWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/reset`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all websites that belong to a team.
|
||||
* @param {string} teamId - The ID of the team.
|
||||
* @param {Object} [params] - Query parameters.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results per page (optional).
|
||||
* @param {string} [params.orderBy='name'] - Order by column name (optional).
|
||||
* @returns {Promise<Array>} List of team websites.
|
||||
*/
|
||||
async getTeamWebsites(teamId, params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/teams/${teamId}/websites?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets website session details within a given time range
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} [params.query] - Search text
|
||||
* @param {number} [params.page=1] - Page number
|
||||
* @param {number} [params.pageSize] - Results per page
|
||||
* @param {string} [params.orderBy] - Order by column name
|
||||
* @returns {Promise<{ data: Session[], count: number, page: number, pageSize: number }>}
|
||||
*/
|
||||
async getSessions(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/sessions?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets summarized website session statistics
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} [params.url] - Filter by URL
|
||||
* @param {string} [params.referrer] - Filter by referrer
|
||||
* @param {string} [params.title] - Filter by page title
|
||||
* @param {string} [params.query] - Filter by query
|
||||
* @param {string} [params.event] - Filter by event name
|
||||
* @param {string} [params.host] - Filter by hostname
|
||||
* @param {string} [params.os] - Filter by operating system
|
||||
* @param {string} [params.browser] - Filter by browser
|
||||
* @param {string} [params.device] - Filter by device
|
||||
* @param {string} [params.country] - Filter by country
|
||||
* @param {string} [params.region] - Filter by region
|
||||
* @param {string} [params.city] - Filter by city
|
||||
* @returns {Promise<SessionStats>}
|
||||
*/
|
||||
async getSessionStats(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/sessions/stats?${queryString}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets session details for an individual session
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {string} sessionId - Session ID
|
||||
* @returns {Promise<Session>}
|
||||
*/
|
||||
async getSession(websiteId, sessionId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/sessions/${sessionId}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets session activity for an individual session
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {string} sessionId - Session ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @returns {Promise<SessionActivity[]>}
|
||||
*/
|
||||
async getSessionActivity(websiteId, sessionId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/sessions/${sessionId}/activity?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets session properties for an individual session
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {string} sessionId - Session ID
|
||||
* @returns {Promise<SessionProperty[]>}
|
||||
*/
|
||||
async getSessionProperties(websiteId, sessionId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/sessions/${sessionId}/properties`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets session data counts by property name
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @returns {Promise<PropertyCount[]>}
|
||||
*/
|
||||
async getSessionDataProperties(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/session-data/properties?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets session data counts for a given property
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} params.propertyName - Property name
|
||||
* @returns {Promise<PropertyValue[]>}
|
||||
*/
|
||||
async getSessionDataValues(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/session-data/values?${queryString}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all tracked websites
|
||||
* @param {Object} [params] - Query parameters
|
||||
* @param {string} [params.query] - Search text
|
||||
* @param {number} [params.page=1] - Page number
|
||||
* @param {number} [params.pageSize] - Results per page
|
||||
* @param {string} [params.orderBy='name'] - Order by column name
|
||||
* @returns {Promise<Array>} List of websites
|
||||
*/
|
||||
async getWebsites(params = {}) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new website
|
||||
* @param {Object} params - Website parameters
|
||||
* @param {string} params.domain - The full domain of the tracked website
|
||||
* @param {string} params.name - The name of the website in Umami
|
||||
* @param {string} [params.shareId] - A unique string to enable a share url
|
||||
* @param {string} [params.teamId] - The ID of the team the website will be created under
|
||||
* @returns {Promise<Object>} Created website details
|
||||
*/
|
||||
async createWebsite(params) {
|
||||
return this.#makeAuthenticatedRequest('/api/websites', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a website by ID
|
||||
* @param {string} websiteId - Website ID
|
||||
* @returns {Promise<Object>} Website details
|
||||
*/
|
||||
async getWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a website
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Update parameters
|
||||
* @param {string} [params.name] - The name of the website in Umami
|
||||
* @param {string} [params.domain] - The full domain of the tracked website
|
||||
* @param {string} [params.shareId] - A unique string to enable a share url
|
||||
* @returns {Promise<Object>} Updated website details
|
||||
*/
|
||||
async updateWebsite(websiteId, params) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a website
|
||||
* @param {string} websiteId - Website ID
|
||||
* @returns {Promise<string>} Confirmation message
|
||||
*/
|
||||
async deleteWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a website by removing all data
|
||||
* @param {string} websiteId - Website ID
|
||||
* @returns {Promise<string>} Confirmation message
|
||||
*/
|
||||
async resetWebsite(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/reset`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of active users on a website
|
||||
* @param {string} websiteId - Website ID
|
||||
* @returns {Promise<Object>} Active users count
|
||||
*/
|
||||
async getActiveUsers(websiteId) {
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/active`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets events within a given time range
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} params.unit - Time unit (year | month | hour | day)
|
||||
* @param {string} params.timezone - Timezone (ex. America/Los_Angeles)
|
||||
* @param {string} [params.url] - Filter by URL
|
||||
* @param {string} [params.referrer] - Filter by referrer
|
||||
* @param {string} [params.title] - Filter by page title
|
||||
* @param {string} [params.host] - Filter by hostname
|
||||
* @param {string} [params.os] - Filter by operating system
|
||||
* @param {string} [params.browser] - Filter by browser
|
||||
* @param {string} [params.device] - Filter by device
|
||||
* @param {string} [params.country] - Filter by country
|
||||
* @param {string} [params.region] - Filter by region
|
||||
* @param {string} [params.city] - Filter by city
|
||||
* @returns {Promise<Array>} Event series data
|
||||
*/
|
||||
async getEventsSeries(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/events/series?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets website event details within a given time range.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of the starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of the end date.
|
||||
* @param {string} [params.query] - Search text (optional).
|
||||
* @param {number} [params.page=1] - Page number (optional).
|
||||
* @param {number} [params.pageSize] - Number of results to return (optional).
|
||||
* @param {string} [params.orderBy] - Order by column name (optional).
|
||||
* @returns {Promise<{ data: Array, count: number, page: number, pageSize: number }>} Event data response.
|
||||
*/
|
||||
async getWebsiteEvents(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/events?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets summarized website statistics.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date.
|
||||
* @param {string} [params.url] - Filter by URL (optional).
|
||||
* @param {string} [params.referrer] - Filter by referrer (optional).
|
||||
* @param {string} [params.title] - Filter by page title (optional).
|
||||
* @param {string} [params.query] - Filter by query (optional).
|
||||
* @param {string} [params.event] - Filter by event name (optional).
|
||||
* @param {string} [params.host] - Filter by hostname (optional).
|
||||
* @param {string} [params.os] - Filter by operating system (optional).
|
||||
* @param {string} [params.browser] - Filter by browser (optional).
|
||||
* @param {string} [params.device] - Filter by device (e.g., Mobile, optional).
|
||||
* @param {string} [params.country] - Filter by country (optional).
|
||||
* @param {string} [params.region] - Filter by region/state/province (optional).
|
||||
* @param {string} [params.city] - Filter by city (optional).
|
||||
* @returns {Promise<{ pageviews: { value: number, prev: number }, visitors: { value: number, prev: number }, visits: { value: number, prev: number }, bounces: { value: number, prev: number }, totaltime: { value: number, prev: number } }>} Summarized website statistics.
|
||||
*/
|
||||
async getWebsiteStats(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/stats?${queryString}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets event data names, properties, and counts.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of the starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of the end date.
|
||||
* @param {string} [params.event] - Event name filter (optional).
|
||||
* @returns {Promise<Array<{ eventName: string, propertyName: string, dataType: number, total: number }>>} Event data summary.
|
||||
*/
|
||||
async getEventDataEvents(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/event-data/events?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets event data property and value counts within a given time range.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of the starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of the end date.
|
||||
* @returns {Promise<Array<{ propertyName: string, dataType: number, value: string, total: number }>>} Event data fields.
|
||||
*/
|
||||
async getEventDataFields(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/event-data/fields?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets event data counts for a given event and property.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of the starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of the end date.
|
||||
* @param {string} params.eventName - The name of the event.
|
||||
* @param {string} params.propertyName - The property name.
|
||||
* @returns {Promise<Array<{ value: string, total: number }>>} Event data values.
|
||||
*/
|
||||
async getEventDataValues(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/event-data/values?${queryString}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets summarized website events, fields, and records within a given time range.
|
||||
* @param {string} websiteId - The ID of the website.
|
||||
* @param {Object} params - Query parameters.
|
||||
* @param {number} params.startAt - Timestamp (in ms) of the starting date.
|
||||
* @param {number} params.endAt - Timestamp (in ms) of the end date.
|
||||
* @returns {Promise<Array<{ events: number, fields: number, records: number }>>} Summary of events, fields, and records.
|
||||
*/
|
||||
async getEventDataStats(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/event-data/stats?${queryString}`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets pageviews within a given time range
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} params.unit - Time unit (year | month | hour | day)
|
||||
* @param {string} params.timezone - Timezone (ex. America/Los_Angeles)
|
||||
* @param {string} [params.url] - Filter by URL
|
||||
* @param {string} [params.referrer] - Filter by referrer
|
||||
* @param {string} [params.title] - Filter by page title
|
||||
* @param {string} [params.host] - Filter by hostname
|
||||
* @param {string} [params.os] - Filter by operating system
|
||||
* @param {string} [params.browser] - Filter by browser
|
||||
* @param {string} [params.device] - Filter by device
|
||||
* @param {string} [params.country] - Filter by country
|
||||
* @param {string} [params.region] - Filter by region
|
||||
* @param {string} [params.city] - Filter by city
|
||||
* @returns {Promise<Object>} Pageview data
|
||||
*/
|
||||
async getPageviews(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/pageviews?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets metrics for a given time range
|
||||
* @param {string} websiteId - Website ID
|
||||
* @param {Object} params - Query parameters
|
||||
* @param {number} params.startAt - Timestamp (in ms) of starting date
|
||||
* @param {number} params.endAt - Timestamp (in ms) of end date
|
||||
* @param {string} params.type - Metrics type (url | referrer | browser | os | device | country | event)
|
||||
* @param {string} [params.url] - Filter by URL
|
||||
* @param {string} [params.referrer] - Filter by referrer
|
||||
* @param {string} [params.title] - Filter by page title
|
||||
* @param {string} [params.query] - Filter by query
|
||||
* @param {string} [params.host] - Filter by hostname
|
||||
* @param {string} [params.os] - Filter by operating system
|
||||
* @param {string} [params.browser] - Filter by browser
|
||||
* @param {string} [params.device] - Filter by device
|
||||
* @param {string} [params.country] - Filter by country
|
||||
* @param {string} [params.region] - Filter by region
|
||||
* @param {string} [params.city] - Filter by city
|
||||
* @param {string} [params.language] - Filter by language
|
||||
* @param {string} [params.event] - Filter by event
|
||||
* @param {number} [params.limit=500] - Number of events returned
|
||||
* @returns {Promise<Array>} Metrics data
|
||||
*/
|
||||
async getMetrics(websiteId, params) {
|
||||
const queryString = this.#formatQueryParams(params);
|
||||
return this.#makeAuthenticatedRequest(`/api/websites/${websiteId}/metrics?${queryString}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an event to Umami
|
||||
* @param {EventPayload} payload - Event data
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async sendEvent(payload) {
|
||||
// No authentication needed for /api/send
|
||||
const response = await fetch(`${this.baseUrl}/api/send`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': navigator.userAgent, // Required for event registration
|
||||
},
|
||||
body: JSON.stringify({
|
||||
payload: {
|
||||
hostname: payload.hostname || window.location.hostname,
|
||||
language: payload.language || navigator.language,
|
||||
referrer: payload.referrer || document.referrer,
|
||||
screen: payload.screen || `${window.screen.width}x${window.screen.height}`,
|
||||
title: payload.title || document.title,
|
||||
url: payload.url || window.location.pathname,
|
||||
website: payload.website,
|
||||
name: payload.name,
|
||||
data: payload.data,
|
||||
},
|
||||
type: 'event',
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to send event: ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UmamiClient;
|
Loading…
Reference in a new issue