diff --git a/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php b/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php
index 0b02561dd..777761b67 100644
--- a/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php
+++ b/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php
@@ -19,6 +19,7 @@ class BaseSettingsFormRequest extends AdminFormRequest
'app:name' => 'required|string|max:255',
'pterodactyl:auth:2fa_required' => 'required|integer|in:0,1,2',
'app:locale' => ['required', 'string', Rule::in(array_keys($this->getAvailableLanguages()))],
+ 'app:analytics' => 'nullable|string',
];
}
@@ -31,6 +32,7 @@ class BaseSettingsFormRequest extends AdminFormRequest
'app:name' => 'Company Name',
'pterodactyl:auth:2fa_required' => 'Require 2-Factor Authentication',
'app:locale' => 'Default Language',
+ 'app:analytics' => 'Google Analytics',
];
}
}
diff --git a/app/Http/ViewComposers/AssetComposer.php b/app/Http/ViewComposers/AssetComposer.php
index 7e8f82dbc..6da825ad4 100644
--- a/app/Http/ViewComposers/AssetComposer.php
+++ b/app/Http/ViewComposers/AssetComposer.php
@@ -37,6 +37,7 @@ class AssetComposer
'enabled' => config('recaptcha.enabled', false),
'siteKey' => config('recaptcha.website_key') ?? '',
],
+ 'analytics' => config('app.analytics') ?? '',
]);
}
}
diff --git a/app/Providers/SettingsServiceProvider.php b/app/Providers/SettingsServiceProvider.php
index 8a1d4db21..abd88c04b 100644
--- a/app/Providers/SettingsServiceProvider.php
+++ b/app/Providers/SettingsServiceProvider.php
@@ -21,6 +21,7 @@ class SettingsServiceProvider extends ServiceProvider
protected $keys = [
'app:name',
'app:locale',
+ 'app:analytics',
'recaptcha:enabled',
'recaptcha:secret_key',
'recaptcha:website_key',
diff --git a/package.json b/package.json
index 99bcf0d37..3a81f98fa 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
"path": "^0.12.7",
"query-string": "^6.7.0",
"react": "^16.13.1",
+ "react-ga": "^3.1.2",
"react-dom": "npm:@hot-loader/react-dom",
"react-fast-compare": "^3.2.0",
"react-google-recaptcha": "^2.0.1",
diff --git a/resources/scripts/components/App.tsx b/resources/scripts/components/App.tsx
index dac7fd102..350387fac 100644
--- a/resources/scripts/components/App.tsx
+++ b/resources/scripts/components/App.tsx
@@ -1,4 +1,5 @@
-import * as React from 'react';
+import React, { useEffect } from 'react';
+import ReactGA from 'react-ga';
import { hot } from 'react-hot-loader/root';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { StoreProvider } from 'easy-peasy';
@@ -48,6 +49,11 @@ const App = () => {
store.getActions().settings.setSettings(SiteConfiguration!);
}
+ useEffect(() => {
+ ReactGA.initialize(SiteConfiguration!.analytics);
+ ReactGA.pageview(location.pathname);
+ }, []);
+
return (
<>
diff --git a/resources/scripts/routers/AuthenticationRouter.tsx b/resources/scripts/routers/AuthenticationRouter.tsx
index a7c687eef..57d1422ca 100644
--- a/resources/scripts/routers/AuthenticationRouter.tsx
+++ b/resources/scripts/routers/AuthenticationRouter.tsx
@@ -1,4 +1,5 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import ReactGA from 'react-ga';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import LoginContainer from '@/components/auth/LoginContainer';
import ForgotPasswordContainer from '@/components/auth/ForgotPasswordContainer';
@@ -6,17 +7,23 @@ import ResetPasswordContainer from '@/components/auth/ResetPasswordContainer';
import LoginCheckpointContainer from '@/components/auth/LoginCheckpointContainer';
import NotFound from '@/components/screens/NotFound';
-export default ({ location, history, match }: RouteComponentProps) => (
-
-
-
-
-
-
-
-
- history.push('/auth/login')}/>
-
-
-
-);
+export default ({ location, history, match }: RouteComponentProps) => {
+ useEffect(() => {
+ ReactGA.pageview(location.pathname);
+ }, [ location.pathname ]);
+
+ return (
+
+
+
+
+
+
+
+
+ history.push('/auth/login')} />
+
+
+
+ );
+};
diff --git a/resources/scripts/routers/DashboardRouter.tsx b/resources/scripts/routers/DashboardRouter.tsx
index 79ebbe4a1..7a895a7e4 100644
--- a/resources/scripts/routers/DashboardRouter.tsx
+++ b/resources/scripts/routers/DashboardRouter.tsx
@@ -1,4 +1,5 @@
-import * as React from 'react';
+import React, { useEffect } from 'react';
+import ReactGA from 'react-ga';
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
import AccountOverviewContainer from '@/components/dashboard/AccountOverviewContainer';
import NavigationBar from '@/components/NavigationBar';
@@ -8,24 +9,30 @@ import NotFound from '@/components/screens/NotFound';
import TransitionRouter from '@/TransitionRouter';
import SubNavigation from '@/components/elements/SubNavigation';
-export default ({ location }: RouteComponentProps) => (
- <>
-
- {location.pathname.startsWith('/account') &&
-
-
- Settings
- API Credentials
-
-
- }
-
-
-
-
-
-
-
-
- >
-);
+export default ({ location }: RouteComponentProps) => {
+ useEffect(() => {
+ ReactGA.pageview(location.pathname);
+ }, [ location.pathname ]);
+
+ return (
+ <>
+
+ {location.pathname.startsWith('/account') &&
+
+
+ Settings
+ API Credentials
+
+
+ }
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/resources/scripts/routers/ServerRouter.tsx b/resources/scripts/routers/ServerRouter.tsx
index 9df270eaa..2e9ee9ed3 100644
--- a/resources/scripts/routers/ServerRouter.tsx
+++ b/resources/scripts/routers/ServerRouter.tsx
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
+import ReactGA from 'react-ga';
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
import NavigationBar from '@/components/NavigationBar';
import ServerConsole from '@/components/server/ServerConsole';
@@ -60,6 +61,10 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
};
}, [ match.params.id ]);
+ useEffect(() => {
+ ReactGA.pageview(location.pathname);
+ }, [ location.pathname ]);
+
return (
diff --git a/resources/scripts/state/settings.ts b/resources/scripts/state/settings.ts
index 20dbbdc6e..3eb782d91 100644
--- a/resources/scripts/state/settings.ts
+++ b/resources/scripts/state/settings.ts
@@ -7,6 +7,7 @@ export interface SiteSettings {
enabled: boolean;
siteKey: string;
};
+ analytics: string;
}
export interface SettingsStore {
diff --git a/resources/views/admin/settings/index.blade.php b/resources/views/admin/settings/index.blade.php
index 489646dc9..5ccec0dfa 100644
--- a/resources/views/admin/settings/index.blade.php
+++ b/resources/views/admin/settings/index.blade.php
@@ -31,6 +31,13 @@
This is the name that is used throughout the panel and in emails sent to clients.
+