Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Analytics (Google and Fullstory) #227

Merged
merged 4 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_GOOGLE_ANALYTICS=
trulyronak marked this conversation as resolved.
Show resolved Hide resolved
SPREADSHEET_URL=
NEXT_FULLSTORY_ID=
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
59 changes: 41 additions & 18 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => (
<>
<NavigationBar />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
minHeight: 960,
padding: `85px 0`,
}}
>
<main>
<Component {...pageProps} />
</main>
</div>
<Footer />
</>
);

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])
trulyronak marked this conversation as resolved.
Show resolved Hide resolved

return (
<>
<NavigationBar />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
minHeight: 960,
padding: `85px 0`,
}}
>
<main>
<Component {...pageProps} />
trulyronak marked this conversation as resolved.
Show resolved Hide resolved
</main>
</div>
<Footer />
</>
);
}

export default MyApp;
24 changes: 24 additions & 0 deletions pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -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 (
trulyronak marked this conversation as resolved.
Show resolved Hide resolved
<Html>
<Head>
{/* Global Site Tag (gtag.js) - Google Analytics */}
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}`}
/>

<script dangerouslySetInnerHTML={{ __html: GOOGLE_ANALYTICS_SCRIPT_CODE, }} />
<script dangerouslySetInnerHTML={{ __html: FULLSTORY_ANALYTICS_SCRIPT_CODE }} />
</Head>
<body>

<Main />
<NextScript />
</body>
</Html>
)
}
4 changes: 2 additions & 2 deletions pages/about.tsx
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -23,7 +23,7 @@ const AboutPage: React.FC<{ board: BoardMemberProps[] }> = ({ board }) => {
return (
<>
<SEO
title="About"
title="About | ACM at UCSD"
path="/about"
description="We are the Association for Computing Machinery at UCSD! We are an inclusive member-first community for all who are interested in the field of computing. We welcome all skill levels and majors!"
image={HeroImage.src}
Expand Down
4 changes: 2 additions & 2 deletions pages/communities.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
import { Size, useWindowSize } from "src/utils";
import { Size, useWindowSize } from "src/utils/general";

import SEO from "src/components/SEO";

Expand All @@ -18,7 +18,7 @@ const CommunitiesPage: React.FC = () => {
return (
<>
<SEO
title="Communities"
title="Communities | ACM at UCSD"
path="/communities"
description="ACM at UCSD is one large community, but it is made up of several smaller communities focused on specific areas of technology."
image={ACMWhiteLogo.src}
Expand Down
7 changes: 3 additions & 4 deletions pages/events/[key].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import NotFoundPage from "pages/404";
import { EventObject, getAllEvents, getEvent } from "src/api/EventsAPI";
import SEO from "src/components/SEO";
import EventContent from "src/sections/event/Event.Content";
import { formatURLEventTitle, getDateTime } from "src/utils";
import { formatURLEventTitle, getDateTime } from "src/utils/general";

const EventPage: React.FC<{ event: EventObject }> = ({ event }) => {
if (!event) return <NotFoundPage />;
Expand All @@ -11,9 +11,8 @@ const EventPage: React.FC<{ event: EventObject }> = ({ event }) => {
<SEO
title={event.title}
path={`${formatURLEventTitle(event.title)}-${event.uuid}`}
description={`${event.location} - ${getDateTime(event).time}\n\nEvent Description: ${
event.description
}`}
description={`${event.location} - ${getDateTime(event).time}\n\nEvent Description: ${event.description
}`}
image={event.cover}
/>
<EventContent event={event} />
Expand Down
3 changes: 2 additions & 1 deletion pages/events/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<SEO title="Events" path="/events" />
<SEO title="Events | ACM at UCSD" path="/events" />
<EventsContent events={futureEvents} />
</>
);
Expand Down
2 changes: 1 addition & 1 deletion pages/sponsor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SponsorHeroLogo from "public/assets/sponsor-images/sponsor_hero.png";
const SponsorshipPage: React.FC = () => (
<>
<SEO
title="Sponsor"
title="Sponsor | ACM at UCSD"
path="/sponsor"
description="Impact a community of 1000+ aspiring developers, designers, and innovators!"
image={SponsorHeroLogo.src}
Expand Down
2 changes: 1 addition & 1 deletion src/api/EventsAPI.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as ics from "ics";
import { formatURLEventTitle } from "src/utils";
import { formatURLEventTitle } from "src/utils/general";
const EVENT_API = "https://api.acmucsd.com/api/v2/event";

export type EventObject = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/EventCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Link from "next/link";
import { EventObject, saveToGoogleCal } from "src/api/EventsAPI";
import { formatURLEventTitle } from "src/utils";
import { formatURLEventTitle } from "src/utils/general";
import s from "./EventCard.module.scss";
import { days, months, getDateTime } from "src/utils";
import { days, months, getDateTime } from "src/utils/general";

const EventCard: React.FC<{
event: EventObject;
Expand Down
2 changes: 1 addition & 1 deletion src/components/NavigationBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Link from "next/link";
import { useEffect, useState } from "react";
import ACMLogo from "public/assets/ACMWhiteLogo.png";
import s from "src/components/NavigationBar/Navbar.module.scss";
import { Size, useWindowSize } from "src/utils";
import { Size, useWindowSize } from "src/utils/general";

const navLinks = [
{ to: "/about", text: "About Us" },
Expand Down
2 changes: 1 addition & 1 deletion src/components/SEO/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const SEO: React.FC<SEOProps> = ({ path, title, description, image }) => {
<Head>
{/* google indexing data */}

<title>ACM at UCSD</title>
<title>{title}</title>
trulyronak marked this conversation as resolved.
Show resolved Hide resolved
<meta
name="description"
content="Join the club. ACM at UCSD is an inclusive community of students passionate about technology. 1000+ UCSD members. 120+ annual events. 850+ cups of boba served."
Expand Down
2 changes: 1 addition & 1 deletion src/sections/event/Event.Content.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Link from "next/link";
import { downloadICS, EventObject, saveToGoogleCal } from "src/api/EventsAPI";
import { days, getDateTime, months } from "src/utils";
import { days, getDateTime, months } from "src/utils/general";
import s from "./Event.module.scss";

const EventContent: React.FC<{ event: EventObject }> = ({ event }) => {
Expand Down
2 changes: 1 addition & 1 deletion src/sections/home/Home.Events.tsx
Original file line number Diff line number Diff line change
@@ -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<EventObject> }> = ({ events }) => {
return (
Expand Down
49 changes: 49 additions & 0 deletions src/utils/analytics.ts
Original file line number Diff line number Diff line change
@@ -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, {
trulyronak marked this conversation as resolved.
Show resolved Hide resolved
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');
`
2 changes: 1 addition & 1 deletion src/utils.ts → src/utils/general.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down