diff --git a/docs/thank-you.md b/docs/thank-you.md new file mode 100644 index 0000000..29daf40 --- /dev/null +++ b/docs/thank-you.md @@ -0,0 +1,14 @@ +--- +layout: page +title: Thank You for Using Copy for Scrapbox! +--- + +# Thank you for Using Copy for Scrapbox! + +We are sorry to see you go! Your feedback is important to us. +Please take a moment to let us know why you decided to uninstall the extension. + +- [GitHub Issues](https://github.com/satoryu/copy-for-scrapbox/issues) +- Email: satoryu.1981@gmail.com + +Thank you for your time and feedback! diff --git a/src/background.js b/src/background.js index c66eac4..f2029e8 100644 --- a/src/background.js +++ b/src/background.js @@ -1,10 +1,12 @@ import { getClientId } from './id.js' -import { sendTrackEvent } from './google-analytics.js' +import { installationHandler } from './installation-handler.js' import contextMenuRepository from './context_menu' -chrome.runtime.onInstalled.addListener(function () { +chrome.runtime.onInstalled.addListener(function ({ previousVersion, reason }) { getClientId() - sendTrackEvent({ name: 'installed' }) + .then((_clientId) => installationHandler({ previousVersion, reason })) + + chrome.runtime.setUninstallURL('https://www.satoryu.com/copy-for-scrapbox/thank-you') contextMenuRepository.getContextMenuInfo().forEach((contextMenuInfo) => { chrome.contextMenus.create(contextMenuInfo) diff --git a/src/google-analytics.js b/src/google-analytics.js index 0fd8eb4..afb9ee5 100644 --- a/src/google-analytics.js +++ b/src/google-analytics.js @@ -11,6 +11,8 @@ async function sendTrackEvent(event) { engagement_time_msec: 100 } + console.debug('Sending event:', event); + return fetch( `${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`, { diff --git a/src/installation-handler.js b/src/installation-handler.js new file mode 100644 index 0000000..0e2c556 --- /dev/null +++ b/src/installation-handler.js @@ -0,0 +1,35 @@ +import { sendTrackEvent } from "./google-analytics" + +async function saveLastInstalledVersion() { + const { version } = chrome.runtime.getManifest() + + return chrome.storage.local.set({ lastInstalledVersion: version }) +} + +async function getLastInstalledVersion() { + return chrome.storage.local.get('lastInstalledVersion') + .then(({ lastInstalledVersion }) => lastInstalledVersion) +} + +export async function installationHandler({ previousVersion, reason }) { + const { version } = chrome.runtime.getManifest() + + if (reason === 'install') { + await sendTrackEvent({ name: 'installed', params: { version } }) + .then(saveLastInstalledVersion) + .then(() => console.debug(`lastInstalledVersion is set: ${version}`)) + } else if (reason === 'update') { + await getLastInstalledVersion() + .then((lastInstalledVersion) => { + // if already installed, just update the version + if (lastInstalledVersion) { + console.debug(`lastInstalledVersion is ${lastInstalledVersion}`) + sendTrackEvent({ name: 'updated', params: { version, previousVersion } }) + return + } + + sendTrackEvent({ name: 'installed', params: { version } }) + .then(saveLastInstalledVersion) + }) + } +} \ No newline at end of file diff --git a/test/installation-hander.test.js b/test/installation-hander.test.js new file mode 100644 index 0000000..0ac4662 --- /dev/null +++ b/test/installation-hander.test.js @@ -0,0 +1,51 @@ +import { installationHandler } from "../src/installation-handler.js" +import { sendTrackEvent } from "../src/google-analytics.js" + +global.chrome = { + runtime: { + getManifest: () => ({ version: '4.4.4' }) + }, + storage: { + local: { + set: jest.fn(() => Promise.resolve()), + get: jest.fn(() => Promise.resolve({})), + }, + } +} + +jest.mock('../src/google-analytics.js', () => ({ sendTrackEvent: jest.fn() })) + +describe('installationHandler', () => { + beforeEach(() => { + chrome.storage.local.set.mockClear() + sendTrackEvent.mockClear() + + sendTrackEvent.mockReturnValue(Promise.resolve()) + }) + + describe('When the reason is install', () => { + it('should send installed event to google analytics', async () => { + await installationHandler({ reason: 'install' }) + + expect(sendTrackEvent).toHaveBeenCalledWith({ name: 'installed', params: { version: '4.4.4' } }) + expect(chrome.storage.local.set).toHaveBeenCalledWith({ lastInstalledVersion: '4.4.4' }) + }) + }) + + describe('When the reason is update', () => { + it('should send updated event to google analytics', async () => { + chrome.storage.local.get.mockReturnValue(Promise.resolve({ lastInstalledVersion: '3.3.3' })) + await installationHandler({ reason: 'update', previousVersion: '4.4.3' }) + + expect(sendTrackEvent).toHaveBeenCalledWith({ name: 'updated', params: { version: '4.4.4', previousVersion: '4.4.3' } }) + expect(chrome.storage.local.set).not.toHaveBeenCalled() + }) + + it('should send installed event if latestInstalledVersion is not set', async () => { + chrome.storage.local.get.mockReturnValue(Promise.resolve({ lastInstalledVersion: null })) + await installationHandler({ reason: 'update', previousVersion: '4.4.3' }) + + expect(sendTrackEvent).toHaveBeenCalledWith({ name: 'installed', params: { version: '4.4.4' } }) + }) + }) +})