diff --git a/package.json b/package.json index cc3d92ff..53a54059 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@storybook/theming": "6.5.9", "@sveltejs/vite-plugin-svelte": "^1.0.1", "@tsconfig/svelte": "^3.0.0", + "@types/gtag.js": "^0.0.12", "@types/proper-url-join": "^2.1.1", "@types/react-syntax-highlighter": "^15.5.4", "@typescript-eslint/eslint-plugin": "^5.33.1", @@ -100,6 +101,10 @@ "./actions/cssVariables": "./dist/actions/cssVariables/index.js", "./actions/resizeObserver": "./dist/actions/resizeObserver/index.js", "./components/@types/global.ts": "./dist/components/@types/global.ts", + "./components/Analytics/Analytics.svelte": "./dist/components/Analytics/Analytics.svelte", + "./components/Analytics/providers/chartbeat.ts": "./dist/components/Analytics/providers/chartbeat.ts", + "./components/Analytics/providers/ga.ts": "./dist/components/Analytics/providers/ga.ts", + "./components/Analytics/providers/index.ts": "./dist/components/Analytics/providers/index.ts", "./components/Article/Article.svelte": "./dist/components/Article/Article.svelte", "./components/BeforeAfter/BeforeAfter.svelte": "./dist/components/BeforeAfter/BeforeAfter.svelte", "./components/Block/Block.svelte": "./dist/components/Block/Block.svelte", @@ -131,10 +136,6 @@ "./components/ReutersGraphicsLogo/ReutersGraphicsLogo.svelte": "./dist/components/ReutersGraphicsLogo/ReutersGraphicsLogo.svelte", "./components/ReutersLogo/ReutersLogo.svelte": "./dist/components/ReutersLogo/ReutersLogo.svelte", "./components/SEO/SEO.svelte": "./dist/components/SEO/SEO.svelte", - "./components/SEO/analytics/chartbeat": "./dist/components/SEO/analytics/chartbeat.js", - "./components/SEO/analytics/ga": "./dist/components/SEO/analytics/ga.js", - "./components/SEO/analytics": "./dist/components/SEO/analytics/index.js", - "./components/SEO/analytics/publisherTags": "./dist/components/SEO/analytics/publisherTags.js", "./components/Scroller/Background.svelte": "./dist/components/Scroller/Background.svelte", "./components/Scroller/Embedded/Background.svelte": "./dist/components/Scroller/Embedded/Background.svelte", "./components/Scroller/Embedded/Foreground.svelte": "./dist/components/Scroller/Embedded/Foreground.svelte", @@ -206,6 +207,7 @@ "./components/Video/Controls.svelte": "./dist/components/Video/Controls.svelte", "./components/Video/Video.svelte": "./dist/components/Video/Video.svelte", "./components/Visible/Visible.svelte": "./dist/components/Visible/Visible.svelte", + "./globals.d.ts": "./dist/globals.d.ts", "./scss/mixins": "./dist/scss/_mixins.scss", "./scss/variables": "./dist/scss/_variables.scss", "./scss/bootstrap/main": "./dist/scss/bootstrap/_main.scss", diff --git a/src/components/Analytics/Analytics.stories.svelte b/src/components/Analytics/Analytics.stories.svelte new file mode 100644 index 00000000..c3263416 --- /dev/null +++ b/src/components/Analytics/Analytics.stories.svelte @@ -0,0 +1,45 @@ + + + + + + + + + + +
Nothing to see here
+
+ + + +
Nothing to see here
+
diff --git a/src/components/Analytics/Analytics.svelte b/src/components/Analytics/Analytics.svelte new file mode 100644 index 00000000..3d8512f0 --- /dev/null +++ b/src/components/Analytics/Analytics.svelte @@ -0,0 +1,29 @@ + + + + diff --git a/src/components/Analytics/providers/chartbeat.ts b/src/components/Analytics/providers/chartbeat.ts new file mode 100644 index 00000000..4d88c65c --- /dev/null +++ b/src/components/Analytics/providers/chartbeat.ts @@ -0,0 +1,41 @@ +// Reuters Chartbeat UID +const UID = 52639; + +const URL = '//static.chartbeat.com/js/chartbeat.js'; + +const attachScript = () => { + // If script is already attached, skip + if (document.querySelector(`script[src="${URL}"]`)) return; + // ... else attach it. + const e = document.createElement('script'); + const n = document.getElementsByTagName('script')[0]; + e.type = 'text/javascript'; + e.async = true; + e.src = URL; + n.parentNode.insertBefore(e, n); +}; + +export default (authors: { name: string }[]) => { + window._sf_async_config = { + uid: UID, + domain: 'reuters.com', + flickerControl: false, + useCanonical: true, + useCanonicalDomain: true, + sections: 'Graphics', + authors: authors.map((a) => a?.name || '').join(','), + ...(window._sf_async_config || {}), + }; + + try { + attachScript(); + } catch (e) { console.warn(`Error initialising Chartbeat Analytics: ${e}`); } +}; + +export const registerPageview = () => { + if (typeof window === 'undefined' || !window.pSUPERFLY) return; + window.pSUPERFLY({ + path: window.location.pathname, + title: document?.title, + }); +}; diff --git a/src/components/Analytics/providers/ga.ts b/src/components/Analytics/providers/ga.ts new file mode 100644 index 00000000..cdfbd24f --- /dev/null +++ b/src/components/Analytics/providers/ga.ts @@ -0,0 +1,43 @@ +// Reuters Google Tag ID +const GOOGLE_TAG_ID = 'G-W3Q2X6NTNM'; + +const URL = `https://www.googletagmanager.com/gtag/js?id=${GOOGLE_TAG_ID}`; + +const attachScript = () => { + // If script is already attached, skip + if (document.querySelector(`script[src="${URL}"]`)) return; + // ... else attach it. + const e = document.createElement('script'); + const n = document.getElementsByTagName('script')[0]; + e.type = 'text/javascript'; + e.async = true; + e.src = URL; + n.parentNode.insertBefore(e, n); +}; + +export default () => { + try { + window.dataLayer = window.dataLayer || []; + if (!window.gtag) { + attachScript(); + /** @type {Gtag.Gtag} */ + window.gtag = (...args) => { + window.dataLayer.push(...args); + }; + window.gtag('js', new Date()); + // config event registers a pageview by default + window.gtag('config', GOOGLE_TAG_ID, { + send_page_view: false, + }); + registerPageview(); + } + } catch (e) { console.warn(`Error initialising Google Analytics: ${e}`); } +}; + +export const registerPageview = () => { + if (typeof window === 'undefined' || !window.gtag) return; + window.gtag('event', 'page_view', { + page_location: window.location.origin + window.location.pathname, + page_title: document?.title, + }); +}; diff --git a/src/components/Analytics/providers/index.ts b/src/components/Analytics/providers/index.ts new file mode 100644 index 00000000..9b2fdba9 --- /dev/null +++ b/src/components/Analytics/providers/index.ts @@ -0,0 +1,2 @@ +export { default as ga } from './ga'; +export { default as chartbeat } from './chartbeat'; diff --git a/src/components/Analytics/stories/docs/component.md b/src/components/Analytics/stories/docs/component.md new file mode 100644 index 00000000..1ddd7b8e --- /dev/null +++ b/src/components/Analytics/stories/docs/component.md @@ -0,0 +1,11 @@ +Add Google and Chartbeat analytics to your page. + +```svelte + + + +``` diff --git a/src/components/Analytics/stories/docs/environments.md b/src/components/Analytics/stories/docs/environments.md new file mode 100644 index 00000000..74089219 --- /dev/null +++ b/src/components/Analytics/stories/docs/environments.md @@ -0,0 +1,17 @@ +Generally, you only want to send page analytics in production environments. + +In a SvelteKit context, you can use `$app` stores to restrict when you send analytics. + +For example, the following excludes analytics from pages in development or hosted on our preview server: + +```svelte + + +{#if !dev && $page.url?.hostname !== 'graphics.thomsonreuters.com'} + +{/if} +``` diff --git a/src/components/Analytics/stories/docs/multipage.md b/src/components/Analytics/stories/docs/multipage.md new file mode 100644 index 00000000..b8336dda --- /dev/null +++ b/src/components/Analytics/stories/docs/multipage.md @@ -0,0 +1,32 @@ +If you're using analytics to measure a multipage newsapp that uses [client-side routing](https://kit.svelte.dev/docs/glossary#routing), then you may need to trigger analytics after virtual page navigation. + +This component also exports a function you can call to register pageviews. + +For example, here's how you can use SvelteKit's [`afterNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-afternavigate) lifecycle to capture additional pageviews: + +```svelte + + + +``` diff --git a/src/components/SEO/SEO.svelte b/src/components/SEO/SEO.svelte index 9c9e49a5..4b4a0720 100644 --- a/src/components/SEO/SEO.svelte +++ b/src/components/SEO/SEO.svelte @@ -1,15 +1,9 @@