mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-30 10:42:38 +00:00
feat: more events tracking for SaaS (#6234)
This commit is contained in:
@@ -43,9 +43,7 @@ import {
|
||||
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../../helper/AnalyticsHelper';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const createState = (content, placeholder, plugins = []) => {
|
||||
return EditorState.create({
|
||||
@@ -265,7 +263,7 @@ export default {
|
||||
);
|
||||
this.state = this.editorView.state.apply(tr);
|
||||
this.emitOnChange();
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.USED_MENTIONS);
|
||||
this.$track(CONVERSATION_EVENTS.USED_MENTIONS);
|
||||
|
||||
return false;
|
||||
},
|
||||
@@ -295,7 +293,7 @@ export default {
|
||||
this.emitOnChange();
|
||||
|
||||
tr.scrollIntoView();
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.INSERTED_A_CANNED_RESPONSE);
|
||||
this.$track(CONVERSATION_EVENTS.INSERTED_A_CANNED_RESPONSE);
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
@@ -164,9 +164,7 @@ import { LocalStorage, LOCAL_STORAGE_KEYS } from '../../../helper/localStorage';
|
||||
import { trimContent, debounce } from '@chatwoot/utils';
|
||||
import wootConstants from 'dashboard/constants';
|
||||
import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../../helper/AnalyticsHelper';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const EmojiInput = () => import('shared/components/emoji/EmojiInput');
|
||||
|
||||
@@ -710,7 +708,7 @@ export default {
|
||||
},
|
||||
replaceText(message) {
|
||||
setTimeout(() => {
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.INSERTED_A_CANNED_RESPONSE);
|
||||
this.$track(CONVERSATION_EVENTS.INSERTED_A_CANNED_RESPONSE);
|
||||
this.message = message;
|
||||
}, 100);
|
||||
},
|
||||
|
||||
@@ -1,9 +1,73 @@
|
||||
export const EXECUTED_A_MACRO = 'Executed a macro';
|
||||
export const SENT_MESSAGE = 'Sent a message';
|
||||
export const SENT_PRIVATE_NOTE = 'Sent a private note';
|
||||
export const INSERTED_A_CANNED_RESPONSE = 'Inserted a canned response';
|
||||
export const USED_MENTIONS = 'Used mentions';
|
||||
export const MERGED_CONTACTS = 'Used merge contact option';
|
||||
export const ADDED_TO_CANNED_RESPONSE = 'Used added to canned response option';
|
||||
export const ADDED_A_CUSTOM_ATTRIBUTE = 'Added a custom attribute';
|
||||
export const ADDED_AN_INBOX = 'Added an inbox';
|
||||
export const CONVERSATION_EVENTS = Object.freeze({
|
||||
EXECUTED_A_MACRO: 'Executed a macro',
|
||||
SENT_MESSAGE: 'Sent a message',
|
||||
SENT_PRIVATE_NOTE: 'Sent a private note',
|
||||
INSERTED_A_CANNED_RESPONSE: 'Inserted a canned response',
|
||||
USED_MENTIONS: 'Used mentions',
|
||||
});
|
||||
|
||||
export const ACCOUNT_EVENTS = Object.freeze({
|
||||
ADDED_TO_CANNED_RESPONSE: 'Used added to canned response option',
|
||||
ADDED_A_CUSTOM_ATTRIBUTE: 'Added a custom attribute',
|
||||
ADDED_AN_INBOX: 'Added an inbox',
|
||||
});
|
||||
|
||||
export const LABEL_EVENTS = Object.freeze({
|
||||
CREATE: 'Created a label',
|
||||
UPDATE: 'Updated a label',
|
||||
DELETED: 'Deleted a label',
|
||||
APPLY_LABEL: 'Applied a label',
|
||||
});
|
||||
|
||||
// REPORTS EVENTS
|
||||
export const REPORTS_EVENTS = Object.freeze({
|
||||
DOWNLOAD_REPORT: 'Downloaded a report',
|
||||
FILTER_REPORT: 'Used filters in the reports',
|
||||
});
|
||||
|
||||
// CONTACTS PAGE EVENTS
|
||||
export const CONTACTS_EVENTS = Object.freeze({
|
||||
APPLY_FILTER: 'Applied filters in the contacts list',
|
||||
SAVE_FILTER: 'Saved a filter in the contacts list',
|
||||
DELETE_FILTER: 'Deleted a filter in the contacts list',
|
||||
|
||||
APPLY_SORT: 'Sorted contacts list',
|
||||
SEARCH: 'Searched contacts list',
|
||||
CREATE_CONTACT: 'Created a contact',
|
||||
MERGED_CONTACTS: 'Used merge contact option',
|
||||
IMPORT_MODAL_OPEN: 'Opened import contacts modal',
|
||||
IMPORT_FAILURE: 'Import contacts failed',
|
||||
IMPORT_SUCCESS: 'Imported contacts successfully',
|
||||
});
|
||||
|
||||
// CAMPAIGN EVENTS
|
||||
export const CAMPAIGNS_EVENTS = Object.freeze({
|
||||
OPEN_NEW_CAMPAIGN_MODAL: 'Opened new campaign modal',
|
||||
CREATE_CAMPAIGN: 'Created a new campaign',
|
||||
UPDATE_CAMPAIGN: 'Updated a campaign',
|
||||
DELETE_CAMPAIGN: 'Deleted a campaign',
|
||||
});
|
||||
|
||||
// PORTAL EVENTS
|
||||
export const PORTALS_EVENTS = Object.freeze({
|
||||
ONBOARD_BASIC_INFORMATION: 'New Portal: Completed basic information',
|
||||
ONBOARD_CUSTOMIZATION: 'New portal: Completed customization',
|
||||
CREATE_PORTAL: 'Created a portal',
|
||||
DELETE_PORTAL: 'Deleted a portal',
|
||||
UPDATE_PORTAL: 'Updated a portal',
|
||||
|
||||
CREATE_LOCALE: 'Created a portal locale',
|
||||
SET_DEFAULT_LOCALE: 'Set default portal locale',
|
||||
DELETE_LOCALE: 'Deleted a portal locale',
|
||||
SWITCH_LOCALE: 'Switched portal locale',
|
||||
|
||||
CREATE_CATEGORY: 'Created a portal category',
|
||||
DELETE_CATEGORY: 'Deleted a portal category',
|
||||
EDIT_CATEGORY: 'Edited a portal category',
|
||||
|
||||
CREATE_ARTICLE: 'Created an article',
|
||||
PUBLISH_ARTICLE: 'Published an article',
|
||||
ARCHIVE_ARTICLE: 'Archived an article',
|
||||
DELETE_ARTICLE: 'Deleted an article',
|
||||
PREVIEW_ARTICLE: 'Previewed article',
|
||||
});
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
import { AnalyticsBrowser } from '@june-so/analytics-next';
|
||||
|
||||
class AnalyticsHelper {
|
||||
/**
|
||||
* AnalyticsHelper class to initialize and track user analytics
|
||||
* @class AnalyticsHelper
|
||||
*/
|
||||
export class AnalyticsHelper {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Object} [options={}] - options for analytics
|
||||
* @param {string} [options.token] - analytics token
|
||||
*/
|
||||
constructor({ token: analyticsToken } = {}) {
|
||||
this.analyticsToken = analyticsToken;
|
||||
this.analytics = null;
|
||||
this.user = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize analytics
|
||||
* @function
|
||||
* @async
|
||||
*/
|
||||
async init() {
|
||||
if (!this.analyticsToken) {
|
||||
return;
|
||||
@@ -18,6 +32,11 @@ class AnalyticsHelper {
|
||||
this.analytics = analytics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the user
|
||||
* @function
|
||||
* @param {Object} user - User object
|
||||
*/
|
||||
identify(user) {
|
||||
if (!this.analytics) {
|
||||
return;
|
||||
@@ -41,6 +60,12 @@ class AnalyticsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track any event
|
||||
* @function
|
||||
* @param {string} eventName - event name
|
||||
* @param {Object} [properties={}] - event properties
|
||||
*/
|
||||
track(eventName, properties = {}) {
|
||||
if (!this.analytics) {
|
||||
return;
|
||||
@@ -53,6 +78,11 @@ class AnalyticsHelper {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Track the page views
|
||||
* @function
|
||||
* @param {Object} params - Page view properties
|
||||
*/
|
||||
page(params) {
|
||||
if (!this.analytics) {
|
||||
return;
|
||||
@@ -62,6 +92,5 @@ class AnalyticsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
export * as ANALYTICS_EVENTS from './events';
|
||||
|
||||
// This object is shared across, the init is called in app/javascript/packs/application.js
|
||||
export default new AnalyticsHelper(window.analyticsConfig);
|
||||
|
||||
11
app/javascript/dashboard/helper/AnalyticsHelper/plugin.js
Normal file
11
app/javascript/dashboard/helper/AnalyticsHelper/plugin.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import analyticsHelper from '.';
|
||||
|
||||
export default {
|
||||
// This function is called when the Vue plugin is installed
|
||||
install(Vue) {
|
||||
analyticsHelper.init();
|
||||
Vue.prototype.$analytics = analyticsHelper;
|
||||
// Add a shorthand function for the track method on the helper module
|
||||
Vue.prototype.$track = analyticsHelper.track.bind(analyticsHelper);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as AnalyticsEvents from '../events';
|
||||
|
||||
describe('Analytics Events', () => {
|
||||
it('should be frozen', () => {
|
||||
Object.entries(AnalyticsEvents).forEach(([, value]) => {
|
||||
expect(Object.isFrozen(value)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('event names should be unique across the board', () => {
|
||||
const allValues = Object.values(AnalyticsEvents).reduce(
|
||||
(acc, curr) => acc.concat(Object.values(curr)),
|
||||
[]
|
||||
);
|
||||
const uniqueValues = new Set(allValues);
|
||||
expect(allValues.length).toBe(uniqueValues.size);
|
||||
});
|
||||
|
||||
it('should not allow properties to be modified', () => {
|
||||
Object.values(AnalyticsEvents).forEach(eventsObject => {
|
||||
expect(() => {
|
||||
eventsObject.NEW_PROPERTY = 'new value';
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,139 @@
|
||||
import helperObject, { AnalyticsHelper } from '../';
|
||||
|
||||
jest.mock('@june-so/analytics-next', () => ({
|
||||
AnalyticsBrowser: {
|
||||
load: () => [
|
||||
{
|
||||
identify: jest.fn(),
|
||||
track: jest.fn(),
|
||||
page: jest.fn(),
|
||||
group: jest.fn(),
|
||||
},
|
||||
],
|
||||
},
|
||||
}));
|
||||
|
||||
describe('helperObject', () => {
|
||||
it('should return an instance of AnalyticsHelper', () => {
|
||||
expect(helperObject).toBeInstanceOf(AnalyticsHelper);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AnalyticsHelper', () => {
|
||||
let analyticsHelper;
|
||||
beforeEach(() => {
|
||||
analyticsHelper = new AnalyticsHelper({ token: 'test_token' });
|
||||
});
|
||||
|
||||
describe('init', () => {
|
||||
it('should initialize the analytics browser with the correct token', async () => {
|
||||
await analyticsHelper.init();
|
||||
expect(analyticsHelper.analytics).not.toBe(null);
|
||||
});
|
||||
|
||||
it('should not initialize the analytics browser if token is not provided', async () => {
|
||||
analyticsHelper = new AnalyticsHelper();
|
||||
await analyticsHelper.init();
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('identify', () => {
|
||||
beforeEach(() => {
|
||||
analyticsHelper.analytics = { identify: jest.fn(), group: jest.fn() };
|
||||
});
|
||||
|
||||
it('should call identify on analytics browser with correct arguments', () => {
|
||||
analyticsHelper.identify({
|
||||
id: '123',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar_url: 'avatar_url',
|
||||
accounts: [{ id: '1', name: 'Account 1' }],
|
||||
account_id: '1',
|
||||
});
|
||||
|
||||
expect(analyticsHelper.analytics.identify).toHaveBeenCalledWith(
|
||||
'test@example.com',
|
||||
{
|
||||
userId: '123',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar: 'avatar_url',
|
||||
}
|
||||
);
|
||||
expect(analyticsHelper.analytics.group).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call identify on analytics browser without group', () => {
|
||||
analyticsHelper.identify({
|
||||
id: '123',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar_url: 'avatar_url',
|
||||
accounts: [{ id: '1', name: 'Account 1' }],
|
||||
account_id: '5',
|
||||
});
|
||||
|
||||
expect(analyticsHelper.analytics.group).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call analytics.page if analytics is null', () => {
|
||||
analyticsHelper.analytics = null;
|
||||
analyticsHelper.identify({});
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('track', () => {
|
||||
beforeEach(() => {
|
||||
analyticsHelper.analytics = { track: jest.fn() };
|
||||
analyticsHelper.user = { id: '123' };
|
||||
});
|
||||
|
||||
it('should call track on analytics browser with correct arguments', () => {
|
||||
analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' });
|
||||
expect(analyticsHelper.analytics.track).toHaveBeenCalledWith({
|
||||
userId: '123',
|
||||
event: 'Test Event',
|
||||
properties: { prop1: 'value1', prop2: 'value2' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should call track on analytics browser with default properties', () => {
|
||||
analyticsHelper.track('Test Event');
|
||||
expect(analyticsHelper.analytics.track).toHaveBeenCalledWith({
|
||||
userId: '123',
|
||||
event: 'Test Event',
|
||||
properties: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call track on analytics browser if analytics is not initialized', () => {
|
||||
analyticsHelper.analytics = null;
|
||||
analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' });
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('page', () => {
|
||||
beforeEach(() => {
|
||||
analyticsHelper.analytics = { page: jest.fn() };
|
||||
});
|
||||
|
||||
it('should call the analytics.page method with the correct arguments', () => {
|
||||
const params = {
|
||||
name: 'Test page',
|
||||
url: '/test',
|
||||
};
|
||||
analyticsHelper.page(params);
|
||||
expect(analyticsHelper.analytics.page).toHaveBeenCalledWith(params);
|
||||
});
|
||||
|
||||
it('should not call analytics.page if analytics is null', () => {
|
||||
analyticsHelper.analytics = null;
|
||||
analyticsHelper.page();
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import Vue from 'vue';
|
||||
import plugin from '../plugin';
|
||||
import analyticsHelper from '../index';
|
||||
|
||||
describe('Vue Analytics Plugin', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(analyticsHelper, 'init');
|
||||
jest.spyOn(analyticsHelper, 'track');
|
||||
Vue.use(plugin);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetModules();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should call the init method on the analyticsHelper', () => {
|
||||
expect(analyticsHelper.init).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should add the analyticsHelper to the Vue prototype', () => {
|
||||
expect(Vue.prototype.$analytics).toBe(analyticsHelper);
|
||||
});
|
||||
|
||||
it('should add the track method to the Vue prototype', () => {
|
||||
expect(typeof Vue.prototype.$track).toBe('function');
|
||||
Vue.prototype.$track('eventName');
|
||||
expect(analyticsHelper.track).toHaveBeenCalledWith('eventName');
|
||||
});
|
||||
|
||||
it('should call the track method on the analyticsHelper when $track is called', () => {
|
||||
Vue.prototype.$track('eventName');
|
||||
expect(analyticsHelper.track).toHaveBeenCalledWith('eventName');
|
||||
});
|
||||
});
|
||||
@@ -24,9 +24,7 @@ import MergeContact from 'dashboard/modules/contact/components/MergeContact';
|
||||
import ContactAPI from 'dashboard/api/contacts';
|
||||
|
||||
import { mapGetters } from 'vuex';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../helper/AnalyticsHelper';
|
||||
import { CONTACTS_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: { MergeContact },
|
||||
@@ -75,7 +73,7 @@ export default {
|
||||
}
|
||||
},
|
||||
async onMergeContacts(childContactId) {
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.MERGED_CONTACTS);
|
||||
this.$track(CONTACTS_EVENTS.MERGED_CONTACTS);
|
||||
try {
|
||||
await this.$store.dispatch('contacts/merge', {
|
||||
childId: childContactId,
|
||||
|
||||
@@ -72,9 +72,7 @@ import AddCannedModal from 'dashboard/routes/dashboard/settings/canned/AddCanned
|
||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem';
|
||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu';
|
||||
import { copyTextToClipboard } from 'shared/helpers/clipboard';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../../helper/AnalyticsHelper';
|
||||
import { ACCOUNT_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -130,7 +128,7 @@ export default {
|
||||
this.$emit('toggle', false);
|
||||
},
|
||||
showCannedResponseModal() {
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.ADDED_TO_CANNED_RESPONSE);
|
||||
this.$track(ACCOUNT_EVENTS.ADDED_TO_CANNED_RESPONSE);
|
||||
this.isCannedResponseModalOpen = true;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -70,6 +70,7 @@ import { mapGetters } from 'vuex';
|
||||
import { filterAttributeGroups } from '../contactFilterItems';
|
||||
import filterMixin from 'shared/mixins/filterMixin';
|
||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
export default {
|
||||
components: {
|
||||
FilterInputBox,
|
||||
@@ -251,6 +252,12 @@ export default {
|
||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||
);
|
||||
this.$emit('applyFilter', this.appliedFilters);
|
||||
this.$track(CONTACTS_EVENTS.APPLY_FILTER, {
|
||||
applied_filters: this.appliedFilters.map(filter => ({
|
||||
key: filter.attribute_key,
|
||||
operator: filter.filter_operator,
|
||||
})),
|
||||
});
|
||||
},
|
||||
resetFilter(index, currentFilter) {
|
||||
this.appliedFilters[index].filter_operator = this.filterTypes.find(
|
||||
|
||||
@@ -86,6 +86,7 @@ import contactFilterItems from '../contactFilterItems';
|
||||
import filterQueryGenerator from '../../../../helper/filterQueryGenerator';
|
||||
import AddCustomViews from 'dashboard/routes/dashboard/customviews/AddCustomViews';
|
||||
import DeleteCustomViews from 'dashboard/routes/dashboard/customviews/DeleteCustomViews';
|
||||
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const DEFAULT_PAGE = 1;
|
||||
const FILTER_TYPE_CONTACT = 1;
|
||||
@@ -334,6 +335,14 @@ export default {
|
||||
onSortChange(params) {
|
||||
this.sortConfig = params;
|
||||
this.fetchContacts(this.meta.currentPage);
|
||||
|
||||
const sortBy =
|
||||
Object.entries(params).find(pair => Boolean(pair[1])) || [];
|
||||
|
||||
this.$track(CONTACTS_EVENTS.APPLY_SORT, {
|
||||
appliedOn: sortBy[0],
|
||||
order: sortBy[1],
|
||||
});
|
||||
},
|
||||
onToggleFilters() {
|
||||
this.showFiltersModal = !this.showFiltersModal;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
import Modal from '../../../../components/Modal';
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -71,6 +72,9 @@ export default {
|
||||
return '/downloads/import-contacts-sample.csv';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$track(CONTACTS_EVENTS.IMPORT_MODAL_OPEN);
|
||||
},
|
||||
methods: {
|
||||
async uploadFile() {
|
||||
try {
|
||||
@@ -78,10 +82,12 @@ export default {
|
||||
await this.$store.dispatch('contacts/import', this.file);
|
||||
this.onClose();
|
||||
this.showAlert(this.$t('IMPORT_CONTACTS.SUCCESS_MESSAGE'));
|
||||
this.$track(CONTACTS_EVENTS.IMPORT_SUCCESS);
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
error.message || this.$t('IMPORT_CONTACTS.ERROR_MESSAGE')
|
||||
);
|
||||
this.$track(CONTACTS_EVENTS.IMPORT_FAILURE);
|
||||
}
|
||||
},
|
||||
handleFileUpload() {
|
||||
|
||||
@@ -35,9 +35,8 @@
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import MacroPreview from './MacroPreview';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../../../helper/AnalyticsHelper';
|
||||
import { CONVERSATION_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MacroPreview,
|
||||
@@ -67,7 +66,7 @@ export default {
|
||||
macroId: macro.id,
|
||||
conversationIds: [this.conversationId],
|
||||
});
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.EXECUTED_A_MACRO);
|
||||
this.$track(CONVERSATION_EVENTS.EXECUTED_A_MACRO);
|
||||
this.showAlert(this.$t('MACROS.EXECUTE.EXECUTED_SUCCESSFULLY'));
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('MACROS.ERROR'));
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<script>
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
@@ -89,6 +90,10 @@ export default {
|
||||
? this.$t('FILTER.CUSTOM_VIEWS.ADD.API_FOLDERS.SUCCESS_MESSAGE')
|
||||
: this.$t('FILTER.CUSTOM_VIEWS.ADD.API_SEGMENTS.SUCCESS_MESSAGE');
|
||||
this.onClose();
|
||||
|
||||
this.$track(CONTACTS_EVENTS.SAVE_FILTER, {
|
||||
type: this.filterType === 0 ? 'folder' : 'segment',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error?.message;
|
||||
this.alertMessage =
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
@@ -82,6 +83,9 @@ export default {
|
||||
? this.$t('FILTER.CUSTOM_VIEWS.DELETE.API_FOLDERS.SUCCESS_MESSAGE')
|
||||
: this.$t('FILTER.CUSTOM_VIEWS.DELETE.API_SEGMENTS.SUCCESS_MESSAGE')
|
||||
);
|
||||
this.$track(CONTACTS_EVENTS.DELETE_FILTER, {
|
||||
type: this.filterType === 0 ? 'folder' : 'segment',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error?.response?.message || this.activeFilterType === 0
|
||||
|
||||
@@ -42,6 +42,7 @@ import Modal from 'dashboard/components/Modal';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import allLocales from 'shared/constants/locales.js';
|
||||
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
@@ -108,6 +109,11 @@ export default {
|
||||
'HELP_CENTER.PORTAL.ADD_LOCALE.API.SUCCESS_MESSAGE'
|
||||
);
|
||||
this.onClose();
|
||||
this.$track(PORTALS_EVENTS.CREATE_LOCALE, {
|
||||
localeAdded: this.selectedLocale,
|
||||
totalLocales: updatedLocales.length,
|
||||
from: this.$route.name,
|
||||
});
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message ||
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import wootConstants from 'dashboard/constants.js';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const { ARTICLE_STATUS_TYPES } = wootConstants;
|
||||
|
||||
@@ -186,6 +187,11 @@ export default {
|
||||
});
|
||||
this.statusUpdateSuccessMessage(status);
|
||||
this.closeActionsDropdown();
|
||||
if (status === this.ARTICLE_STATUS_TYPES.ARCHIVE) {
|
||||
this.$track(PORTALS_EVENTS.ARCHIVE_ARTICLE, { uiFrom: 'header' });
|
||||
} else if (status === this.ARTICLE_STATUS_TYPES.PUBLISH) {
|
||||
this.$track(PORTALS_EVENTS.PUBLISH_ARTICLE);
|
||||
}
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message || this.statusUpdateErrorMessage(status);
|
||||
|
||||
@@ -190,6 +190,7 @@ import thumbnail from 'dashboard/components/widgets/Thumbnail';
|
||||
import LocaleItemTable from './PortalListItemTable';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -309,6 +310,10 @@ export default {
|
||||
'HELP_CENTER.PORTAL.CHANGE_DEFAULT_LOCALE.API.ERROR_MESSAGE'
|
||||
),
|
||||
});
|
||||
this.$track(PORTALS_EVENTS.SET_DEFAULT_LOCALE, {
|
||||
newLocale: localeCode,
|
||||
from: this.$route.name,
|
||||
});
|
||||
},
|
||||
deletePortalLocale({ localeCode }) {
|
||||
const updatedLocales = this.allowedLocales.filter(
|
||||
@@ -325,6 +330,10 @@ export default {
|
||||
'HELP_CENTER.PORTAL.DELETE_LOCALE.API.ERROR_MESSAGE'
|
||||
),
|
||||
});
|
||||
this.$track(PORTALS_EVENTS.DELETE_LOCALE, {
|
||||
deletedLocale: localeCode,
|
||||
from: this.$route.name,
|
||||
});
|
||||
},
|
||||
async updatePortalLocales({
|
||||
allowedLocales,
|
||||
|
||||
@@ -53,6 +53,7 @@ import portalMixin from '../../mixins/portalMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import wootConstants from 'dashboard/constants';
|
||||
import { buildPortalArticleURL } from 'dashboard/helper/portalHelper';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const { ARTICLE_STATUS_TYPES } = wootConstants;
|
||||
export default {
|
||||
@@ -118,6 +119,9 @@ export default {
|
||||
confirmDeletion() {
|
||||
this.closeDeletePopup();
|
||||
this.deleteArticle();
|
||||
this.$track(PORTALS_EVENTS.DELETE_ARTICLE, {
|
||||
status: this.article?.status,
|
||||
});
|
||||
},
|
||||
async saveArticle({ ...values }) {
|
||||
this.isUpdating = true;
|
||||
@@ -171,6 +175,7 @@ export default {
|
||||
status: ARTICLE_STATUS_TYPES.ARCHIVE,
|
||||
});
|
||||
this.alertMessage = this.$t('HELP_CENTER.ARCHIVE_ARTICLE.API.SUCCESS');
|
||||
this.$track(PORTALS_EVENTS.ARCHIVE_ARTICLE, { uiFrom: 'sidebar' });
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message || this.$t('HELP_CENTER.ARCHIVE_ARTICLE.API.ERROR');
|
||||
@@ -186,6 +191,9 @@ export default {
|
||||
},
|
||||
showArticleInPortal() {
|
||||
window.open(this.portalLink, '_blank');
|
||||
this.$track(PORTALS_EVENTS.PREVIEW_ARTICLE, {
|
||||
status: this.article?.status,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ import ArticleEditor from '../../components/ArticleEditor.vue';
|
||||
import portalMixin from '../../mixins/portalMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin.js';
|
||||
import ArticleSettings from './ArticleSettings.vue';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
export default {
|
||||
components: {
|
||||
EditArticleHeader,
|
||||
@@ -91,6 +92,9 @@ export default {
|
||||
recentlyCreated: true,
|
||||
},
|
||||
});
|
||||
this.$track(PORTALS_EVENTS.CREATE_ARTICLE, {
|
||||
locale: this.locale,
|
||||
});
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message ||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
@@ -158,6 +159,9 @@ export default {
|
||||
'HELP_CENTER.CATEGORY.ADD.API.SUCCESS_MESSAGE'
|
||||
);
|
||||
this.onClose();
|
||||
this.$track(PORTALS_EVENTS.CREATE_CATEGORY, {
|
||||
hasDescription: Boolean(description),
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error?.message;
|
||||
this.alertMessage =
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
variant="smooth"
|
||||
icon="delete"
|
||||
color-scheme="alert"
|
||||
@click="deleteCategory(category.id)"
|
||||
@click="deleteCategory(category)"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -83,8 +83,8 @@ export default {
|
||||
editCategory(category) {
|
||||
this.$emit('edit', category);
|
||||
},
|
||||
deleteCategory(categoryId) {
|
||||
this.$emit('delete', categoryId);
|
||||
deleteCategory(category) {
|
||||
this.$emit('delete', category);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
@@ -166,6 +167,7 @@ export default {
|
||||
this.alertMessage = this.$t(
|
||||
'HELP_CENTER.CATEGORY.EDIT.API.SUCCESS_MESSAGE'
|
||||
);
|
||||
this.$track(PORTALS_EVENTS.EDIT_CATEGORY);
|
||||
this.onClose();
|
||||
} catch (error) {
|
||||
const errorMessage = error?.message;
|
||||
|
||||
@@ -64,6 +64,7 @@ import portalMixin from '../../mixins/portalMixin';
|
||||
import CategoryListItem from './CategoryListItem';
|
||||
import AddCategory from './AddCategory';
|
||||
import EditCategory from './EditCategory';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -137,15 +138,18 @@ export default {
|
||||
locale: localeCode,
|
||||
});
|
||||
},
|
||||
async deleteCategory(categoryId) {
|
||||
async deleteCategory(category) {
|
||||
try {
|
||||
await this.$store.dispatch('categories/delete', {
|
||||
portalSlug: this.currentPortalSlug,
|
||||
categoryId: categoryId,
|
||||
categoryId: category.id,
|
||||
});
|
||||
this.alertMessage = this.$t(
|
||||
'HELP_CENTER.CATEGORY.DELETE.API.SUCCESS_MESSAGE'
|
||||
);
|
||||
this.$track(PORTALS_EVENTS.DELETE_CATEGORY, {
|
||||
hasArticles: category?.meta?.articles_count !== 0,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error?.message;
|
||||
this.alertMessage =
|
||||
|
||||
@@ -36,6 +36,7 @@ import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import LocaleItemTable from 'dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue';
|
||||
import AddLocale from 'dashboard/routes/dashboard/helpcenter/components/AddLocale';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
export default {
|
||||
components: {
|
||||
LocaleItemTable,
|
||||
@@ -85,6 +86,10 @@ export default {
|
||||
'HELP_CENTER.PORTAL.CHANGE_DEFAULT_LOCALE.API.ERROR_MESSAGE'
|
||||
),
|
||||
});
|
||||
this.$track(PORTALS_EVENTS.SET_DEFAULT_LOCALE, {
|
||||
newLocale: localeCode,
|
||||
from: this.$route.name,
|
||||
});
|
||||
},
|
||||
deletePortalLocale({ localeCode }) {
|
||||
const updatedLocales = this.allowedLocales.filter(
|
||||
@@ -101,6 +106,10 @@ export default {
|
||||
'HELP_CENTER.PORTAL.DELETE_LOCALE.API.ERROR_MESSAGE'
|
||||
),
|
||||
});
|
||||
this.$track(PORTALS_EVENTS.DELETE_LOCALE, {
|
||||
deletedLocale: localeCode,
|
||||
from: this.$route.name,
|
||||
});
|
||||
},
|
||||
async updatePortalLocales({
|
||||
allowedLocales,
|
||||
|
||||
@@ -17,6 +17,7 @@ import PortalSettingsCustomizationForm from 'dashboard/routes/dashboard/helpcent
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import { getRandomColor } from 'dashboard/helper/labelColor';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -52,7 +53,6 @@ export default {
|
||||
},
|
||||
async updatePortalSettings(portalObj) {
|
||||
const portalSlug = this.$route.params.portalSlug;
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('portals/update', {
|
||||
portalSlug,
|
||||
@@ -61,6 +61,12 @@ export default {
|
||||
this.alertMessage = this.$t(
|
||||
'HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE'
|
||||
);
|
||||
|
||||
this.$track(PORTALS_EVENTS.ONBOARD_CUSTOMIZATION, {
|
||||
hasHomePageLink: Boolean(portalObj.homepage_link),
|
||||
hasPageTitle: Boolean(portalObj.page_title),
|
||||
hasHeaderText: Boolean(portalObj.headerText),
|
||||
});
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message ||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
import PortalSettingsBasicForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm';
|
||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -49,6 +50,11 @@ export default {
|
||||
name: 'portal_customization',
|
||||
params: { portalSlug: portal.slug },
|
||||
});
|
||||
const analyticsPayload = {
|
||||
has_custom_domain: portal.domain !== '',
|
||||
};
|
||||
this.$track(PORTALS_EVENTS.ONBOARD_BASIC_INFORMATION, analyticsPayload);
|
||||
this.$track(PORTALS_EVENTS.CREATE_PORTAL, analyticsPayload);
|
||||
} catch (error) {
|
||||
this.alertMessage =
|
||||
error?.message ||
|
||||
|
||||
@@ -177,6 +177,7 @@ import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor';
|
||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
||||
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
|
||||
import { URLPattern } from 'urlpattern-polyfill';
|
||||
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -275,6 +276,11 @@ export default {
|
||||
];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$track(CAMPAIGNS_EVENTS.OPEN_NEW_CAMPAIGN_MODAL, {
|
||||
type: this.campaignType,
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('on-close');
|
||||
@@ -339,6 +345,12 @@ export default {
|
||||
try {
|
||||
const campaignDetails = this.getCampaignDetails();
|
||||
await this.$store.dispatch('campaigns/create', campaignDetails);
|
||||
|
||||
// tracking this here instead of the store to track the type of campaign
|
||||
this.$track(CAMPAIGNS_EVENTS.CREATE_CAMPAIGN, {
|
||||
type: this.campaignType,
|
||||
});
|
||||
|
||||
this.showAlert(this.$t('CAMPAIGN.ADD.API.SUCCESS_MESSAGE'));
|
||||
this.onClose();
|
||||
} catch (error) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import CsatTable from './components/CsatTable';
|
||||
import ReportFilterSelector from './components/FilterSelector';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { generateFileName } from '../../../../helper/downloadHelper';
|
||||
import { REPORTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
name: 'CsatResponses',
|
||||
@@ -66,6 +67,13 @@ export default {
|
||||
this.getResponses();
|
||||
},
|
||||
onDateRangeChange({ from, to }) {
|
||||
// do not track filter change on inital load
|
||||
if (this.from !== 0 && this.to !== 0) {
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'date',
|
||||
reportType: 'csat',
|
||||
});
|
||||
}
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.getAllData();
|
||||
@@ -73,6 +81,10 @@ export default {
|
||||
onAgentsFilterChange(agents) {
|
||||
this.userIds = agents.map(el => el.id);
|
||||
this.getAllData();
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'agent',
|
||||
reportType: 'csat',
|
||||
});
|
||||
},
|
||||
downloadReports() {
|
||||
const type = 'csat';
|
||||
|
||||
@@ -58,6 +58,7 @@ import ReportFilterSelector from './components/FilterSelector';
|
||||
import { GROUP_BY_FILTER, METRIC_CHART } from './constants';
|
||||
import reportMixin from '../../../../mixins/reportMixin';
|
||||
import { formatTime } from '@chatwoot/utils';
|
||||
import { REPORTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const REPORTS_KEYS = {
|
||||
CONVERSATIONS: 'conversations_count',
|
||||
@@ -222,6 +223,13 @@ export default {
|
||||
this.fetchChartData();
|
||||
},
|
||||
onDateRangeChange({ from, to, groupBy }) {
|
||||
// do not track filter change on inital load
|
||||
if (this.from !== 0 && this.to !== 0) {
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'date',
|
||||
reportType: 'conversations',
|
||||
});
|
||||
}
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.filterItemsList = this.fetchFilterItems(groupBy);
|
||||
@@ -239,6 +247,12 @@ export default {
|
||||
onFilterChange(payload) {
|
||||
this.groupBy = GROUP_BY_FILTER[payload.id];
|
||||
this.fetchAllData();
|
||||
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'groupBy',
|
||||
filterValue: this.groupBy?.period,
|
||||
reportType: 'conversations',
|
||||
});
|
||||
},
|
||||
fetchFilterItems(group_by) {
|
||||
switch (group_by) {
|
||||
@@ -255,6 +269,12 @@ export default {
|
||||
onBusinessHoursToggle(value) {
|
||||
this.businessHours = value;
|
||||
this.fetchAllData();
|
||||
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'businessHours',
|
||||
filterValue: value,
|
||||
reportType: 'conversations',
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -62,6 +62,7 @@ import { GROUP_BY_FILTER, METRIC_CHART } from '../constants';
|
||||
import reportMixin from '../../../../../mixins/reportMixin';
|
||||
import { formatTime } from '@chatwoot/utils';
|
||||
import { generateFileName } from '../../../../../helper/downloadHelper';
|
||||
import { REPORTS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const REPORTS_KEYS = {
|
||||
CONVERSATIONS: 'conversations_count',
|
||||
@@ -269,6 +270,14 @@ export default {
|
||||
this.fetchChartData();
|
||||
},
|
||||
onDateRangeChange({ from, to, groupBy }) {
|
||||
// do not track filter change on inital load
|
||||
if (this.from !== 0 && this.to !== 0) {
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'date',
|
||||
reportType: this.type,
|
||||
});
|
||||
}
|
||||
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.groupByfilterItemsList = this.fetchFilterItems(groupBy);
|
||||
@@ -292,6 +301,12 @@ export default {
|
||||
onGroupByFilterChange(payload) {
|
||||
this.groupBy = GROUP_BY_FILTER[payload.id];
|
||||
this.fetchAllData();
|
||||
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'groupBy',
|
||||
filterValue: this.groupBy?.period,
|
||||
reportType: this.type,
|
||||
});
|
||||
},
|
||||
fetchFilterItems(group_by) {
|
||||
switch (group_by) {
|
||||
@@ -308,6 +323,12 @@ export default {
|
||||
onBusinessHoursToggle(value) {
|
||||
this.businessHours = value;
|
||||
this.fetchAllData();
|
||||
|
||||
this.$track(REPORTS_EVENTS.FILTER_REPORT, {
|
||||
filterType: 'businessHours',
|
||||
filterValue: value,
|
||||
reportType: this.type,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
||||
import types from '../mutation-types';
|
||||
import CampaignsAPI from '../../api/campaigns';
|
||||
import AnalyticsHelper from '../../helper/AnalyticsHelper';
|
||||
import { CAMPAIGNS_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
export const state = {
|
||||
records: [],
|
||||
@@ -51,6 +53,7 @@ export const actions = {
|
||||
commit(types.SET_CAMPAIGN_UI_FLAG, { isUpdating: true });
|
||||
try {
|
||||
const response = await CampaignsAPI.update(id, updateObj);
|
||||
AnalyticsHelper.track(CAMPAIGNS_EVENTS.UPDATE_CAMPAIGN);
|
||||
commit(types.EDIT_CAMPAIGN, response.data);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
@@ -62,6 +65,7 @@ export const actions = {
|
||||
commit(types.SET_CAMPAIGN_UI_FLAG, { isDeleting: true });
|
||||
try {
|
||||
await CampaignsAPI.delete(id);
|
||||
AnalyticsHelper.track(CAMPAIGNS_EVENTS.DELETE_CAMPAIGN);
|
||||
commit(types.DELETE_CAMPAIGN, id);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
|
||||
@@ -5,6 +5,8 @@ import {
|
||||
import types from '../../mutation-types';
|
||||
import ContactAPI from '../../../api/contacts';
|
||||
import AccountActionsAPI from '../../../api/accountActions';
|
||||
import AnalyticsHelper from '../../../helper/AnalyticsHelper';
|
||||
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
|
||||
const buildContactFormData = contactParams => {
|
||||
const formData = new FormData();
|
||||
@@ -104,6 +106,8 @@ export const actions = {
|
||||
const response = await ContactAPI.create(
|
||||
isFormData ? buildContactFormData(contactParams) : contactParams
|
||||
);
|
||||
|
||||
AnalyticsHelper.track(CONTACTS_EVENTS.CREATE_CONTACT);
|
||||
commit(types.SET_CONTACT_ITEM, response.data.payload.contact);
|
||||
commit(types.SET_CONTACT_UI_FLAG, { isCreating: false });
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,9 +10,8 @@ import {
|
||||
isOnUnattendedView,
|
||||
} from './helpers/actionHelpers';
|
||||
import messageReadActions from './actions/messageReadActions';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../../helper/AnalyticsHelper';
|
||||
import AnalyticsHelper from '../../../helper/AnalyticsHelper';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
// actions
|
||||
const actions = {
|
||||
getConversation: async ({ commit }, conversationId) => {
|
||||
@@ -176,8 +175,8 @@ const actions = {
|
||||
const response = await MessageApi.create(pendingMessage);
|
||||
AnalyticsHelper.track(
|
||||
pendingMessage.private
|
||||
? ANALYTICS_EVENTS.SENT_PRIVATE_NOTE
|
||||
: ANALYTICS_EVENTS.SENT_MESSAGE
|
||||
? CONVERSATION_EVENTS.CONVERSATION.SENT_PRIVATE_NOTE
|
||||
: CONVERSATION_EVENTS.CONVERSATION.SENT_MESSAGE
|
||||
);
|
||||
commit(types.ADD_MESSAGE, {
|
||||
...response.data,
|
||||
|
||||
@@ -2,6 +2,8 @@ import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
||||
import types from '../mutation-types';
|
||||
import CSATReports from '../../api/csatReports';
|
||||
import { downloadCsvFile } from '../../helper/downloadHelper';
|
||||
import AnalyticsHelper from '../../helper/AnalyticsHelper';
|
||||
import { REPORTS_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
const computeDistribution = (value, total) =>
|
||||
((value * 100) / total).toFixed(2);
|
||||
@@ -111,6 +113,9 @@ export const actions = {
|
||||
downloadCSATReports(_, params) {
|
||||
return CSATReports.download(params).then(response => {
|
||||
downloadCsvFile(params.fileName, response.data);
|
||||
AnalyticsHelper.track(REPORTS_EVENTS.DOWNLOAD_REPORT, {
|
||||
reportType: 'csat',
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,9 +6,8 @@ import WebChannel from '../../api/channel/webChannel';
|
||||
import FBChannel from '../../api/channel/fbChannel';
|
||||
import TwilioChannel from '../../api/channel/twilioChannel';
|
||||
import { throwErrorMessage } from '../utils/api';
|
||||
import AnalyticsHelper, {
|
||||
ANALYTICS_EVENTS,
|
||||
} from '../../helper/AnalyticsHelper';
|
||||
import AnalyticsHelper from '../../helper/AnalyticsHelper';
|
||||
import { ACCOUNT_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
const buildInboxData = inboxParams => {
|
||||
const formData = new FormData();
|
||||
@@ -121,7 +120,7 @@ export const getters = {
|
||||
};
|
||||
|
||||
const sendAnalyticsEvent = channelType => {
|
||||
AnalyticsHelper.track(ANALYTICS_EVENTS.ADDED_AN_INBOX, {
|
||||
AnalyticsHelper.track(ACCOUNT_EVENTS.ADDED_AN_INBOX, {
|
||||
channelType,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
||||
import types from '../mutation-types';
|
||||
import LabelsAPI from '../../api/labels';
|
||||
import AnalyticsHelper from '../../helper/AnalyticsHelper';
|
||||
import { LABEL_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
export const state = {
|
||||
records: [],
|
||||
@@ -43,6 +45,7 @@ export const actions = {
|
||||
commit(types.SET_LABEL_UI_FLAG, { isCreating: true });
|
||||
try {
|
||||
const response = await LabelsAPI.create(cannedObj);
|
||||
AnalyticsHelper.track(LABEL_EVENTS.CREATE);
|
||||
commit(types.ADD_LABEL, response.data);
|
||||
} catch (error) {
|
||||
const errorMessage = error?.response?.data?.message;
|
||||
@@ -56,6 +59,7 @@ export const actions = {
|
||||
commit(types.SET_LABEL_UI_FLAG, { isUpdating: true });
|
||||
try {
|
||||
const response = await LabelsAPI.update(id, updateObj);
|
||||
AnalyticsHelper.track(LABEL_EVENTS.UPDATE);
|
||||
commit(types.EDIT_LABEL, response.data);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
@@ -68,6 +72,7 @@ export const actions = {
|
||||
commit(types.SET_LABEL_UI_FLAG, { isDeleting: true });
|
||||
try {
|
||||
await LabelsAPI.delete(id);
|
||||
AnalyticsHelper.track(LABEL_EVENTS.DELETED);
|
||||
commit(types.DELETE_LABEL, id);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import * as types from '../mutation-types';
|
||||
import Report from '../../api/reports';
|
||||
import { downloadCsvFile } from '../../helper/downloadHelper';
|
||||
import AnalyticsHelper from '../../helper/AnalyticsHelper';
|
||||
import { REPORTS_EVENTS } from '../../helper/AnalyticsHelper/events';
|
||||
|
||||
const state = {
|
||||
fetchingStatus: false,
|
||||
@@ -116,6 +118,10 @@ export const actions = {
|
||||
return Report.getAgentReports(reportObj)
|
||||
.then(response => {
|
||||
downloadCsvFile(reportObj.fileName, response.data);
|
||||
AnalyticsHelper.track(REPORTS_EVENTS.DOWNLOAD_REPORT, {
|
||||
reportType: 'agent',
|
||||
businessHours: reportObj?.businessHours,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
@@ -125,6 +131,10 @@ export const actions = {
|
||||
return Report.getLabelReports(reportObj)
|
||||
.then(response => {
|
||||
downloadCsvFile(reportObj.fileName, response.data);
|
||||
AnalyticsHelper.track(REPORTS_EVENTS.DOWNLOAD_REPORT, {
|
||||
reportType: 'label',
|
||||
businessHours: reportObj?.businessHours,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
@@ -134,6 +144,10 @@ export const actions = {
|
||||
return Report.getInboxReports(reportObj)
|
||||
.then(response => {
|
||||
downloadCsvFile(reportObj.fileName, response.data);
|
||||
AnalyticsHelper.track(REPORTS_EVENTS.DOWNLOAD_REPORT, {
|
||||
reportType: 'inbox',
|
||||
businessHours: reportObj?.businessHours,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
@@ -143,6 +157,10 @@ export const actions = {
|
||||
return Report.getTeamReports(reportObj)
|
||||
.then(response => {
|
||||
downloadCsvFile(reportObj.fileName, response.data);
|
||||
AnalyticsHelper.track(REPORTS_EVENTS.DOWNLOAD_REPORT, {
|
||||
reportType: 'team',
|
||||
businessHours: reportObj?.businessHours,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
|
||||
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||
import { domPurifyConfig } from '../shared/helpers/HTMLSanitizer';
|
||||
import AnalyticsHelper from '../dashboard/helper/AnalyticsHelper';
|
||||
import AnalyticsPlugin from '../dashboard/helper/AnalyticsHelper/plugin';
|
||||
|
||||
Vue.config.env = process.env;
|
||||
|
||||
@@ -55,6 +55,7 @@ Vue.use(VTooltip, {
|
||||
defaultHtml: false,
|
||||
});
|
||||
Vue.use(hljs.vuePlugin);
|
||||
Vue.use(AnalyticsPlugin);
|
||||
|
||||
Vue.component('multiselect', Multiselect);
|
||||
Vue.component('woot-switch', WootSwitch);
|
||||
@@ -74,7 +75,6 @@ window.WootConstants = constants;
|
||||
window.axios = createAxios(axios);
|
||||
window.bus = new Vue();
|
||||
initializeChatwootEvents();
|
||||
AnalyticsHelper.init();
|
||||
initializeAnalyticsEvents();
|
||||
initalizeRouter();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user