Public
Edited
Aug 12, 2024
Importers
Insert cell
Insert cell
Plot.line(data, { x: "Date", y: "Users", tip: true }).plot({
marginLeft: 50,
title: "BetterHelp's user growth has inverted",
caption:
"BetterHelp have seen monthly paying user decreases for four consecutive quarters from Q2 2023.",
y: {
grid: true,
ticks: 5,
tickFormat: "s",
label: "Monthly Paying Users"
}
})
Insert cell
Plot.line(data, { x: "Date", y: "Revenue", tip: true }).plot({
marginLeft: 50,
title: "BetterHelp's revenue growth has inverted",
caption:
"BetterHelp have seen revenue decreases for four consecutive quarters from Q2 2023.",
y: {
grid: true,
ticks: 5,
tickFormat: "$s"
}
})
Insert cell
Plot.rectY(data, {
x: "Date",
y: "EBITDA",
tip: true,
interval: d3.utcMonth.every(3)
}).plot({
marginLeft: 50,
title: "BetterHelp isn't getting more expensive to provide",
caption:
"BetterHelp's EBITDA exhibits a seasonal pattern, but is largely stable. EBITDA is Earnings Before Interest, Taxes, Appreciation, and Amortization, and is a rough measure of the profitability of the service. We would expect it to significantly decrease if the service was getting more expensive to provide.",
y: {
grid: true,
ticks: 5,
tickFormat: "$s"
},
marks: [Plot.ruleY([0])]
})
Insert cell
Plot.rectY(data, {
x: "Date",
y: "Margin",
tip: true,
interval: d3.utcMonth.every(3)
}).plot({
marginLeft: 50,
caption: "BetterHelp's margins, derived by dividing EBITDA by revenue.",
y: {
grid: true,
ticks: 5,
tickFormat: "%"
},
marks: [Plot.ruleY([0])]
})
Insert cell
Plot.lineY(data, {
x: "Date",
y: "Marketing Yield",
tip: true
}).plot({
marginLeft: 50,
title: "Teladoc's return on marketing is decreasing",
caption:
"BetterHelp's new users per million dollars spent on marketing has dramatically decreased, and inverted in Q3 2023.",
y: {
label: "New users per million dollars",
grid: true,
ticks: 5
},
marks: [Plot.ruleY([0])]
})
Insert cell
data = [
{
Date: "2021-12-31",
Users: 351_000,
Revenue: 214_000_000,
EBITDA: 43_000_000,
Marketing: 112_988_000
},
{
Date: "2022-03-31",
Users: 382_000,
Revenue: 230_000_000,
EBITDA: 30_000_000,
Marketing: 133_600_000
},
{
Date: "2022-06-30",
Users: 408_000,
Revenue: 247_000_000,
EBITDA: 20_000_000,
Marketing: 164_574_000
},
{
Date: "2022-09-30",
Users: 437_000,
Revenue: 265_000_000,
EBITDA: 11_000_000,
Marketing: 178_920_000
},
{
Date: "2022-12-31",
Users: 450_000,
Revenue: 277_000_000,
EBITDA: 53_000_000,
Marketing: 146_443_000
},
{
Date: "2023-03-31",
Users: 467_000,
Revenue: 279_000_000,
EBITDA: 18_000_000,
Marketing: 176_790_000
},
{
Date: "2023-06-30",
Users: 476_000,
Revenue: 292_000_000,
EBITDA: 34_000_000,
Marketing: 178_756_000
},
{
Date: "2023-09-30",
Users: 459_000,
Revenue: 285_000_000,
EBITDA: 26_000_000,
Marketing: 186_152_000
},
{
Date: "2023-12-31",
Users: 425_000,
Revenue: 276_000_000,
EBITDA: 58_000_000,
Marketing: 147_156_000
},
{
Date: "2024-03-31",
Users: 415_000,
Revenue: 269_000_000,
EBITDA: 15_000_000,
Marketing: 183_329_000
},
{
Date: "2024-06-30",
Users: 407_000,
Revenue: 265_000_000,
EBITDA: 25_000_000,
Marketing: 170_270_000
}
].map(({ Date: rawDate, Users, Revenue, EBITDA, Marketing }, i, array) => ({
Date: new Date(rawDate),
Users,
Revenue,
EBITDA,
Margin: EBITDA / Revenue,
Marketing,
"Marketing Yield":
i > 0 ? ((Users - array[i - 1].Users) / Marketing) * 1_000_000 : undefined
}))
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more