diff --git a/website/package.json b/website/package.json index 5c811a82cd6..e2ba43ada01 100644 --- a/website/package.json +++ b/website/package.json @@ -42,11 +42,12 @@ "@near-wallet-selector/here-wallet": "^8.5.1", "@near-wallet-selector/modal-ui": "^8.5.1", "@near-wallet-selector/my-near-wallet": "^8.5.1", + "@rudderstack/analytics-js": "^3.0.0-beta.20", "@saucelabs/theme-github-codeblock": "^0.2.3", "algoliasearch": "^4.14.2", + "axios": "^1.6.2", "bootstrap": "^5.3.2", "bootstrap-icons": "^1.11.1", - "axios": "^1.6.2", "clsx": "^1.1.1", "docusaurus-plugin-remote-content": "^4.0.0", "docusaurus-plugin-sass": "^0.2.5", diff --git a/website/src/components/ContactUs.mdx b/website/src/components/ContactUs.mdx index f59725f1c75..83680edb488 100644 --- a/website/src/components/ContactUs.mdx +++ b/website/src/components/ContactUs.mdx @@ -4,38 +4,38 @@ If you have any questions, or simply would want to chat with us, please do throu
-
-
-
-
+
+
+
+
-
-
Twitter
- @nearprotocol +
+
Twitter
+ @nearprotocol
-
-
+
+
-
-
Discord
- NEAR Protocol +
+
Discord
+ NEAR Protocol
-
-
+
+
-
-
Zulip
- Near Chat +
+
Zulip
+ Near Chat
diff --git a/website/src/components/featurelist.js b/website/src/components/featurelist.js index fa85f112a83..123bc417eb0 100644 --- a/website/src/components/featurelist.js +++ b/website/src/components/featurelist.js @@ -3,8 +3,8 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; export function FeatureList({ children }) { return <> -
-
+
+
{children}
@@ -13,7 +13,7 @@ export function FeatureList({ children }) { export function Column({ title, children, size = 4 }) { return <> -
+

{title}

{children}
@@ -24,20 +24,20 @@ export function Feature({ image, title, subtitle, url, highlight = false }) { const { siteConfig, i18n } = useDocusaurusContext(); let link; if (url.startsWith('http')) { - link = ; + link = ; } else if (i18n.currentLocale != i18n.defaultLocale) { url = "/" + i18n.currentLocale + url; } return <>

- + -
-
{title} {link}
- {subtitle} +
+
{title} {link}
+ {subtitle}
diff --git a/website/src/components/social-widget.js b/website/src/components/social-widget.js index 333625621e5..52bccab3f64 100644 --- a/website/src/components/social-widget.js +++ b/website/src/components/social-widget.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { useWallet } from '@theme/Gateway/wallet-selector'; +import { useWallet } from '@theme/scripts/wallet-selector'; import BrowserOnly from '@docusaurus/BrowserOnly'; import "react-bootstrap-typeahead/css/Typeahead.css"; import "react-bootstrap-typeahead/css/Typeahead.bs5.css"; @@ -25,7 +25,7 @@ export function WidgetEditor({ children, id = 1, height = "160px" }) { }, [initNear, selector]); return
-
+
-
-
-
+
+
+
diff --git a/website/src/theme/NavbarItem/login-button.js b/website/src/theme/NavbarItem/login-button.js index 27302e51de4..fea283340bf 100644 --- a/website/src/theme/NavbarItem/login-button.js +++ b/website/src/theme/NavbarItem/login-button.js @@ -1,6 +1,6 @@ import React from 'react'; import { useState, useEffect } from 'react'; -import { useWallet } from '@theme/Gateway/wallet-selector'; +import { useWallet } from '@theme/scripts/wallet-selector'; import styles from './btn.module.css'; export default function LoginButton(props) { diff --git a/website/src/theme/Root.js b/website/src/theme/Root.js index 191458c9510..368d569fe95 100644 --- a/website/src/theme/Root.js +++ b/website/src/theme/Root.js @@ -2,25 +2,31 @@ import '@near-wallet-selector/modal-ui/styles.css'; import React from 'react'; -import useIsBrowser from '@docusaurus/useIsBrowser'; // https://docusaurus.io/docs/advanced/ssg#useisbrowser import Gleap from "gleap"; // See https://gleap.io/docs/javascript/ and https://app.gleap.io/projects/62697858a4f6850036ae2e6a/widget import { withRouter } from 'react-router-dom'; +import useIsBrowser from '@docusaurus/useIsBrowser'; // https://docusaurus.io/docs/advanced/ssg#useisbrowser import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { setupAlgoliaEvents } from './algolia-events'; -import { useInitWallet } from './Gateway/wallet-selector'; +import { setupAlgoliaEvents } from '@theme/scripts/algolia-events'; +import { useInitWallet } from '@theme/scripts/wallet-selector'; -const GLEAP_API_KEY = 'K2v3kvAJ5XtPzNYSgk4Ulpe5ptgBkIMv'; - -function Root({ children, history }) { - useInitWallet({ createAccessKeyFor: 'v1.social08.testnet' , networkId: 'testnet' }); +function Root({ children, location, history }) { + useInitWallet({ createAccessKeyFor: 'v1.social08.testnet', networkId: 'testnet' }); const isBrowser = useIsBrowser(); const docusaurusContext = useDocusaurusContext(); if (isBrowser) { - Gleap.initialize(GLEAP_API_KEY); + const { initRudderAnalytics, recordPageView } = require('./scripts/rudderstack'); + + Gleap.initialize('K2v3kvAJ5XtPzNYSgk4Ulpe5ptgBkIMv'); setupAlgoliaEvents(docusaurusContext, history); + + const rudderAnalytics = initRudderAnalytics(); + recordPageView(rudderAnalytics, location.pathname); } return <>{children}; } -export default withRouter(Root); \ No newline at end of file +const router = withRouter(Root); + + +export default router; \ No newline at end of file diff --git a/website/src/theme/algolia-events.js b/website/src/theme/scripts/algolia-events.js similarity index 100% rename from website/src/theme/algolia-events.js rename to website/src/theme/scripts/algolia-events.js diff --git a/website/src/theme/scripts/rudderstack.js b/website/src/theme/scripts/rudderstack.js new file mode 100644 index 00000000000..5bf97ea7fe4 --- /dev/null +++ b/website/src/theme/scripts/rudderstack.js @@ -0,0 +1,153 @@ +import { nanoid } from 'nanoid'; +import { createHash } from 'crypto'; +import { get, split, truncate } from 'lodash'; +import { RudderAnalytics } from '@rudderstack/analytics-js'; + +export function initRudderAnalytics() { + const rudderAnalytics = new RudderAnalytics(); + window.rudderanalytics = rudderAnalytics; + rudderAnalytics.load("2bP8Ev07SiL1ABLXhcru4JZQ5Uh", "https://near.dataplane.rudderstack.com", {}); + rudderAnalytics.setAnonymousId(getAnonymousId()); + return rudderAnalytics; +} + +export function recordPageView(rudderAnalytics, pageName) { + if(pageName === '/') return; + if(!rudderAnalytics) return; + + // pageName should be /category/page and never contain ? or # + // but just in case we split on ? and # + const split = pageName.split('?')[0].split('#')[0].split('/'); + const category = split[1]; + const page = split.slice(2).join('/'); + try { + rudderAnalytics.page(category, page, { + hashId: localStorage.getItem('hashId') || '', + url: filterURL(window.location.href), + ref: filterURL(document.referrer), + }); + } catch (e) { } // Silent error +} + +// let rudderAnalytics = null; +// let hashId = ''; +// let pendingEvents = []; + +// export function setAccountIdHash(accountId) { +// const hash = createHash('sha512'); +// hash.update(accountId); +// hashId = hash.digest('hex'); +// localStorage.setItem('hashId', hashId); +// } + +export function getAnonymousId() { + const storageId = localStorage.getItem('anonymousUserId'); + + if (storageId) { + console.log("Existing storageId", storageId); + return storageId; + } + + console.log("Creating new storageId"); + const anonymousUserId = nanoid(); + const anonymousUserIdCreatedAt = new Date().toUTCString(); + localStorage.setItem('anonymousUserId', anonymousUserId); + localStorage.setItem('anonymousUserIdCreatedAt', anonymousUserIdCreatedAt); + + return anonymousUserId; +} + +function isStringAllowed(str) { + const denyList = ['account_id', 'public_key', 'all_keys', 'publicKey', 'apiKey', 'accountId', 'email']; + return !str || !denyList.some((param) => str.indexOf(param) !== -1); +} + +function filterURL(url) { + const [urlTrim, params] = split(url, '?'); + return isStringAllowed(params) ? url : urlTrim; +} + + +// const record = (eventType, e) => { +// const key = get(e.target, 'placeholder', get(e.target, 'innerText', get(e.target, 'href'))); +// recordEventWithProps(eventType, { +// element: truncate(key, { length: 255 }), +// url: e.target ? filterURL(e.target.baseURI) : '', +// xPath: getXPath(e.target), +// componentSrc: getComponentName(e.target), +// }); +// }; + +// export const recordClick = (e) => record('click', e); +// export const recordMouseEnter = (e) => record('mouseover', e); +// export const recordTouchStart = (e) => record('touchstart', e); + +// export function recordWalletConnect(accountId) { +// if (!localStorage.getItem('hashId')) { +// setAccountIdHash(accountId); +// recordEvent('wallet-connected'); +// } +// } + +// export function reset() { +// if (!rudderAnalytics) return; +// try { +// recordEvent('wallet-logout'); +// localStorage.removeItem('hashId'); +// localStorage.removeItem('anonymousUserId'); +// localStorage.removeItem('anonymousUserIdCreatedAt'); +// rudderAnalytics.reset(); +// } catch (e) { +// console.error(e); +// } +// } + +// export function recordEventWithProps(eventLabel, properties) { +// if (!rudderAnalytics) return; +// try { +// rudderAnalytics.track(eventLabel, { +// ...properties, +// hashId: localStorage.getItem('hashId'), +// anonymousUserIdCreatedAt, +// }); +// } catch (e) { +// console.error(e); +// } +// } + +// export function recordEvent(eventLabel) { +// if (!rudderAnalytics) return; +// try { +// rudderAnalytics.track(eventLabel, { +// hashId: localStorage.getItem('hashId'), +// url: window.location.href, +// anonymousUserIdCreatedAt, +// }); +// } catch (e) { +// console.error(e); +// } +// } + +// function getComponentName(element) { +// if (!element) return ''; +// if (element.hasAttribute('data-component')) return element.getAttribute('data-component') || ''; +// return ''; +// } + +// function getXPath(element) { +// if (!element) return ''; +// if (element.id !== '') return 'id("' + element.id + '")'; +// if (element === document.body) return element.tagName; + +// let ix = 0; +// const siblings = element.parentNode?.children; +// if (!siblings) return ''; + +// for (let i = 0; i < siblings.length; i++) { +// const sibling = siblings[i]; +// if (sibling === element) return getXPath(element.parentElement) + '/' + element.tagName + '[' + (ix + 1) + ']'; +// if (sibling.nodeType === 1 && sibling.tagName === element.tagName) ix++; +// } + +// return ''; +// } \ No newline at end of file diff --git a/website/src/theme/Gateway/wallet-selector.js b/website/src/theme/scripts/wallet-selector.js similarity index 100% rename from website/src/theme/Gateway/wallet-selector.js rename to website/src/theme/scripts/wallet-selector.js