Skip to content

Instantly share code, notes, and snippets.

@nickfogle
Created July 21, 2021 17:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickfogle/4352b2102e4aee0885ca0a355b22bd68 to your computer and use it in GitHub Desktop.
Save nickfogle/4352b2102e4aee0885ca0a355b22bd68 to your computer and use it in GitHub Desktop.
Churnkey Sample Code for Vue.js Implementation
import moment from 'moment';
import { Notification } from 'element-ui';
import UserService from '@/api/user.service';
import { IS_PRODUCTION } from '@/config';
import store from '@/store';
export default async function launchChurnkey(user) {
const customerId = user.stripe.id;
try {
const { authHash } = await UserService.getChurnKeyHash(customerId);
// initialize Churnkey flow
window.churnkey.init('show', {
appId: 'ikmp8qyfz',
customerId,
authHash,
mode: IS_PRODUCTION ? 'live' : 'test',
// sample code for launching intercom support chat when embed button clicked.
handleSupportRequest: customer => {
window.Intercom('showNewMessage', 'Attention: Offboarding Customer Needs Help ASAP.');
window.churnkey.hide();
},
// sample pause handler (used if you want to handle cancelation instead of letting Churnkey do it
handlePause: (customer, options) => {
const duration = options.pauseDuration;
return new Promise(async (resolve, reject) => {
try {
await submitPause(user, duration);
resolve({ message: 'Account paused.' });
} catch (e) {
reject({ message: 'Pause failed. Please reach out to us for help.' });
}
});
},
// sample pause handler (used if you want to handle cancelation instead of letting Churnkey do it
// params `customer` and `surveyAnswer` are optional if you want to handle cancel and collect the data yourself.
handleCancel: (customer, surveyAnswer)
return new Promise(async (resolve, reject) => {
try {
await submitCancel(user, customer.plan);
resolve({ message: 'Your account has been canceled.' });
} catch (e) {
reject({ message: 'Failed to cancel account. Please reach out to us for help.' });
}
});
},
});
} catch (error) {
console.log('Error', error);
}
}
async function submitPause(user, duration) {
try {
// Make API request to custom endpoint for updating stripe as well as DB record.
await UserService.updateBilling(user.id, { duration, event: 'pause' });
// sync updated user subscription details to vuex
await store.dispatch('SYNC_USER_TO_DB');
Notification.success({ title: 'Success', message: 'Subscription Paused' });
} catch (err) {
throw new Error('Could not pause');
}
}
async function submitCancel(user, plan) {
try {
await UserService.updateBilling(user.id, { event: 'cancel', plan });
// sync updated user subscription details to vuex and refresh state
await store.dispatch('SYNC_USER_TO_DB');
// Notify user of successful cancellation
Notification.success({ title: 'Canceled', message: `Access will end on ${planChange.stopDate}.` });
} catch (err) {
throw new Error('Could not cancel');
}
}
export default function loadChurnKey() {
if (!window.churnkey || !window.churnkey.created) {
window.churnkey = { created: true };
const a = document.createElement('script');
a.src = 'https://assets.churnkey.co/js/app.js';
a.async = true;
const b = document.getElementsByTagName('script')[0];
b.parentNode.insertBefore(a, b);
}
}
<template>
<div>
<h1>Billing Summary</h1>
<!-- show button if user can cancel and loading finished -->
<div>
<button id="ck-cancel" @click="cancelFlow()" v-if="user.canCancel && !isLoading">Cancel</el-button>
</div>
</template>
<script>
import loadChurnKey from '@/helpers/loadChurnKey';
import launchChurnKey from '@/helpers/launchChurnKey';
export default {
name: 'SamplePage',
computed: {
user() {
return this.$store.state.user;
},
canCancel() {
// hide cancel button if user doesn't have an active subscription
return this.user.subscription;
},
},
data() {
return {
isLoading: false,
};
},
methods: {
// click handler for launching churnkey embed
cancelFlow() {
launchChurnKey(this.user);
},
},
mounted() {
const vm = this;
loadChurnKey();
},
};
</script>
<style>
.button {
color: #000;
}
</style>
@nickfogle
Copy link
Author

nickfogle commented Jul 21, 2021

You can load the Churnkey 3rd party Javascript on a single page or across your entire application. We find it's best to only load it on the page where you actually need it (example - billing page).

This example code shows you how to do that using vue.js. The loadChurnkey.js script allows you to import Churnkey to whatever page or component from which you plan to launch Churnkey. Then, the handleCustomFlow.js script shows off a few of the custom callback handlers (options described more fully here: https://docs.churnkey.co/installing-churnkey#efc85982b3364c28b1ebaa7c9d21d7c1).

Finally, you'll import both of these scripts into the vue template and then you'll create a click handler for triggering the embed loading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment