-
-
Save peter-mach/d78e9b4001a06e04c2a2031c705d0b5b to your computer and use it in GitHub Desktop.
Find churn reasons by sucking out all Stripe subscriptions (includes all subscriptions)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const moment = require('moment'); | |
const stripe = require('../stripe'); | |
const hashCode = (str) => { | |
let hash = 0; | |
if (typeof str !== 'string' || str.length === 0) { | |
return String(hash); | |
} | |
for (let i = 0; i < str.length; i++) { | |
const char = str.charCodeAt(i); | |
hash = ((hash << 5) - hash) + char; | |
hash = hash & hash; | |
} | |
hash = hash >>> 0; | |
return Number(hash).toString(32).toLowerCase(); | |
}; | |
const VAT_RATE = 0; | |
const exportSubscriptionData = async () => { | |
let hasMore = false; | |
let lastId = ''; | |
let page = 1; | |
const subs = []; | |
const collection = []; | |
while (subs.length === 0 || hasMore) { | |
console.log(`getting page ${page} of subs...`) | |
const opt = { | |
limit: 100, | |
expand: ['data.customer'], | |
status: 'all', | |
}; | |
if (lastId) opt.starting_after = lastId; | |
const result = await stripe.subscriptions.list(opt); | |
hasMore = result.has_more; | |
if (result && result.data?.length > 0) { | |
result.data.forEach((item) => { | |
subs.push(item); | |
let amount = item.plan.amount; | |
if (item.discount && item.discount.coupon) { | |
amount = (amount * (1 + VAT_RATE)) * (1 - (item.discount.coupon.percent_off / 100)); | |
} | |
amount = amount / 100; | |
let interval = item.plan.interval; | |
if (item.plan.interval_count === 3) { | |
interval = 'quarter'; | |
} | |
let monthly = amount; | |
if (interval === 'quarter') { | |
monthly = amount / 3; | |
} else if (interval === 'year') { | |
monthly = amount / 12; | |
} | |
monthly = monthly; | |
const discount = item.discount && item.discount.coupon ? item.discount.coupon.id : ''; | |
collection.push({ | |
customer: hashCode(item.customer.email), | |
start: moment(item.start_date * 1000).format('YYYY-MM-DD'), | |
end: item.canceled_at ? moment(item.canceled_at * 1000).format('YYYY-MM-DD') : '', | |
status: item.status, | |
plan: item.plan.id, | |
amount, | |
interval, | |
monthly, | |
discount, | |
cancellation_reason: item.cancellation_details && item.cancellation_details.feedback ? item.cancellation_details.feedback : '', | |
cancellation_comment: item.cancellation_details && item.cancellation_details.comment ? item.cancellation_details.comment : '', | |
}); | |
}) | |
lastId = result.data[result.data.length - 1].id | |
} else { | |
break | |
} | |
page += 1 | |
console.log(`${collection.length} subs collected...`); | |
} | |
collection.sort((a, b) => new Date(b.start) - new Date(a.start)); | |
let csv = 'Customer,Start,End,Status,Plan,Amount,Interval,Monthly,Discount,Cancellation Reason,Cancellation Comment\n'; | |
csv += collection.map((item) => `${item.customer},${item.start},${item.end},${item.status},${item.plan},${item.amount.toFixed(2)},${item.interval},${item.monthly.toFixed(2)},${item.discount},${item.cancellation_reason},"${item.cancellation_comment}"`).join('\n'); | |
fs.writeFileSync('./subscription.csv', csv, { encoding: 'utf8' }); | |
}; | |
exportSubscriptionData().then(() => process.exit()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment