mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-09-27 03:57:07 +02:00
update analytics
This commit is contained in:
@@ -29,8 +29,11 @@ SEND_EMAILS_IN_DEVELOPMENT=true
|
||||
# (OPTIONAL) get your openai api key at https://platform.openai.com/account
|
||||
OPENAI_API_KEY=
|
||||
|
||||
# (OPTIONAL) get your plausible api key at https://plausible.io/login
|
||||
# (OPTIONAL) get your plausible api key at https://plausible.io/login or https://your-plausible-instance.com/login
|
||||
PLAUSIBLE_API_KEY=
|
||||
# You will find your site id in the Plausible dashboard. It will look like 'opensaas.sh'
|
||||
PLAUSIBLE_SITE_ID=
|
||||
PLAUSIBLE_BASE_URL=https://plausible.io/api/v1 # if you are self-hosting plausible, change this to your plausible instance's base url
|
||||
|
||||
# (OPTIONAL) get your google service account key at https://console.cloud.google.com/iam-admin/serviceaccounts
|
||||
GOOGLE_ANALYTICS_CLIENT_EMAIL=
|
||||
|
13
main.wasp
13
main.wasp
@@ -13,10 +13,10 @@ app SaaSTemplate {
|
||||
"<meta name='twitter:image:height' content='400' />",
|
||||
"<meta name='twitter:card' content='summary_large_image' />",
|
||||
// you can put your analytics scripts here
|
||||
"<script defer data-domain='localhost' src='https://plausible.apps.twoducks.dev/js/script.js'></script>",
|
||||
// plausible has script extension `script.local.js` for local development
|
||||
"<script defer data-domain='localhost' src='https://plausible.apps.twoducks.dev/js/script.local.js'></script>",
|
||||
// google analytics automatically detects if you are in dev mode and
|
||||
"<script defer data-domain='opensaas.sh' src='https://plausible.apps.twoducks.dev/js/script.js'></script>",
|
||||
// plausible has script extension `script.local.js` for local development TODO: remove before deploying
|
||||
"<script defer data-domain='opensaas.sh' src='https://plausible.apps.twoducks.dev/js/script.local.js'></script>",
|
||||
// google analytics only needs one script and will automatically detect if you are in dev mode
|
||||
"<!-- Google tag (gtag.js) --><script async src='https://www.googletagmanager.com/gtag/js?id=G-H3LSJCK95H'></script><script>window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'G-H3LSJCK95H');</script>"
|
||||
],
|
||||
// 🔐 Auth out of the box! https://wasp-lang.dev/docs/auth/overview
|
||||
@@ -355,9 +355,8 @@ job dailyStatsJob {
|
||||
fn: import { calculateDailyStats } from "@server/workers/calculateDailyStats.js"
|
||||
},
|
||||
schedule: {
|
||||
// every hour
|
||||
// cron: "0 * * * *"
|
||||
cron: "* * * * *"
|
||||
// cron: "0 * * * *" // every hour. use in production
|
||||
cron: "* * * * *" // every minute. useful for debugging
|
||||
},
|
||||
entities: [User, DailyStats, Logs, PageViewSource]
|
||||
}
|
||||
|
@@ -41,8 +41,6 @@ export const getDailyStats: GetDailyStats<void, DailyStatsValues> = async (_args
|
||||
},
|
||||
});
|
||||
|
||||
console.log('dailyStats: ', dailyStats)
|
||||
|
||||
const weeklyStats = await context.entities.DailyStats.findMany({
|
||||
orderBy: {
|
||||
date: 'desc',
|
||||
|
@@ -1,25 +1,23 @@
|
||||
import { BetaAnalyticsDataClient } from '@google-analytics/data';
|
||||
|
||||
const clientEmail = process.env.GOOGLE_ANALYTICS_CLIENT_EMAIL;
|
||||
// const privateKey =
|
||||
// '-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0pLaSKNIJ4Lio\nTunlGK0T5a228onb8zrpF/i4TMlkHoRwtJFIj19Hvj6RiGRkNCP62x1AfFwiUVzd\nV8BuagsN+BwaxvW/gZS7JeDdB7W5G5w9wTmY75gWpVy034lUoTK1Oe+mpA1m9UG7\nXv/0iUcz88vubZWXDOlnYYm2EIVboONuKwJglaVzgvlNMkpZQHzomOwmCIs/6Ujr\ntOWL3ESUKgLSmLwv/NRwAYCa3DMQ3uYwKQT73ZlHgX8R4cqmvP2AwQIeBlM4pq4S\nhUsDPpFhHEbTBww4uLXaUETW8j26tAZKYq17NjoUnMx0eRW2kkEuOz9l8D/4297D\n9ARjpWRJAgMBAAECggEAAhE4fae176MAufxdNN/5axbfzA4ugbPg4rYBhKpsS5cF\n0PxgBUKOxpVoxeWXsIXgO4iyZwCFVWc09tuAOkNAaSKDv9KzEUP8Xb/rONxTuhCU\n0ygY7qUfSnMOAovkWHGX0PcexPtvo9P+spQ9vaCsje2mUc4zPg1JxoMZPlomDIxf\n38wPtTThJCwHc7uOg0BAof3vjF+zC6Vf1YYLiqlNhAC9E6aS8Np8CVXtpxRsJifn\nb5E6jBESK9PjrtPFdUtRcm7j2vohmLqCy+6ddwjwlCSxcpIky1QVlXNxmH/qkvKA\nK8vrLJlXeGuOb3ISsRrHSfY5J8fnFtol0Rec5Bag4QKBgQDjzl0xO6PnfuGRWs/d\nVfrZuuRmQvFx7kj9D04sC4NVwWuYFauh7RWt8nJwgbRdR3lHqTQ7JlUe4627y1PW\nOzffrbMY0Q3DiwLXj+mYbt2cfrHGqPxGYjeKJCMIvbHOzQ7NBacjtw/AflxsDqKx\n2Wzu//j0QISv2uH/zNESlsd2HQKBgQDLABT7uDMoxn4JIzEwqZTdzfASaSZQ1ppU\nbdm7Tug7hNVCU+orhgAa8k6ODCjH75uwdPrkstjzmQ303Zwxfw1llt1X8CICEqNR\nPS1Ptl+5H2wBcH8K96fFeGLO5CuWOmt/e1C19n3VJULQsh9jdj5yA2rfSI7DvfsC\nCnIjvKWfHQKBgQDR2WDJoIn9D0mVD5WZ68E33szVUud9rya3TukQ884ZKiMGJzhC\n4tZstYEsGJ9gqh2ToM/HiSkyWkPJUaU6HLT8rNLlknZeYmjMz/o8fCxTI/Z57WLv\nJzzIWT+Ypr3rpcPzozhzUwgEp6JVvCmtMYACrfPUdLaGFFjJvg/+Ur0NFQKBgGQ0\nMCdo72frQv+DrZ5VtzQdmamc2dsBc8DFULrS4nOuyA4rmeXOCXNDtF8NxXub3QAn\nXklRtyHXpTn/wj/0dUp2Q+BKmp7nUFKjniBA59NbnVbAjxV81gX1vOBfZNyNDc8p\nsdeASvDRqb+WjUPtdDmXUkPRbxdUSfjh6yGU1zRJAoGBALfUrbxg8t827HMa+xLH\nMvaBHqdQ6jhdjm51sOUfRBe2EOKQWug/Dnr+XlQKWN467JCWmKS0HfQY16BLIusQ\nUUc2dD+7jFTgtkvnSHvrbj+WX1Zl4tvkawxozu04Me83Fx2eYbxf0Ds5D4HiB04j\nn6O2YEStTVYy4ViSPGxTYKEI\n-----END PRIVATE KEY-----\n';
|
||||
const privateKey = Buffer.from(process.env.GOOGLE_ANALYTICS_PRIVATE_KEY!, 'base64').toString('utf-8');
|
||||
const CLIENT_EMAIL = process.env.GOOGLE_ANALYTICS_CLIENT_EMAIL;
|
||||
const PRIVATE_KEY = Buffer.from(process.env.GOOGLE_ANALYTICS_PRIVATE_KEY!, 'base64').toString('utf-8');
|
||||
|
||||
const propertyId = process.env.GOOGLE_ANALYTICS_PROPERTY_ID;
|
||||
const PROPERTY_ID = process.env.GOOGLE_ANALYTICS_PROPERTY_ID;
|
||||
|
||||
const analyticsDataClient = new BetaAnalyticsDataClient({
|
||||
credentials: {
|
||||
client_email: clientEmail,
|
||||
private_key: privateKey,
|
||||
client_email: CLIENT_EMAIL,
|
||||
private_key: PRIVATE_KEY,
|
||||
},
|
||||
});
|
||||
|
||||
export async function getSources() {
|
||||
const [response] = await analyticsDataClient.runReport({
|
||||
property: `properties/${propertyId}`,
|
||||
property: `properties/${PROPERTY_ID}`,
|
||||
dateRanges: [
|
||||
{
|
||||
startDate: 'yesterday',
|
||||
startDate: '2020-01-01',
|
||||
endDate: 'today',
|
||||
},
|
||||
],
|
||||
@@ -27,7 +25,7 @@ export async function getSources() {
|
||||
// get total page views
|
||||
dimensions: [
|
||||
{
|
||||
name: 'pageReferrer',
|
||||
name: 'source',
|
||||
},
|
||||
],
|
||||
metrics: [
|
||||
@@ -39,6 +37,7 @@ export async function getSources() {
|
||||
|
||||
let activeUsersPerReferrer: any[] = [];
|
||||
if (response?.rows) {
|
||||
console.log('response.rows (sources): ', response.rows)
|
||||
activeUsersPerReferrer = response.rows.map((row) => {
|
||||
if (row.dimensionValues && row.metricValues) {
|
||||
return {
|
||||
@@ -66,7 +65,7 @@ export async function getDailyPageViews() {
|
||||
|
||||
async function getTotalPageViews() {
|
||||
const [response] = await analyticsDataClient.runReport({
|
||||
property: `properties/${propertyId}`,
|
||||
property: `properties/${PROPERTY_ID}`,
|
||||
dateRanges: [
|
||||
{
|
||||
startDate: '2020-01-01', // go back to earliest date of your app
|
||||
@@ -91,7 +90,7 @@ async function getTotalPageViews() {
|
||||
|
||||
async function getPrevDayViewsChangePercent() {
|
||||
const [response] = await analyticsDataClient.runReport({
|
||||
property: `properties/${propertyId}`,
|
||||
property: `properties/${PROPERTY_ID}`,
|
||||
|
||||
dateRanges: [
|
||||
{
|
||||
@@ -120,7 +119,7 @@ async function getPrevDayViewsChangePercent() {
|
||||
],
|
||||
});
|
||||
|
||||
console.log('response: ', JSON.stringify(response?.rows, null, 2));
|
||||
// console.log('response: ', JSON.stringify(response?.rows, null, 2));
|
||||
let viewsFromYesterday;
|
||||
let viewsFromDayBeforeYesterday;
|
||||
|
||||
@@ -140,7 +139,7 @@ async function getPrevDayViewsChangePercent() {
|
||||
console.table({ viewsFromYesterday, viewsFromDayBeforeYesterday });
|
||||
|
||||
const change = ((viewsFromYesterday - viewsFromDayBeforeYesterday) / viewsFromDayBeforeYesterday) * 100;
|
||||
return change.toFixed(2);
|
||||
return change.toFixed(0);
|
||||
}
|
||||
} else {
|
||||
return '0';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const PLAUSIBLE_API_KEY = process.env.PLAUSIBLE_API_KEY!; // Replace with your Plausible API key
|
||||
const PLAUSIBLE_SITE_ID = 'localhost'; // Replace with your registered site ID with Plausible
|
||||
const PLAUSIBLE_BASE_URL = 'https://plausible.apps.twoducks.dev/api'; // This is a self-hosted Plausible instance. Replace with your own, or the cloud-based Plausible base URL (e.g. https://plausible.io/api)
|
||||
const PLAUSIBLE_API_KEY = process.env.PLAUSIBLE_API_KEY!;
|
||||
const PLAUSIBLE_SITE_ID = process.env.PLAUSIBLE_SITE_ID!;
|
||||
const PLAUSIBLE_BASE_URL = process.env.PLAUSIBLE_BASE_URL;
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -74,7 +74,7 @@ async function getPrevDayViewsChangePercent() {
|
||||
} else {
|
||||
change = ((pageViewsYesterday - pageViewsDayBeforeYesterday) / pageViewsDayBeforeYesterday) * 100;
|
||||
}
|
||||
return change.toFixed(2);
|
||||
return change.toFixed(0);
|
||||
}
|
||||
|
||||
async function getPageviewsForDate(date: string) {
|
||||
|
@@ -7,7 +7,7 @@ export enum TierIds {
|
||||
//get this link at https://dashboard.stripe.com/test/settings/billing/portal
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
const customerPortalTestUrl = 'https://billing.stripe.com/p/login/test_8wM8x17JN7DT4zC000';
|
||||
const customerPortalProdUrl = undefined;
|
||||
const customerPortalProdUrl = undefined; // TODO: add before deploying to production
|
||||
|
||||
export const STRIPE_CUSTOMER_PORTAL_LINK = isDev ? customerPortalTestUrl : customerPortalProdUrl;
|
||||
|
||||
|
Reference in New Issue
Block a user