feat: Configure Chatwoot & Analytics for SaaS app (#2975)

* feat: Add Chatwoot support inside Chatwoot SaaS
* Fix identity issues with Chatwoot
This commit is contained in:
Pranav Raj S
2021-09-07 23:11:01 +05:30
committed by GitHub
parent 8de4ce0037
commit 4759730022
12 changed files with 125 additions and 39 deletions

View File

@@ -23,7 +23,9 @@ class DashboardController < ActionController::Base
'CREATE_NEW_ACCOUNT_FROM_DASHBOARD',
'CHATWOOT_INBOX_TOKEN',
'API_CHANNEL_NAME',
'API_CHANNEL_THUMBNAIL'
'API_CHANNEL_THUMBNAIL',
'ANALYTICS_TOKEN',
'ANALYTICS_HOST'
).merge(
APP_VERSION: Chatwoot.config[:version]
)

View File

@@ -255,19 +255,11 @@ export default {
return frontendURL(`accounts/${this.accountId}/dashboard`);
},
},
watch: {
currentUser(newUserInfo, oldUserInfo) {
if (!oldUserInfo.email && newUserInfo.email) {
this.setChatwootUser();
}
},
},
mounted() {
this.$store.dispatch('labels/get');
this.$store.dispatch('inboxes/get');
this.$store.dispatch('notifications/unReadCount');
this.$store.dispatch('teams/get');
this.setChatwootUser();
},
methods: {
@@ -288,17 +280,6 @@ export default {
toggleSupportChatWindow() {
window.$chatwoot.toggle();
},
setChatwootUser() {
if (!this.currentUser.email || !this.globalConfig.chatwootInboxToken) {
return;
}
window.$chatwoot.setUser(this.currentUser.email, {
name: this.currentUser.name,
email: this.currentUser.email,
avatar_url: this.currentUser.avatar_url,
identifier_hash: this.currentUser.hmac_identifier,
});
},
filterMenuItemsByRole(menuItems) {
if (!this.currentRole) {
return [];

View File

@@ -94,10 +94,6 @@ export default {
methods: {
logout() {
Auth.logout();
if (this.globalConfig.chatwootInboxToken) {
window.$chatwoot.reset();
}
},
},
};

View File

@@ -0,0 +1,43 @@
import posthog from 'posthog-js';
export const CHATWOOT_SET_USER = 'CHATWOOT_SET_USER';
export const CHATWOOT_RESET = 'CHATWOOT_RESET';
export const ANALYTICS_IDENTITY = 'ANALYTICS_IDENTITY';
export const ANALYTICS_RESET = 'ANALYTICS_RESET';
export const initializeAnalyticsEvents = () => {
window.bus.$on(ANALYTICS_IDENTITY, ({ user }) => {
if (window.analyticsConfig) {
posthog.identify(user.id, { name: user.name, email: user.email });
}
});
window.bus.$on(ANALYTICS_RESET, () => {
if (window.analyticsConfig) {
posthog.reset();
}
});
};
export const initializeChatwootEvents = () => {
window.bus.$on(CHATWOOT_RESET, () => {
if (window.$chatwoot) {
window.$chatwoot.reset();
}
});
window.bus.$on(CHATWOOT_SET_USER, ({ user }) => {
if (window.$chatwoot) {
window.$chatwoot.setUser(user.email, {
avatar_url: user.avatar_url,
email: user.email,
identifier_hash: user.hmac_identifier,
name: user.name,
});
window.$chatwoot.setCustomAttributes({
signedUpAt: user.created_at,
cloudCustomer: 'true',
});
}
});
};

View File

@@ -81,7 +81,9 @@ export const actions = {
async validityCheck(context) {
try {
const response = await authAPI.validityCheck();
setUser(response.data.payload.data, getHeaderExpiry(response));
setUser(response.data.payload.data, getHeaderExpiry(response), {
setUserInSDK: true,
});
context.commit(types.default.SET_CURRENT_USER);
} catch (error) {
if (error?.response?.status === 401) {

View File

@@ -3,6 +3,12 @@ import fromUnixTime from 'date-fns/fromUnixTime';
import differenceInDays from 'date-fns/differenceInDays';
import Cookies from 'js-cookie';
import { frontendURL } from '../../helper/URLHelper';
import {
ANALYTICS_IDENTITY,
ANALYTICS_RESET,
CHATWOOT_RESET,
CHATWOOT_SET_USER,
} from '../../helper/scriptHelpers';
Cookies.defaults = { sameSite: 'Lax' };
@@ -11,10 +17,15 @@ export const setLoadingStatus = (state, status) => {
state.fetchAPIloadingStatus = status;
};
export const setUser = (userData, expiryDate) =>
Cookies.set('user', userData, {
export const setUser = (user, expiryDate, options = {}) => {
if (options && options.setUserInSDK) {
window.bus.$emit(CHATWOOT_SET_USER, { user });
window.bus.$emit(ANALYTICS_IDENTITY, { user });
}
Cookies.set('user', user, {
expires: differenceInDays(expiryDate, new Date()),
});
};
export const getHeaderExpiry = response =>
fromUnixTime(response.headers.expiry);
@@ -28,6 +39,9 @@ export const setAuthCredentials = response => {
};
export const clearCookiesOnLogout = () => {
window.bus.$emit(CHATWOOT_RESET);
window.bus.$emit(ANALYTICS_RESET);
Cookies.remove('auth_data');
Cookies.remove('user');
window.location = frontendURL('login');

View File

@@ -34,6 +34,11 @@ import {
import * as Sentry from '@sentry/vue';
import 'vue-easytable/libs/theme-default/index.css';
import { Integrations } from '@sentry/tracing';
import posthog from 'posthog-js';
import {
initializeAnalyticsEvents,
initializeChatwootEvents,
} from '../dashboard/helper/scriptHelpers';
Vue.config.env = process.env;
@@ -45,6 +50,12 @@ if (window.errorLoggingConfig) {
});
}
if (window.analyticsConfig) {
posthog.init(window.analyticsConfig.token, {
api_host: window.analyticsConfig.host,
});
}
Vue.use(VueRouter);
Vue.use(VueI18n);
Vue.use(WootUiKit);
@@ -75,6 +86,9 @@ commonHelpers();
window.WootConstants = constants;
window.axios = createAxios(axios);
window.bus = new Vue();
initializeChatwootEvents();
initializeAnalyticsEvents();
window.onload = () => {
window.WOOT = new Vue({
router,
@@ -85,6 +99,7 @@ window.onload = () => {
}).$mount('#app');
vueActionCable.init();
};
window.addEventListener('load', () => {
verifyServiceWorkerExistence(registration =>
registration.pushManager.getSubscription().then(subscription => {

View File

@@ -1,4 +1,7 @@
json.payload do
json.success true
json.partial! 'auth.json.jbuilder', resource: @resource
json.data do
json.created_at @resource.created_at
end
end

View File

@@ -48,6 +48,14 @@
}
window.errorLoggingConfig = '<%= ENV.fetch('SENTRY_DSN', '')%>'
</script>
<% if @global_config['ANALYTICS_TOKEN'].present? && @global_config['ANALYTICS_HOST'].present? %>
<script>
window.analyticsConfig = {
token: '<%= @global_config['ANALYTICS_TOKEN'] %>',
host: '<%= @global_config['ANALYTICS_HOST'] %>',
}
</script>
<% end %>
<%= javascript_pack_tag 'application' %>
<%= stylesheet_pack_tag 'application' %>
</head>
@@ -55,21 +63,14 @@
<div id="app"></div>
<noscript id="noscript">This app works best with JavaScript enabled.</noscript>
<%= yield %>
<% @global_config['CHATWOOT_INBOX_TOKEN'] %>
<% if @global_config['CHATWOOT_INBOX_TOKEN'] %>
<% if @global_config['CHATWOOT_INBOX_TOKEN'].present? %>
<script>
window.chatwootSettings = {
hideMessageBubble: true,
position: 'left',
};
window.chatwootSettings = { hideMessageBubble: true, position: 'left' };
(function(d,t) {
var BASE_URL="";
var BASE_URL="https://app.chatwoot.com";
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=BASE_URL+"/packs/js/sdk.js";
g.defer = true;
g.async = true;
g.src=BASE_URL+"/packs/js/sdk.js"; g.defer=true; g.async=true;
s.parentNode.insertBefore(g,s);
s.async=!0;
g.onload=function(){
window.chatwootSDK.run({
websiteToken: '<%= @global_config['CHATWOOT_INBOX_TOKEN'] %>',