CLASSROOMIO-T-216: Capture posthog events
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import posthog from 'posthog-js';
|
||||
import { goto } from '$app/navigation';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { capturePosthogEvent } from '$lib/utils/services/posthog';
|
||||
|
||||
async function logout() {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
console.error('Error logging out: ', error);
|
||||
|
||||
capturePosthogEvent('user_logged_out');
|
||||
posthog.reset();
|
||||
goto('/login');
|
||||
}
|
||||
</script>
|
||||
|
||||
<PrimaryButton variant={VARIANTS.OUTLINED} label="Log out" onClick={logout} />
|
||||
@@ -11,6 +11,7 @@
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { currentOrg } from '$lib/utils/store/org';
|
||||
import { goto } from '$app/navigation';
|
||||
import { capturePosthogEvent } from '$lib/utils/services/posthog';
|
||||
|
||||
let isLoading = false;
|
||||
let errors = {
|
||||
@@ -31,7 +32,7 @@
|
||||
}));
|
||||
}
|
||||
|
||||
async function createCourse(e) {
|
||||
async function createCourse() {
|
||||
isLoading = true;
|
||||
const { hasError, fieldErrors } = validateForm($createCourseModal);
|
||||
|
||||
@@ -46,6 +47,9 @@
|
||||
.select();
|
||||
|
||||
console.log(`newGroup`, newGroup);
|
||||
|
||||
if (!newGroup) return;
|
||||
|
||||
const { id: group_id } = newGroup[0];
|
||||
|
||||
// Set userPrompt to the description
|
||||
@@ -62,11 +66,21 @@
|
||||
.select();
|
||||
console.log(`newCourse`, newCourse);
|
||||
|
||||
if (!newCourse) return;
|
||||
|
||||
courses.update((_courses) => [..._courses, newCourse[0]]);
|
||||
|
||||
// 3. Add group members
|
||||
capturePosthogEvent('course_created', {
|
||||
course_id: newCourse[0]?.id,
|
||||
course_title: newCourse[0]?.title,
|
||||
course_description: newCourse[0]?.description,
|
||||
organization_id: $currentOrg.id,
|
||||
organization_name: $currentOrg.name,
|
||||
user_id: $profile.id,
|
||||
user_email: $profile.email
|
||||
});
|
||||
|
||||
// Get profile of author and add as member
|
||||
// 3. Add group members
|
||||
await addGroupMember({
|
||||
profile_id: $profile.id,
|
||||
email: $profile.email,
|
||||
@@ -105,8 +119,7 @@
|
||||
<TextArea
|
||||
label="Short description"
|
||||
bind:value={$createCourseModal.description}
|
||||
rows="4"
|
||||
maxRows="4"
|
||||
rows={4}
|
||||
placeholder="A little description about this course"
|
||||
className="mb-4"
|
||||
isRequired={true}
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { Grid, Row, Column } from 'carbon-components-svelte';
|
||||
import TextField from '$lib/components/Form/TextField.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
import UploadImage from '$lib/components/UploadImage/index.svelte';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { snackbar } from '$lib/components/Snackbar/store';
|
||||
import LogoutButton from '$lib/components/Buttons/Logout/index.svelte';
|
||||
|
||||
let avatar;
|
||||
let avatar = '';
|
||||
let loading = false;
|
||||
|
||||
async function logout() {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
goto('/login');
|
||||
}
|
||||
|
||||
async function handleUpdate() {
|
||||
try {
|
||||
loading = true;
|
||||
@@ -92,6 +86,6 @@
|
||||
isDisabled={loading}
|
||||
onClick={handleUpdate}
|
||||
/>
|
||||
<PrimaryButton variant={VARIANTS.OUTLINED} label="Log out" onClick={logout} />
|
||||
<LogoutButton />
|
||||
</Row>
|
||||
</Grid>
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { Grid, Row, Column } from 'carbon-components-svelte';
|
||||
import TextField from '$lib/components/Form/TextField.svelte';
|
||||
import SectionTitle from '../SectionTitle.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
import UploadImage from '$lib/components/UploadImage/index.svelte';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { snackbar } from '$lib/components/Snackbar/store';
|
||||
import LogoutButton from '$lib/components/Buttons/Logout/index.svelte';
|
||||
|
||||
let avatar;
|
||||
let avatar = '';
|
||||
let loading = false;
|
||||
|
||||
async function logout() {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
console.log('error logout', error);
|
||||
goto('/login');
|
||||
}
|
||||
|
||||
async function handleUpdate() {
|
||||
try {
|
||||
loading = true;
|
||||
@@ -94,6 +87,6 @@
|
||||
isDisabled={loading}
|
||||
onClick={handleUpdate}
|
||||
/>
|
||||
<PrimaryButton variant={VARIANTS.OUTLINED} label="Log out" onClick={logout} />
|
||||
<LogoutButton />
|
||||
</Row>
|
||||
</Grid>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
// import { Moon } from 'svelte-loading-spinners';
|
||||
import { VARIANTS, VARIANTS_CLASS } from './constants';
|
||||
import { Loading } from 'carbon-components-svelte';
|
||||
@@ -7,7 +7,7 @@
|
||||
export let className = '';
|
||||
export let onClick = () => {};
|
||||
export let name = '';
|
||||
export let type = 'button';
|
||||
export let type: 'button' | 'submit' | 'reset' | null | undefined = 'button';
|
||||
export let variant = VARIANTS.CONTAINED;
|
||||
export let disablePadding = false;
|
||||
export let isDisabled = false;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { dev } from '$app/environment';
|
||||
import posthog from 'posthog-js';
|
||||
|
||||
export const capturePosthogEvent = (event: string, properties?: Record<string, any>): void => {
|
||||
if (dev) return;
|
||||
|
||||
posthog.capture(event, properties);
|
||||
};
|
||||
|
||||
export const identifyPosthogUser = (id: string, properties?: Record<string, any>): void => {
|
||||
if (dev) return;
|
||||
|
||||
posthog.identify(id, properties);
|
||||
};
|
||||
|
||||
export const initPosthog = (): void => {
|
||||
if (dev) return;
|
||||
|
||||
posthog.init('phc_JfdHOZ6v0cVlGELBYx1Tmoen2nxNOrAzvgvrPA6Ksov', {
|
||||
api_host: 'https://eu.posthog.com'
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { dev } from '$app/environment';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { CaptureConsole } from '@sentry/integrations';
|
||||
|
||||
export const initSentry = (): void => {
|
||||
if (dev) return;
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://[email protected]/5999999',
|
||||
integrations: [
|
||||
new CaptureConsole({
|
||||
levels: ['error']
|
||||
}),
|
||||
new Sentry.Replay()
|
||||
],
|
||||
environment: 'production',
|
||||
replaysSessionSampleRate: 0.5,
|
||||
replaysOnErrorSampleRate: 1.0
|
||||
});
|
||||
};
|
||||
|
||||
export const setSentryUser = (user: Record<string, any>): void => {
|
||||
if (dev) return;
|
||||
|
||||
Sentry.setUser(user);
|
||||
};
|
||||
+17
-37
@@ -3,12 +3,9 @@
|
||||
import { fly } from 'svelte/transition';
|
||||
import { derived } from 'svelte/store';
|
||||
import { goto } from '$app/navigation';
|
||||
import { dev, browser } from '$app/environment';
|
||||
import { browser } from '$app/environment';
|
||||
import { page, navigating } from '$app/stores';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { CaptureConsole } from '@sentry/integrations';
|
||||
import posthog from 'posthog-js';
|
||||
import { Theme, ToastNotification, Loading } from 'carbon-components-svelte';
|
||||
import type { CarbonTheme } from 'carbon-components-svelte/types/Theme/Theme.svelte';
|
||||
import LandingNavigation from '$lib/components/Navigation/index.svelte';
|
||||
@@ -37,6 +34,8 @@
|
||||
import hideNavByRoute from '$lib/utils/functions/routes/hideNavByRoute';
|
||||
import shouldRedirectOnAuth from '$lib/utils/functions/routes/shouldRedirectOnAuth';
|
||||
import AddOrgModal from '$lib/components/Org/AddOrgModal/AddOrgModal.svelte';
|
||||
import { identifyPosthogUser, initPosthog } from '$lib/utils/services/posthog';
|
||||
import { initSentry, setSentryUser } from '$lib/utils/services/sentry';
|
||||
|
||||
import '../app.postcss';
|
||||
|
||||
@@ -50,39 +49,24 @@
|
||||
setTimeout(() => set(currentPreloading), 250);
|
||||
});
|
||||
|
||||
function setupSentry() {
|
||||
Sentry.init({
|
||||
dsn: 'https://[email protected]/5999999',
|
||||
integrations: [
|
||||
new CaptureConsole({
|
||||
levels: ['error']
|
||||
}),
|
||||
new Sentry.Replay()
|
||||
],
|
||||
environment: 'production',
|
||||
// This sets the sample rate to be 10%. You may want this to be 100% while
|
||||
// in development and sample at a lower rate in production
|
||||
replaysSessionSampleRate: 0.5,
|
||||
// If the entire session is not sampled, use the below sample rate to sample
|
||||
// sessions when an error occurs.
|
||||
replaysOnErrorSampleRate: 1.0
|
||||
});
|
||||
function setupAnalytics() {
|
||||
// Set up sentry
|
||||
initSentry();
|
||||
|
||||
// Set up posthog
|
||||
initPosthog();
|
||||
}
|
||||
|
||||
function setupPosthug() {
|
||||
posthog.init('phc_JfdHOZ6v0cVlGELBYx1Tmoen2nxNOrAzvgvrPA6Ksov', {
|
||||
api_host: 'https://eu.posthog.com'
|
||||
});
|
||||
}
|
||||
|
||||
function setSentryUser() {
|
||||
if ($profile) {
|
||||
Sentry.setUser({
|
||||
function setAnalyticsUser() {
|
||||
if ($profile.id) {
|
||||
setSentryUser({
|
||||
id: $profile.id,
|
||||
username: $profile.username,
|
||||
email: $profile.email,
|
||||
fullname: $profile.fullname
|
||||
});
|
||||
|
||||
identifyPosthogUser($profile.id, { email: $profile.email, name: $profile.fullname });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +114,7 @@
|
||||
|
||||
profile.set(newProfileData[0]);
|
||||
|
||||
// Set user in sentry
|
||||
setSentryUser();
|
||||
setAnalyticsUser();
|
||||
|
||||
if (data.isOrgSite) {
|
||||
const { data, error } = await supabase
|
||||
@@ -173,7 +156,7 @@
|
||||
profile.set(profileData);
|
||||
|
||||
// Set user in sentry
|
||||
setSentryUser();
|
||||
setAnalyticsUser();
|
||||
|
||||
const orgRes = await getOrganizations(profileData.id);
|
||||
|
||||
@@ -225,10 +208,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
setupSentry();
|
||||
setupPosthug();
|
||||
}
|
||||
setupAnalytics();
|
||||
|
||||
handleResize();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
NOTIFICATION_NAME
|
||||
} from '$lib/utils/services/notification/notification';
|
||||
import { snackbar } from '$lib/components/Snackbar/store.js';
|
||||
import { capturePosthogEvent } from '$lib/utils/services/posthog/index.js';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -73,6 +74,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
capturePosthogEvent('student_joined_course', {
|
||||
course_name: data.name,
|
||||
student_id: $profile.id,
|
||||
student_email: $profile.email
|
||||
});
|
||||
|
||||
// Send email welcoming student to the course
|
||||
triggerSendEmail(NOTIFICATION_NAME.STUDENT_COURSE_WELCOME, {
|
||||
to: $profile.email,
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
import AuthUI from '$lib/components/AuthUI/index.svelte';
|
||||
import { currentOrg } from '$lib/utils/store/org';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { capturePosthogEvent } from '$lib/utils/services/posthog';
|
||||
|
||||
let formRef;
|
||||
let supabase = getSupabase();
|
||||
let fields = Object.assign({}, LOGIN_FIELDS);
|
||||
let submitError;
|
||||
let submitError: string;
|
||||
let loading = false;
|
||||
let errors = {};
|
||||
let reloadTimeout: NodeJS.Timeout;
|
||||
@@ -43,6 +44,10 @@
|
||||
console.log('Forcing full page reload for auth listener');
|
||||
window.location.reload();
|
||||
}, 1500);
|
||||
|
||||
capturePosthogEvent('login', {
|
||||
email: fields.email
|
||||
});
|
||||
} catch (error) {
|
||||
submitError = error.error_description || error.message;
|
||||
} finally {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import UserAvatarIcon from 'carbon-icons-svelte/lib/UserAvatar.svelte';
|
||||
import BookIcon from 'carbon-icons-svelte/lib/Book.svelte';
|
||||
import TextField from '$lib/components/Form/TextField.svelte';
|
||||
import LogoutButton from '$lib/components/Buttons/Logout/index.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
import UploadImage from '$lib/components/UploadImage/index.svelte';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { user, profile } from '$lib/utils/store/user';
|
||||
@@ -88,12 +87,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
console.log('error logout', error);
|
||||
goto('/login');
|
||||
}
|
||||
|
||||
$: isDirty =
|
||||
avatar ||
|
||||
initialValueOfUserName !== currentProfile.username ||
|
||||
@@ -200,7 +193,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PrimaryButton variant={VARIANTS.OUTLINED} label="Log out" onClick={logout} />
|
||||
<LogoutButton />
|
||||
</div>
|
||||
<!-- {:else if loading}
|
||||
<Box>
|
||||
|
||||
@@ -13,12 +13,17 @@
|
||||
import AuthUI from '$lib/components/AuthUI/index.svelte';
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { currentOrg } from '$lib/utils/store/org';
|
||||
import { capturePosthogEvent } from '$lib/utils/services/posthog';
|
||||
|
||||
let supabase = getSupabase();
|
||||
let fields = Object.assign({}, SIGNUP_FIELDS);
|
||||
let loading = false;
|
||||
let success = false;
|
||||
let errors = {};
|
||||
let errors: {
|
||||
email?: string;
|
||||
password?: string;
|
||||
confirmPassword?: string;
|
||||
} = {};
|
||||
let submitError: string;
|
||||
let disableSubmit = false;
|
||||
let formRef: HTMLFormElement;
|
||||
@@ -26,7 +31,7 @@
|
||||
let query = new URLSearchParams($page.url.search);
|
||||
let redirect = query.get('redirect');
|
||||
|
||||
async function handleSubmit(e) {
|
||||
async function handleSubmit() {
|
||||
const validationRes = authValidation(fields);
|
||||
console.log('validationRes', validationRes);
|
||||
|
||||
@@ -80,6 +85,13 @@
|
||||
console.log('setting profile', profileRes.data[0]);
|
||||
profile.set(profileRes.data[0]);
|
||||
|
||||
capturePosthogEvent('user_signed_up', {
|
||||
distinct_id: $profile.id || '',
|
||||
email: authUser.email,
|
||||
username: regexUsernameMatch[1],
|
||||
metadata
|
||||
});
|
||||
|
||||
if (redirect) {
|
||||
goto(redirect);
|
||||
} else {
|
||||
@@ -90,7 +102,7 @@
|
||||
success = true;
|
||||
fields = Object.assign({}, SIGNUP_FIELDS);
|
||||
} catch (error) {
|
||||
submitError = error.error_description || error.message;
|
||||
submitError = error?.error_description || error?.message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user