mirror of
https://github.com/BillyOutlast/posthog.com.git
synced 2026-02-04 03:11:21 +01:00
Merge branch 'master' into workflows-beta
This commit is contained in:
@@ -4,7 +4,7 @@ title: Workflows are now in Alpha and I already broke mine
|
||||
author:
|
||||
- sara-miteva
|
||||
featuredImage: >-
|
||||
https://res.cloudinary.com/dmukukwp6/image/upload/w_1600,c_limit,q_auto,f_auto/this_is_fine_6336efb0ae.jpg
|
||||
https://res.cloudinary.com/dmukukwp6/image/upload/this_is_fine_6336efb0ae.jpg
|
||||
rootPage: /blog
|
||||
sidebar: Blog
|
||||
showTitle: true
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
title: Managing cool tech jobs
|
||||
---
|
||||
|
||||
> **Applying to get your jobs listed?** The Cool Tech Jobs board exists to help people find jobs at companies with similar perks and culture to PostHog, and a strong engineer-led environment. Applications are approved only at our discretion and moderation can take up to 48 hours. If you have a question about an application, please [contact our support team](http://app.posthog.com/home#supportModal).
|
||||
|
||||
## Create a company/jobs:
|
||||
|
||||
### Non-moderator flow
|
||||
|
||||
@@ -43,3 +43,18 @@ Here are the common tools the Sales & CS teams use daily.
|
||||
- [YubiKey Manager](https://www.yubico.com/support/download/yubikey-manager/) (app) for configuring provided YubiKey
|
||||
- An IDE, like VS Code, Zed, or Cursor. It will come in handy for coding and development tasks.
|
||||
- Your next favorite tool!
|
||||
|
||||
### Useful Slack channels
|
||||
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C08M011SBCM'>#team-customer-success</PrivateLink> - the Customer Success team.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C09677WV1GW'>#team-new-business-sales</PrivateLink> - the New Business sales team.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C093XHYMGBE'>#team-product-led-sales</PrivateLink> - the Product-led sales team.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C090RCG671C'>#cs-sales-support</PrivateLink> - cross-team discussion for everyone who owns customers.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C01MGUHFH6G'>#sales</PrivateLink> - for general sales topics.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C03V7SP3Z3K'>#incidents</PrivateLink> - for notifications of incidents which may impact customers. Make sure you set this to alert you for every message so that you know when something is up.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C071PGWKBQS'>#sales-alerts</PrivateLink> - automated notifications from Vitally.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C054BJSHG82'>#sales-leads</PrivateLink> - automated notifications for new sales leads.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C08MYQX74KH'>#legal</PrivateLink> - for requests from our legal folks.
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C08UNFX75ST'>#closed-won</PrivateLink> - yay!
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C096DC85NH5'>#closed-lost</PrivateLink> - boo!
|
||||
- <PrivateLink url='https://posthog.slack.com/archives/C09HKF565MZ'>#customer-churn-retros</PrivateLink> - retros from big churns.
|
||||
|
||||
@@ -3,6 +3,7 @@ export const sfBenchmark: Record<string, number> = {
|
||||
'Account Executive (OTE)': 300000,
|
||||
'Backend Engineer': 243000,
|
||||
'Billing Support Specialist': 154619,
|
||||
'Business Development Representative (OTE)': 182000,
|
||||
'Content Marketer': 190910,
|
||||
'Community Manager': 185000,
|
||||
'Customer Success Manager (OTE)': 211000,
|
||||
|
||||
@@ -362,71 +362,77 @@ const OSSelect = ({
|
||||
{isOpen && (
|
||||
<div
|
||||
ref={selectRef}
|
||||
className={`absolute z-50 w-full mt-1 bg-primary border border-primary rounded shadow-lg ${maxHeight} overflow-hidden`}
|
||||
className={`absolute z-50 w-full mt-1 bg-primary border border-primary rounded shadow-lg min-h-0`}
|
||||
role="listbox"
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<ScrollArea className={`min-h-0 ${height} ${maxHeight}`}>
|
||||
{searchable && (
|
||||
<div className="p-2 border-b border-primary">
|
||||
<div className="relative">
|
||||
<IconSearch className="absolute left-2 top-1/2 transform -translate-y-1/2 size-4 text-muted" />
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
type="text"
|
||||
placeholder={searchPlaceholder}
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
className="w-full pl-8 pr-3 py-1.5 text-sm bg-primary border border-primary rounded text-primary placeholder-muted focus:outline-none focus:ring-1 focus:ring-blue"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) =>
|
||||
option.isHeader ? (
|
||||
<div
|
||||
data-scheme="secondary"
|
||||
key={`header-${option.label}-${index}`}
|
||||
className="px-3 py-1 text-sm text-muted bg-primary border-y border-primary"
|
||||
>
|
||||
{option.label}
|
||||
<ScrollArea>
|
||||
<div className={maxHeight}>
|
||||
{searchable && (
|
||||
<div className="p-2 border-b border-primary">
|
||||
<div className="relative">
|
||||
<IconSearch className="absolute left-2 top-1/2 transform -translate-y-1/2 size-4 text-muted" />
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
type="text"
|
||||
placeholder={searchPlaceholder}
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
className="w-full pl-8 pr-3 py-1.5 text-sm bg-primary border border-primary rounded text-primary placeholder-muted focus:outline-none focus:ring-1 focus:ring-blue"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
key={`${option.value}-${index}`}
|
||||
ref={(el) => (optionRefs.current[index] = el)}
|
||||
type="button"
|
||||
onClick={() => handleOptionSelect(option)}
|
||||
disabled={option.disabled}
|
||||
className={`w-full px-3 py-2 text-left text-sm hover:bg-accent focus:bg-accent focus:outline-none flex items-center justify-between ${
|
||||
option.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
|
||||
} ${option.value === value ? 'font-bold' : ''} ${
|
||||
index === highlightedIndex ? 'bg-accent' : ''
|
||||
}`}
|
||||
role="option"
|
||||
aria-selected={option.value === value}
|
||||
onMouseEnter={() => setHighlightedIndex(index)}
|
||||
>
|
||||
<span className="flex items-center space-x-2">
|
||||
{renderIcon(option.icon, option.color)}
|
||||
<div>
|
||||
<div className="text-primary">{option.label}</div>
|
||||
{option.description && (
|
||||
<div className="text-xs text-muted">{option.description}</div>
|
||||
)}
|
||||
</div>
|
||||
</span>
|
||||
{option.value === value && <IconCheck className="size-4 text-primary" />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) =>
|
||||
option.isHeader ? (
|
||||
<div
|
||||
data-scheme="secondary"
|
||||
key={`header-${option.label}-${index}`}
|
||||
className="px-3 py-1 text-sm text-muted bg-primary border-y border-primary"
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
key={`${option.value}-${index}`}
|
||||
ref={(el) => (optionRefs.current[index] = el)}
|
||||
type="button"
|
||||
onClick={() => handleOptionSelect(option)}
|
||||
disabled={option.disabled}
|
||||
className={`w-full px-3 py-2 text-left text-sm hover:bg-accent focus:bg-accent focus:outline-none flex items-center justify-between ${
|
||||
option.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
|
||||
} ${option.value === value ? 'font-bold' : ''} ${
|
||||
index === highlightedIndex ? 'bg-accent' : ''
|
||||
}`}
|
||||
role="option"
|
||||
aria-selected={option.value === value}
|
||||
onMouseEnter={() => setHighlightedIndex(index)}
|
||||
>
|
||||
<span className="flex items-center space-x-2">
|
||||
{renderIcon(option.icon, option.color)}
|
||||
<div>
|
||||
<div className="text-primary">{option.label}</div>
|
||||
{option.description && (
|
||||
<div className="text-xs text-muted">
|
||||
{option.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</span>
|
||||
{option.value === value && (
|
||||
<IconCheck className="size-4 text-primary" />
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<div className="px-3 py-2 text-sm text-muted">
|
||||
{searchTerm ? `No options found for "${searchTerm}"` : 'No options available'}
|
||||
</div>
|
||||
)}
|
||||
) : (
|
||||
<div className="px-3 py-2 text-sm text-muted">
|
||||
{searchTerm ? `No options found for "${searchTerm}"` : 'No options available'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -104,7 +104,6 @@ export const Select = ({
|
||||
placeholder={label}
|
||||
searchable={true}
|
||||
searchPlaceholder="Search topics..."
|
||||
height="!h-96"
|
||||
maxHeight="max-h-[300px]"
|
||||
showLabel={false}
|
||||
className=""
|
||||
|
||||
213
src/components/Team/SpiritAnimal.tsx
Normal file
213
src/components/Team/SpiritAnimal.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
import { Fieldset } from 'components/OSFieldset'
|
||||
import { OSSelect, OSTextarea } from 'components/OSForm'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import qs from 'qs'
|
||||
|
||||
const spiritAnimals = [
|
||||
{ emoji: '🐜', name: 'Ant' },
|
||||
{ emoji: '🦡', name: 'Badger' },
|
||||
{ emoji: '🦇', name: 'Bat' },
|
||||
{ emoji: '🐻', name: 'Bear' },
|
||||
{ emoji: '🦫', name: 'Beaver' },
|
||||
{ emoji: '🐝', name: 'Bee' },
|
||||
{ emoji: '🦬', name: 'Bison' },
|
||||
{ emoji: '🐦', name: 'Bird' },
|
||||
{ emoji: '🐈⬛', name: 'Black cat' },
|
||||
{ emoji: '🐡', name: 'Blowfish' },
|
||||
{ emoji: '🐗', name: 'Boar' },
|
||||
{ emoji: '🦋', name: 'Butterfly' },
|
||||
{ emoji: '🐫', name: 'Camel' },
|
||||
{ emoji: '🐈', name: 'Cat' },
|
||||
{ emoji: '🐔', name: 'Chicken' },
|
||||
{ emoji: '🐿', name: 'Chipmunk' },
|
||||
{ emoji: '🦀', name: 'Crab' },
|
||||
{ emoji: '🐊', name: 'Crocodile' },
|
||||
{ emoji: '🦌', name: 'Deer' },
|
||||
{ emoji: '🐕', name: 'Shiba Inu' },
|
||||
{ emoji: '🐬', name: 'Dolphin' },
|
||||
{ emoji: '🫏', name: 'Donkey' },
|
||||
{ emoji: '🕊️', name: 'Dove' },
|
||||
{ emoji: '🐉', name: 'Dragon' },
|
||||
{ emoji: '🦆', name: 'Duck' },
|
||||
{ emoji: '🦅', name: 'Eagle' },
|
||||
{ emoji: '🐘', name: 'Elephant' },
|
||||
{ emoji: '🐀', name: 'Rat' },
|
||||
{ emoji: '🐟', name: 'Fish' },
|
||||
{ emoji: '🦩', name: 'Flamingo' },
|
||||
{ emoji: '🪰', name: 'Fly' },
|
||||
{ emoji: '🦊', name: 'Fox' },
|
||||
{ emoji: '🐸', name: 'Frog' },
|
||||
{ emoji: '🦒', name: 'Giraffe' },
|
||||
{ emoji: '🐐', name: 'Goat' },
|
||||
{ emoji: '🪿', name: 'Goose' },
|
||||
{ emoji: '🦍', name: 'Gorilla' },
|
||||
{ emoji: '🦮', name: 'Labrador' },
|
||||
{ emoji: '🦔', name: 'Hedgehog' },
|
||||
{ emoji: '🦛', name: 'Hippopotamus' },
|
||||
{ emoji: '🐎', name: 'Horse' },
|
||||
{ emoji: '🪼', name: 'Jellyfish' },
|
||||
{ emoji: '🦘', name: 'Kangaroo' },
|
||||
{ emoji: '🐨', name: 'Koala' },
|
||||
{ emoji: '🐞', name: 'Ladybug' },
|
||||
{ emoji: '🐆', name: 'Leopard' },
|
||||
{ emoji: '🦁', name: 'Lion' },
|
||||
{ emoji: '🦎', name: 'Lizard' },
|
||||
{ emoji: '🦙', name: 'Llama' },
|
||||
{ emoji: '🦣', name: 'Mammoth' },
|
||||
{ emoji: '🐒', name: 'Monkey' },
|
||||
{ emoji: '🫎', name: 'Moose' },
|
||||
{ emoji: '🐁', name: 'Mouse' },
|
||||
{ emoji: '🐙', name: 'Octopus' },
|
||||
{ emoji: '🦧', name: 'Orangutan' },
|
||||
{ emoji: '🦦', name: 'Otter' },
|
||||
{ emoji: '🦉', name: 'Owl' },
|
||||
{ emoji: '🐂', name: 'Ox' },
|
||||
{ emoji: '🐼', name: 'Panda' },
|
||||
{ emoji: '🦜', name: 'Parrot' },
|
||||
{ emoji: '🦚', name: 'Peacock' },
|
||||
{ emoji: '🐧', name: 'Penguin' },
|
||||
{ emoji: '🐖', name: 'Pig' },
|
||||
{ emoji: '🐻❄️', name: 'Polar bear' },
|
||||
{ emoji: '🐩', name: 'Poodle' },
|
||||
{ emoji: '🐇', name: 'Rabbit' },
|
||||
{ emoji: '🦝', name: 'Raccoon' },
|
||||
{ emoji: '🐏', name: 'Ram' },
|
||||
{ emoji: '🦏', name: 'Rhinoceros' },
|
||||
{ emoji: '🐓', name: 'Rooster' },
|
||||
{ emoji: '🦕', name: 'Sauropod' },
|
||||
{ emoji: '🦂', name: 'Scorpion' },
|
||||
{ emoji: '🦭', name: 'Seal' },
|
||||
{ emoji: '🦈', name: 'Shark' },
|
||||
{ emoji: '🐑', name: 'Sheep' },
|
||||
{ emoji: '🦐', name: 'Shrimp' },
|
||||
{ emoji: '🦨', name: 'Skunk' },
|
||||
{ emoji: '🦥', name: 'Sloth' },
|
||||
{ emoji: '🐌', name: 'Snail' },
|
||||
{ emoji: '🐍', name: 'Snake' },
|
||||
{ emoji: '🕷️', name: 'Spider' },
|
||||
{ emoji: '🐳', name: 'Spouting whale' },
|
||||
{ emoji: '🦑', name: 'Squid' },
|
||||
{ emoji: '🦢', name: 'Swan' },
|
||||
{ emoji: '🦖', name: 'T-Rex' },
|
||||
{ emoji: '🐅', name: 'Tiger' },
|
||||
{ emoji: '🐠', name: 'Tropical fish' },
|
||||
{ emoji: '🦃', name: 'Turkey' },
|
||||
{ emoji: '🐢', name: 'Turtle' },
|
||||
{ emoji: '🦄', name: 'Unicorn' },
|
||||
{ emoji: '🐃', name: 'Water buffalo' },
|
||||
{ emoji: '🐋', name: 'Whale' },
|
||||
{ emoji: '🐺', name: 'Wolf' },
|
||||
{ emoji: '🦓', name: 'Zebra' },
|
||||
{ emoji: '🦤', name: 'Dodo' },
|
||||
]
|
||||
|
||||
const SpiritAnimalForm = ({
|
||||
spiritAnimal,
|
||||
setFieldValue,
|
||||
}: {
|
||||
spiritAnimal: { animal: string; description: string } | null
|
||||
setFieldValue: (field: string, value: any) => void
|
||||
}) => {
|
||||
const [takenAnimals, setTakenAnimals] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTakenAnimals = async () => {
|
||||
try {
|
||||
const query = qs.stringify({
|
||||
filter: {
|
||||
profiles: {
|
||||
id: {
|
||||
$ne: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
populate: 'spiritAnimal',
|
||||
pagination: {
|
||||
limit: 100,
|
||||
},
|
||||
})
|
||||
await fetch(`${process.env.GATSBY_SQUEAK_API_HOST}/api/teams?${query}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const takenAnimals = data.data
|
||||
.map((team: any) => team.attributes.spiritAnimal?.animal)
|
||||
.filter(Boolean)
|
||||
setTakenAnimals(takenAnimals)
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
fetchTakenAnimals()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<OSSelect
|
||||
size="sm"
|
||||
label="Spirit animal"
|
||||
direction="column"
|
||||
options={spiritAnimals
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((animal) => {
|
||||
const name = `${animal.emoji} ${animal.name}`
|
||||
return {
|
||||
label: name,
|
||||
value: name,
|
||||
disabled: takenAnimals.includes(`${animal.emoji} ${animal.name}`),
|
||||
}
|
||||
})}
|
||||
onChange={(value) => {
|
||||
setFieldValue('spiritAnimal.animal', value)
|
||||
}}
|
||||
value={spiritAnimal?.animal}
|
||||
/>
|
||||
<div className="[&_label]:font-normal">
|
||||
<OSTextarea
|
||||
placeholder="Why is this your spirit animal?"
|
||||
rows={3}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setFieldValue('spiritAnimal.description', e.target.value)
|
||||
}}
|
||||
value={spiritAnimal?.description || ''}
|
||||
label="Description"
|
||||
direction="column"
|
||||
/>
|
||||
</div>
|
||||
{spiritAnimal && (
|
||||
<div className="flex justify-end mt-1.5">
|
||||
<button
|
||||
onClick={() => {
|
||||
setFieldValue('spiritAnimal', null)
|
||||
}}
|
||||
className="text-sm text-red font-bold"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function SpiritAnimal({
|
||||
spiritAnimal,
|
||||
editing,
|
||||
setFieldValue,
|
||||
}: {
|
||||
spiritAnimal: { animal: string; description: string } | null
|
||||
editing: boolean
|
||||
setFieldValue: (field: string, value: any) => void
|
||||
}): JSX.Element | null {
|
||||
return editing ? (
|
||||
<SpiritAnimalForm spiritAnimal={spiritAnimal} setFieldValue={setFieldValue} />
|
||||
) : (
|
||||
spiritAnimal && (
|
||||
<Fieldset legend="Spirit animal">
|
||||
<h4 className="!m-0">{spiritAnimal.animal}</h4>
|
||||
<p className="m-0 text-sm">{spiritAnimal.description}</p>
|
||||
</Fieldset>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -48,6 +48,12 @@ export const errorTracking = {
|
||||
// imgClasses: 'rounded-tl-md shadow-2xl',
|
||||
},
|
||||
},
|
||||
videos: {
|
||||
overview: {
|
||||
youtube: '',
|
||||
wistia: 'scuzsr1rcz',
|
||||
},
|
||||
},
|
||||
hog: {
|
||||
src: 'https://res.cloudinary.com/dmukukwp6/image/upload/error_hog_c2eff84e29.png',
|
||||
alt: 'Just another hedgehog',
|
||||
@@ -258,6 +264,31 @@ export const errorTracking = {
|
||||
rows: ['error_tracking'],
|
||||
excluded_sections: ['platform.libraries'],
|
||||
},
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses Error Tracking',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Track errors',
|
||||
description: 'and identify spikes in exception events',
|
||||
},
|
||||
{
|
||||
title: 'Investigate root causes',
|
||||
description: 'using stack traces and session replays',
|
||||
},
|
||||
{
|
||||
title: 'Triage issues',
|
||||
description: 'by filtering based on severity and impact',
|
||||
},
|
||||
{
|
||||
title: 'Find out when things go wrong',
|
||||
description: 'by setting up alerts for critical errors',
|
||||
},
|
||||
{
|
||||
title: 'Dodge blame',
|
||||
description: 'by assigning errors to someone else',
|
||||
},
|
||||
],
|
||||
},
|
||||
integrations: ['ab_experiments', 'product_analytics', 'session_replays'],
|
||||
pairsWith: [
|
||||
{
|
||||
|
||||
@@ -263,7 +263,7 @@ export const experiments = {
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses experiments',
|
||||
title: 'How PostHog uses Experiments',
|
||||
benefits: [
|
||||
{
|
||||
title: 'A/B tests',
|
||||
|
||||
@@ -346,7 +346,7 @@ export const featureFlags = {
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses feature flags',
|
||||
title: 'How PostHog uses Feature Flags',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Test new ideas',
|
||||
|
||||
@@ -61,6 +61,11 @@ export const llmAnalytics = {
|
||||
textColor: 'text-white',
|
||||
layout: 'overlay',
|
||||
},
|
||||
videos: {
|
||||
overview: {
|
||||
wistia: 'bl174kpxu8',
|
||||
},
|
||||
},
|
||||
screenshots: {
|
||||
overview: {
|
||||
src: 'https://res.cloudinary.com/dmukukwp6/image/upload/llm_overview_desktop_2399cc57d6.png',
|
||||
@@ -332,6 +337,35 @@ export const llmAnalytics = {
|
||||
],
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses LLM Analytics',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Analyze costs',
|
||||
description: 'by comparing models and analyzing usage',
|
||||
},
|
||||
{
|
||||
title: 'Spot emergencies',
|
||||
description: 'with latency and error rate alerting',
|
||||
},
|
||||
{
|
||||
title: 'Monitor performance',
|
||||
description: 'by comparing speed and reliability across models',
|
||||
},
|
||||
{
|
||||
title: 'Muck about',
|
||||
description: 'in the prompt playground (meaningfully)',
|
||||
},
|
||||
{
|
||||
title: 'Integrate with other tools',
|
||||
description: 'like Langfuse, Helicone, and more',
|
||||
},
|
||||
{
|
||||
title: 'Build AI features',
|
||||
description: 'like PostHog AI, obviously',
|
||||
},
|
||||
],
|
||||
},
|
||||
questions: [
|
||||
{
|
||||
question: 'What are my LLM costs by customer?',
|
||||
|
||||
@@ -525,6 +525,11 @@ export const posthog_ai = {
|
||||
],
|
||||
},
|
||||
],
|
||||
videos: {
|
||||
overview: {
|
||||
wistia: 'tgws1dixc0',
|
||||
},
|
||||
},
|
||||
answers: [
|
||||
{
|
||||
q: "What's my churn rate?",
|
||||
@@ -557,6 +562,31 @@ export const posthog_ai = {
|
||||
q: 'Show me a signup funnel',
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses PostHog AI',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Build insights and dashboards',
|
||||
description: 'using natural language',
|
||||
},
|
||||
{
|
||||
title: 'Create SQL queries',
|
||||
description: 'to use for detailed analysis',
|
||||
},
|
||||
{
|
||||
title: 'Summarize session replays',
|
||||
description: "so we don't have to watch them all",
|
||||
},
|
||||
{
|
||||
title: 'Get product advice',
|
||||
description: 'because we trained the AI on our blog too',
|
||||
},
|
||||
{
|
||||
title: 'Fix bugs in our implementation',
|
||||
description: 'way faster than reading all the docs',
|
||||
},
|
||||
],
|
||||
},
|
||||
comparison: {
|
||||
comparison_companies: {
|
||||
Segment: true,
|
||||
|
||||
@@ -52,6 +52,12 @@ export const productAnalytics = {
|
||||
alt: 'Product analytics funnel',
|
||||
},
|
||||
},
|
||||
videos: {
|
||||
overview: {
|
||||
youtube: '',
|
||||
wistia: '0be67lqiau',
|
||||
},
|
||||
},
|
||||
hog: {
|
||||
src: 'https://res.cloudinary.com/dmukukwp6/image/upload/v1/posthog.com/src/components/Product/hogs/product-analytics-hog.png',
|
||||
alt: 'A hedgehog presenting some shocking findings',
|
||||
@@ -517,6 +523,31 @@ export const productAnalytics = {
|
||||
excluded_sections: ['platform.integrations'],
|
||||
require_complete_data: true,
|
||||
},
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses Product Analytics',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Track metrics',
|
||||
description: 'and monitor feature usage trends',
|
||||
},
|
||||
{
|
||||
title: 'Understand user behavior',
|
||||
description: 'by analyzing funnels and retention',
|
||||
},
|
||||
{
|
||||
title: 'Identify opportunities',
|
||||
description: 'by filtering based on drop-offs and conversion rates',
|
||||
},
|
||||
{
|
||||
title: 'Find out when things change',
|
||||
description: 'by setting up dashboards and alerts',
|
||||
},
|
||||
{
|
||||
title: 'Make data-driven decisions',
|
||||
description: 'by linking insights to session replays',
|
||||
},
|
||||
],
|
||||
},
|
||||
pairsWith: [
|
||||
{
|
||||
slug: 'session-replay',
|
||||
|
||||
@@ -30,6 +30,11 @@ export const sessionReplay = {
|
||||
'Play back sessions to diagnose UI issues, improve support, and get context on nuanced user behavior in your product, website, or mobile app.',
|
||||
textColor: 'text-black', // tw
|
||||
},
|
||||
videos: {
|
||||
overview: {
|
||||
wistia: 'a1480fky0u',
|
||||
},
|
||||
},
|
||||
screenshots: {
|
||||
overview: {
|
||||
src: 'https://res.cloudinary.com/dmukukwp6/image/upload/replay_screenshot_de8cb3a4ed.jpg',
|
||||
@@ -399,6 +404,35 @@ window.posthog.onFeatureFlags(function () {
|
||||
],
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses Session Replay',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Gather context',
|
||||
description: 'by seeing what led to each rageclick',
|
||||
},
|
||||
{
|
||||
title: 'Debug issues',
|
||||
description: 'by watching the prelude to each bug',
|
||||
},
|
||||
{
|
||||
title: 'Assess performance',
|
||||
description: 'by measuring first contentful paint and load time',
|
||||
},
|
||||
{
|
||||
title: 'Resolve experiments',
|
||||
description: 'by seeing how users interact with new features',
|
||||
},
|
||||
{
|
||||
title: 'Build user empathy',
|
||||
description: 'by watching their entire product journey',
|
||||
},
|
||||
{
|
||||
title: 'Improve conversion',
|
||||
description: 'by using context to solve stubborn problems',
|
||||
},
|
||||
],
|
||||
},
|
||||
questions: [
|
||||
{
|
||||
question: 'Why are users dropping off in my funnel?',
|
||||
|
||||
@@ -31,7 +31,7 @@ export const surveys = {
|
||||
},
|
||||
},
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses surveys',
|
||||
title: 'How PostHog uses Surveys',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Track NPS scores',
|
||||
|
||||
@@ -23,6 +23,11 @@ export const webAnalytics = {
|
||||
'Track visitors, pageviews, and conversions with a pre-built dashboard. No cookies required, no complex setup, real-time data, and privacy-focused. Built for people who really liked GA3...',
|
||||
textColor: 'text-[#063619]', // tw
|
||||
},
|
||||
videos: {
|
||||
overview: {
|
||||
wistia: 'x05zb7x023',
|
||||
},
|
||||
},
|
||||
screenshots: {
|
||||
overview: {
|
||||
src: 'https://res.cloudinary.com/dmukukwp6/image/upload/screenshot_web_analytics_2a101a8558.png',
|
||||
@@ -277,6 +282,31 @@ export const webAnalytics = {
|
||||
],
|
||||
},
|
||||
],
|
||||
postHogOnPostHog: {
|
||||
title: 'How PostHog uses Web Analytics',
|
||||
benefits: [
|
||||
{
|
||||
title: 'Track pageviews, visitors,',
|
||||
description: 'and other essential web metrics',
|
||||
},
|
||||
{
|
||||
title: 'Gauge site performance',
|
||||
description: 'using bounce rates and Core Web Vitals',
|
||||
},
|
||||
{
|
||||
title: 'Protect user privacy',
|
||||
description: 'with cookieless tracking and anonymous mode',
|
||||
},
|
||||
{
|
||||
title: 'Monitor ad performance',
|
||||
description: 'by focusing on landing page conversions',
|
||||
},
|
||||
{
|
||||
title: 'Understand users',
|
||||
description: 'by looking at device types and demographics',
|
||||
},
|
||||
],
|
||||
},
|
||||
questions: [
|
||||
{
|
||||
question: 'Find broken links (404s)',
|
||||
|
||||
@@ -38,6 +38,7 @@ const teamQuery = (slug: string) =>
|
||||
},
|
||||
miniCrest: true,
|
||||
tagline: true,
|
||||
spiritAnimal: true,
|
||||
},
|
||||
},
|
||||
{ encodeValuesOnly: true }
|
||||
|
||||
@@ -324,7 +324,6 @@ export default function PostHogAI(): JSX.Element {
|
||||
'feature-comparison',
|
||||
'docs',
|
||||
'pairs-with',
|
||||
'posthog-on-posthog',
|
||||
'answers',
|
||||
],
|
||||
custom: [
|
||||
@@ -344,7 +343,7 @@ export default function PostHogAI(): JSX.Element {
|
||||
// component: CustomManifestoSlide,
|
||||
// },
|
||||
],
|
||||
order: ['overview', 'features', 'demo', 'roadmap', 'pricing', 'getting-started'],
|
||||
order: ['overview', 'features', 'demo', `posthog-on-posthog`, 'roadmap', 'pricing', 'getting-started'],
|
||||
templates: {
|
||||
overview: 'max',
|
||||
features: 'ai',
|
||||
|
||||
@@ -1458,6 +1458,17 @@ const CompanyForm = ({ onSuccess, companyId }: { onSuccess?: () => void; company
|
||||
)}
|
||||
</OSButton>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm opacity-70 m-0">
|
||||
Approvals are at our discretion and can take up to 48 hours to process.{' '}
|
||||
<Link
|
||||
to="http://app.posthog.com/home#supportModal"
|
||||
className="text-red dark:text-yellow font-semibold"
|
||||
>
|
||||
Got a question?
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -143,7 +143,6 @@ export default function ErrorTracking(): JSX.Element {
|
||||
|
||||
// Configure slides with custom ProductOS Benefits slide
|
||||
const slides = createSlideConfig({
|
||||
exclude: ['posthog-on-posthog'],
|
||||
custom: [
|
||||
{
|
||||
slug: 'product-os-benefits',
|
||||
@@ -156,6 +155,7 @@ export default function ErrorTracking(): JSX.Element {
|
||||
'customers',
|
||||
'product-os-benefits',
|
||||
'features',
|
||||
'posthog-on-posthog',
|
||||
'pricing',
|
||||
'answers',
|
||||
'comparison-summary',
|
||||
|
||||
@@ -81,7 +81,7 @@ export default function LLMAnalytics(): JSX.Element {
|
||||
templates: {
|
||||
overview: 'stacked',
|
||||
},
|
||||
exclude: ['answers', 'posthog-on-posthog'],
|
||||
exclude: ['answers'],
|
||||
content: {
|
||||
answersDescription: 'Track costs, performance, and usage of your AI features with detailed analytics',
|
||||
answersHeadline: 'What can LLM Analytics help me discover?',
|
||||
|
||||
@@ -61,7 +61,6 @@ export default function ProductAnalytics(): JSX.Element {
|
||||
// Optional: Customize slides
|
||||
// See /components/Products/Slides/README.md for more details
|
||||
const slides = createSlideConfig({
|
||||
exclude: ['posthog-on-posthog'],
|
||||
// order: ['overview', 'pricing', 'features'],
|
||||
templates: {
|
||||
overview: 'stacked', // Use the horizontal split layout
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function RevenueAnalytics(): JSX.Element {
|
||||
`)
|
||||
|
||||
const slides = createSlideConfig({
|
||||
exclude: ['customers', 'pricing', 'posthog-on-posthog'],
|
||||
exclude: ['customers', 'pricing'],
|
||||
templates: {
|
||||
overview: 'stacked',
|
||||
},
|
||||
|
||||
@@ -62,7 +62,6 @@ export default function SessionReplay(): JSX.Element {
|
||||
// Optional: Customize slides
|
||||
// See /components/Products/Slides/README.md for more details
|
||||
const slides = createSlideConfig({
|
||||
exclude: ['posthog-on-posthog'],
|
||||
// order: ['overview', 'pricing', 'features'],
|
||||
templates: {
|
||||
overview: 'columns', // Use the horizontal split layout
|
||||
|
||||
@@ -28,7 +28,6 @@ import Tooltip from 'components/RadixUI/Tooltip'
|
||||
import { Fieldset } from 'components/OSFieldset'
|
||||
import ZoomHover from 'components/ZoomHover'
|
||||
import Link from 'components/Link'
|
||||
import TeamPatch from 'components/TeamPatch'
|
||||
import Header from 'components/Team/Header'
|
||||
import Profile, { ProfileData } from 'components/Team/Profile'
|
||||
import Roadmap from 'components/Team/Roadmap'
|
||||
@@ -39,8 +38,8 @@ import {
|
||||
StickerPineappleUnknown,
|
||||
StickerPineapple,
|
||||
} from 'components/Stickers/Index'
|
||||
import { DebugContainerQuery } from 'components/DebugContainerQuery'
|
||||
import TeamFeatures from 'components/TeamFeatures'
|
||||
import SpiritAnimal from 'components/Team/SpiritAnimal'
|
||||
|
||||
const hedgehogImageWidth = 30
|
||||
const hedgehogLengthInches = 7
|
||||
@@ -294,6 +293,7 @@ export default function TeamPage(props: TeamPageProps) {
|
||||
teamMembers: team?.attributes?.profiles?.data || [],
|
||||
teamLeads: team?.attributes?.leadProfiles?.data || [],
|
||||
miniCrest: miniCrest?.data ? { file: null, objectURL: miniCrest?.data?.attributes?.url } : undefined,
|
||||
spiritAnimal: team?.attributes?.spiritAnimal,
|
||||
},
|
||||
onSubmit: async ({
|
||||
name,
|
||||
@@ -305,6 +305,7 @@ export default function TeamPage(props: TeamPageProps) {
|
||||
teamMembers,
|
||||
teamLeads,
|
||||
miniCrest,
|
||||
spiritAnimal,
|
||||
...other
|
||||
}) => {
|
||||
const jwt = await getJwt()
|
||||
@@ -336,6 +337,7 @@ export default function TeamPage(props: TeamPageProps) {
|
||||
name,
|
||||
description,
|
||||
tagline,
|
||||
spiritAnimal,
|
||||
teamImage: {
|
||||
image: uploadedTeamImage
|
||||
? uploadedTeamImage.id
|
||||
@@ -638,6 +640,12 @@ export default function TeamPage(props: TeamPageProps) {
|
||||
|
||||
<TeamFeatures teamSlug={slug} />
|
||||
|
||||
<SpiritAnimal
|
||||
spiritAnimal={values.spiritAnimal}
|
||||
editing={editing}
|
||||
setFieldValue={setFieldValue}
|
||||
/>
|
||||
|
||||
<div>
|
||||
{teamEmojis?.length > 0 && (
|
||||
<Fieldset legend="Custom emojis">
|
||||
|
||||
@@ -132,12 +132,12 @@ export default function WebAnalytics(): JSX.Element {
|
||||
`)
|
||||
|
||||
const slides = createSlideConfig({
|
||||
exclude: ['posthog-on-posthog'],
|
||||
order: [
|
||||
'overview',
|
||||
'customers',
|
||||
'features',
|
||||
'comparison-summary',
|
||||
'posthog-on-posthog',
|
||||
'feature-comparison',
|
||||
'answers',
|
||||
'pricing',
|
||||
|
||||
Reference in New Issue
Block a user