diff --git a/.env.example b/.env.example
new file mode 100644
index 00000000..9788f6df
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,3 @@
+NEXT_PUBLIC_GOOGLE_ANALYTICS=
+SPREADSHEET_URL=
+NEXT_FULLSTORY_ID=
\ No newline at end of file
diff --git a/package.json b/package.json
index fe294ac4..0886d619 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"isready": "npm run format && npm run lint && npm run build"
},
"dependencies": {
+ "@fullstory/browser": "^1.5.1",
"ics": "^2.35.0",
"next": "12.1.0",
"react": "17.0.2",
@@ -20,6 +21,7 @@
},
"devDependencies": {
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
+ "@types/gtag.js": "^0.0.10",
"@types/node": "^17.0.14",
"@types/react": "^17.0.38",
"@types/react-typist": "^2.0.3",
diff --git a/pages/_app.tsx b/pages/_app.tsx
index e940a065..7d92f5db 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -16,26 +16,49 @@ import "src/sections/community/styles.scss";
import "src/sections/home/styles.scss";
import "src/sections/sponsorship/styles.scss";
+import { useEffect } from 'react'
+import { useRouter } from 'next/router'
import NavigationBar from "src/components/NavigationBar";
import Footer from "src/components/Footer";
+import * as ga from "src/utils/analytics"
-const MyApp = ({ Component, pageProps }) => (
- <>
-
-
-
-
-
-
-
- >
-);
+
+const MyApp = ({ Component, pageProps }) => {
+ const router = useRouter();
+
+ useEffect(() => {
+ const handleRouteChange = (url: string) => {
+ ga.pageview(url)
+ }
+ //When the component is mounted, subscribe to router changes
+ //and log those page views
+ router.events.on('routeChangeComplete', handleRouteChange)
+
+ // If the component is unmounted, unsubscribe
+ // from the event with the `off` method
+ return () => {
+ router.events.off('routeChangeComplete', handleRouteChange)
+ }
+ }, [router.events])
+
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+}
export default MyApp;
diff --git a/pages/_document.tsx b/pages/_document.tsx
new file mode 100644
index 00000000..c62a2f74
--- /dev/null
+++ b/pages/_document.tsx
@@ -0,0 +1,24 @@
+import { Html, Head, Main, NextScript } from 'next/document'
+import { FULLSTORY_ANALYTICS_SCRIPT_CODE, GOOGLE_ANALYTICS_SCRIPT_CODE } from 'src/utils/analytics'
+
+export default function Document() {
+ return (
+
+
+ {/* Global Site Tag (gtag.js) - Google Analytics */}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/pages/about.tsx b/pages/about.tsx
index a2d48de2..af566641 100644
--- a/pages/about.tsx
+++ b/pages/about.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
-import { Size, useWindowSize } from "src/utils";
+import { Size, useWindowSize } from "src/utils/general";
import SEO from "src/components/SEO";
@@ -23,7 +23,7 @@ const AboutPage: React.FC<{ board: BoardMemberProps[] }> = ({ board }) => {
return (
<>
{
return (
<>
= ({ event }) => {
if (!event) return ;
@@ -11,9 +11,8 @@ const EventPage: React.FC<{ event: EventObject }> = ({ event }) => {
diff --git a/pages/events/index.tsx b/pages/events/index.tsx
index acabf8f9..ee0cac9f 100644
--- a/pages/events/index.tsx
+++ b/pages/events/index.tsx
@@ -1,11 +1,12 @@
import { EventsArray, getAllEvents } from "src/api/EventsAPI";
import SEO from "src/components/SEO";
+import Head from "next/head";
import EventsContent from "src/sections/events/Events.Content";
const EventsPage: React.FC<{ futureEvents: EventsArray }> = ({ futureEvents }) => {
return (
<>
-
+
>
);
diff --git a/pages/sponsor.tsx b/pages/sponsor.tsx
index 6da0543c..a1f75dcc 100644
--- a/pages/sponsor.tsx
+++ b/pages/sponsor.tsx
@@ -8,7 +8,7 @@ import SponsorHeroLogo from "public/assets/sponsor-images/sponsor_hero.png";
const SponsorshipPage: React.FC = () => (
<>
= ({ path, title, description, image }) => {
{/* google indexing data */}
- ACM at UCSD
+ {title}
= ({ event }) => {
diff --git a/src/sections/home/Home.Events.tsx b/src/sections/home/Home.Events.tsx
index 44d7d7c0..5c1f2303 100644
--- a/src/sections/home/Home.Events.tsx
+++ b/src/sections/home/Home.Events.tsx
@@ -1,5 +1,5 @@
import { EventObject } from "src/api/EventsAPI";
-import { isURL, getAbsoluteURL, getDateTime } from "src/utils";
+import { isURL, getAbsoluteURL, getDateTime } from "src/utils/general";
const HomeEvents: React.FC<{ events: Array }> = ({ events }) => {
return (
diff --git a/src/utils/analytics.ts b/src/utils/analytics.ts
new file mode 100644
index 00000000..7e0c87a0
--- /dev/null
+++ b/src/utils/analytics.ts
@@ -0,0 +1,49 @@
+// Directly taken from https://mariestarck.com/add-google-analytics-to-your-next-js-application-in-5-easy-steps/
+
+// log the pageview with their URL
+export const pageview = (url: string) => {
+ window.gtag('config', process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS, {
+ page_path: url,
+ })
+}
+
+// log specific events happening.
+export const event = ({ action, params }) => {
+ window.gtag('event', action, params)
+}
+
+// google analytics script code, lifted from https://developers.google.com/analytics/devguides/collection/gtagjs
+export const GOOGLE_ANALYTICS_SCRIPT_CODE = `
+window.dataLayer = window.dataLayer || [];
+function gtag(){dataLayer.push(arguments);}
+gtag('js', new Date());
+gtag('config', '${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}', {
+ page_path: window.location.pathname,
+});
+`
+
+// fullstory analyrics script code, lifted from https://help.fullstory.com/hc/en-us/articles/360020623514-Installing-the-FullStory-Script
+export const FULLSTORY_ANALYTICS_SCRIPT_CODE = `
+window['_fs_debug'] = false;
+window['_fs_host'] = 'fullstory.com';
+window['_fs_script'] = 'edge.fullstory.com/s/fs.js';
+window['_fs_org'] = '${process.env.NEXT_FULLSTORY_ID}';
+window['_fs_namespace'] = 'FS';
+(function(m,n,e,t,l,o,g,y){
+ if (e in m) {if(m.console && m.console.log) { m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');} return;}
+ g=m[e]=function(a,b,s){g.q?g.q.push([a,b,s]):g._api(a,b,s);};g.q=[];
+ o=n.createElement(t);o.async=1;o.crossOrigin='anonymous';o.src='https://'+_fs_script;
+ y=n.getElementsByTagName(t)[0];y.parentNode.insertBefore(o,y);
+ g.identify=function(i,v,s){g(l,{uid:i},s);if(v)g(l,v,s)};g.setUserVars=function(v,s){g(l,v,s)};g.event=function(i,v,s){g('event',{n:i,p:v},s)};
+ g.anonymize=function(){g.identify(!!0)};
+ g.shutdown=function(){g("rec",!1)};g.restart=function(){g("rec",!0)};
+ g.log = function(a,b){g("log",[a,b])};
+ g.consent=function(a){g("consent",!arguments.length||a)};
+ g.identifyAccount=function(i,v){o='account';v=v||{};v.acctId=i;g(o,v)};
+ g.clearUserCookie=function(){};
+ g.setVars=function(n, p){g('setVars',[n,p]);};
+ g._w={};y='XMLHttpRequest';g._w[y]=m[y];y='fetch';g._w[y]=m[y];
+ if(m[y])m[y]=function(){return g._w[y].apply(this,arguments)};
+ g._v="1.3.0";
+})(window,document,window['_fs_namespace'],'script','user');
+`
\ No newline at end of file
diff --git a/src/utils.ts b/src/utils/general.ts
similarity index 98%
rename from src/utils.ts
rename to src/utils/general.ts
index dd77f6bd..0c10e746 100644
--- a/src/utils.ts
+++ b/src/utils/general.ts
@@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
-import { EventObject } from "./api/EventsAPI";
+import { EventObject } from "src/api/EventsAPI";
/**
* Determines if given string is a valid website link.
diff --git a/yarn.lock b/yarn.lock
index de05a4f3..7114cc78 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1078,6 +1078,11 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
+"@fullstory/browser@^1.5.1":
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/@fullstory/browser/-/browser-1.5.1.tgz#4b6ce95df3a91408a8b56bac06038f4d128f9ec8"
+ integrity sha512-eOTR0lc2BwwyGYn7ke7aJrJpl8Ae4+KdWyiibixVn+RUG3NaQgrP7hj/KmlMnndRSO9I4YqoqZCKYwtqDFo3rw==
+
"@humanwhocodes/config-array@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
@@ -1228,6 +1233,11 @@
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
+"@types/gtag.js@^0.0.10":
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.10.tgz#ac90d9b79c00daac447725a4b78ec1c398796760"
+ integrity sha512-98Hy7woUb3jMAMXkZQwfIOYNyfxmI0+U4m0PpCGdnd/FHk0tDpQFCqgXdNkdEoXsKkcGya/2Gew1cAJjKJspVw==
+
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"