Repository: PostHog/posthog
Pull request #30247: feat: hide upgrade CTAs from and show owner to managed accounts
Author: login: pawel-cebula
Created: 2025-03-20T18:36:20Z | Merged: 2025-03-21T18:02:21Z

## Problem

We've been showing upgrade related CTAs to managed accounts, which has been confusing to them and was often at odds with the sales team efforts

## Changes

Following on from `billing` changes (https://github.com/PostHog/billing/pull/1155), which now sync Vitally account owner information and return it via billing API
- Hides upgrade related CTAs on the billing page from managed accounts
- Shows account owner information in the menu, at the bottom of the `CURRENT ORGANIZATION` section, since the account owner is on a billing organization level, allowing click-to-copy

Alternative options considered
- Link to [community profile page](https://posthog.com/community/profiles/28895) - no private contact option there, just a public AMA. We could add contact details there too, maybe by adding some custom query param, but doesn't feel like adding more steps is helpful and my assumption is that accounts know their AEs/CSMs already.
- Surveys - briefly looked into using surveys here as a contact form - definitely a bit of a stretch but doable. I'm not convinced about the ROI on this though.

For more context see
- [Slack thread](https://posthog.slack.com/archives/C08ERRQT41E/p1742298597016129)
- https://github.com/PostHog/billing/issues/1147

## Does this work well for both Cloud and self-hosted?

Cloud only

## How did you test this code?

Manually (see below and Loom: https://www.loom.com/share/80f127f1d6644b8da4f07e7cf031b11d)

![SCR-20250320-qutd](https://github.com/user-attachments/assets/337e0946-83d7-4cb2-b54b-7798aa3e11af)



Diff:
diff --git a/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--dark.png b/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--dark.png
index 57ba9291bd87..d34a83616386 100644
Binary files a/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--dark.png and b/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--dark.png differ
diff --git a/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--light.png b/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--light.png
index 4bb27b2fd210..a290805518be 100644
Binary files a/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--light.png and b/frontend/__snapshots__/posthog-3000-navigation--navigation-3000--light.png differ
diff --git a/frontend/src/layout/navigation-3000/Navigation.stories.tsx b/frontend/src/layout/navigation-3000/Navigation.stories.tsx
index a5cbadec01f7..ba5e430bb105 100644
--- a/frontend/src/layout/navigation-3000/Navigation.stories.tsx
+++ b/frontend/src/layout/navigation-3000/Navigation.stories.tsx
@@ -1,4 +1,5 @@
 import { Meta } from '@storybook/react'
+import { useActions } from 'kea'
 import { router } from 'kea-router'
 import { FEATURE_FLAGS } from 'lib/constants'
 import { useEffect } from 'react'
@@ -8,6 +9,8 @@ import { urls } from 'scenes/urls'
 import { mswDecorator, setFeatureFlags } from '~/mocks/browser'
 import { EMPTY_PAGINATED_RESPONSE } from '~/mocks/handlers'
 
+import { navigationLogic } from '../navigation/navigationLogic'
+
 const meta: Meta = {
     title: 'PostHog 3000/Navigation',
     decorators: [
@@ -25,6 +28,8 @@ const meta: Meta = {
         layout: 'fullscreen',
         testOptions: {
             includeNavigationInSnapshot: true,
+            waitForLoadersToDisappear: true,
+            snapshotBrowsers: ['chromium'],
         },
         viewMode: 'story',
         mockDate: '2023-02-01',
@@ -41,10 +46,12 @@ export function NavigationBase(): JSX.Element {
 }
 
 export function Navigation3000(): JSX.Element {
+    const { openAccountPopover } = useActions(navigationLogic)
     setFeatureFlags([FEATURE_FLAGS.POSTHOG_3000_NAV])
     useEffect(() => {
         router.actions.push(urls.projectHomepage())
-    }, [])
+        openAccountPopover()
+    }, [openAccountPopover])
 
     return <App />
 }
diff --git a/frontend/src/layout/navigation/TopBar/AccountPopover.tsx b/frontend/src/layout/navigation/TopBar/AccountPopover.tsx
index 92e40b53429d..b1d33c9b1495 100644
--- a/frontend/src/layout/navigation/TopBar/AccountPopover.tsx
+++ b/frontend/src/layout/navigation/TopBar/AccountPopover.tsx
@@ -3,6 +3,7 @@ import './AccountPopover.scss'
 import {
     IconCheckCircle,
     IconConfetti,
+    IconCopy,
     IconFeatures,
     IconGear,
     IconLeave,
@@ -20,7 +21,9 @@ import { LemonButton } from 'lib/lemon-ui/LemonButton'
 import { ProfilePicture } from 'lib/lemon-ui/ProfilePicture'
 import { UploadedLogo } from 'lib/lemon-ui/UploadedLogo'
 import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
+import { copyToClipboard } from 'lib/utils/copyToClipboard'
 import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
+import { billingLogic } from 'scenes/billing/billingLogic'
 import { inviteLogic } from 'scenes/settings/organization/inviteLogic'
 import { ThemeSwitcher } from 'scenes/settings/user/ThemeSwitcher'
 
@@ -110,6 +113,36 @@ function CurrentOrganization({ organization }: { organization: OrganizationBasic
     )
 }
 
+function AccountOwner({ name, email }: { name: string; email: string }): JSX.Element {
+    const { reportAccountOwnerClicked } = useActions(eventUsageLogic)
+
+    return (
+        <LemonButton
+            onClick={() => {
+                void copyToClipboard(email, 'email')
+                reportAccountOwnerClicked({ name, email })
+            }}
+            fullWidth
+            sideIcon={<IconCopy />}
+            tooltip="This is your dedicated PostHog human. Click to copy their email. They can help you with trying out new products, solving problems, and reducing your spend."
+        >
+            <div className="flex items-center gap-2 grow">
+                <ProfilePicture
+                    user={{
+                        first_name: name,
+                        email: email,
+                    }}
+                    size="md"
+                />
+                <div>
+                    <div className="font-medium truncate">{name}</div>
+                    <div className="text-sm text-muted truncate">{email}</div>
+                </div>
+            </div>
+        </LemonButton>
+    )
+}
+
 export function InviteMembersButton({
     text = 'Invite members',
     center = false,
@@ -215,6 +248,7 @@ export function AccountPopoverOverlay(): JSX.Element {
     const { preflight, isCloudOrDev, isCloud } = useValues(preflightLogic)
     const { closeAccountPopover } = useActions(navigationLogic)
     const { featureFlags } = useValues(featureFlagLogic)
+    const { billing } = useValues(billingLogic)
 
     return (
         <>
@@ -239,6 +273,12 @@ export function AccountPopoverOverlay(): JSX.Element {
                     </LemonButton>
                 ) : null}
                 <InviteMembersButton />
+                {billing?.account_owner?.email && billing?.account_owner?.name && (
+                    <>
+                        <h5 className="flex items-center mt-2">YOUR POSTHOG HUMAN</h5>
+                        <AccountOwner name={billing.account_owner.name} email={billing.account_owner.email} />
+                    </>
+                )}
             </AccountPopoverSection>
             {(otherOrganizations.length > 0 || preflight?.can_create_org) && (
                 <AccountPopoverSection title="Other organizations">
diff --git a/frontend/src/lib/utils/eventUsageLogic.ts b/frontend/src/lib/utils/eventUsageLogic.ts
index 8e8fab42c0d1..ec489530ef88 100644
--- a/frontend/src/lib/utils/eventUsageLogic.ts
+++ b/frontend/src/lib/utils/eventUsageLogic.ts
@@ -554,6 +554,7 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
         reportCommandBarActionResultExecuted: (resultDisplay) => ({ resultDisplay }),
         reportBillingCTAShown: true,
         reportSDKSelected: (sdk: SDK) => ({ sdk }),
+        reportAccountOwnerClicked: ({ name, email }: { name: string; email: string }) => ({ name, email }),
     }),
     listeners(({ values }) => ({
         reportBillingCTAShown: () => {
@@ -1340,5 +1341,8 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
         reportCommandBarActionResultExecuted: ({ resultDisplay }) => {
             posthog.capture('command bar search result executed', { resultDisplay })
         },
+        reportAccountOwnerClicked: ({ name, email }) => {
+            posthog.capture('account owner clicked', { name, email })
+        },
     })),
 ])
diff --git a/frontend/src/mocks/fixtures/_billing.tsx b/frontend/src/mocks/fixtures/_billing.tsx
index acae28c8f887..52ffd493af78 100644
--- a/frontend/src/mocks/fixtures/_billing.tsx
+++ b/frontend/src/mocks/fixtures/_billing.tsx
@@ -3644,4 +3644,8 @@ export const billingJson: BillingType = {
     stripe_portal_url:
         'https://billing.stripe.com/p/session/test_YWNjdF8xSElNRERFdUlhdFJYU2R6LF9QaEVJR3VyemlvMDZzRzdiQXZrc1AxSjNXZk1BellP0100ZsforDQG',
     subscription_level: 'paid',
+    account_owner: {
+        name: 'Simon Fisher',
+        email: 'simon@posthog.com',
+    },
 }
diff --git a/frontend/src/scenes/billing/Billing.stories.tsx b/frontend/src/scenes/billing/Billing.stories.tsx
index 455f76c3d080..5c653124bb5b 100644
--- a/frontend/src/scenes/billing/Billing.stories.tsx
+++ b/frontend/src/scenes/billing/Billing.stories.tsx
@@ -75,6 +75,7 @@ export const BillingWithCreditCTA = (): JSX.Element => {
         get: {
             '/api/billing/': {
                 ...billingJson,
+                account_owner: null,
             },
             '/api/billing/credits/overview': {
                 status: 'none',
diff --git a/frontend/src/scenes/billing/Billing.tsx b/frontend/src/scenes/billing/Billing.tsx
index dfb491c29bdd..0e47c99db516 100644
--- a/frontend/src/scenes/billing/Billing.tsx
+++ b/frontend/src/scenes/billing/Billing.tsx
@@ -32,8 +32,15 @@ export const scene: SceneExport = {
 }
 
 export function Billing(): JSX.Element {
-    const { billing, billingLoading, isOnboarding, showLicenseDirectInput, isActivateLicenseSubmitting, billingError } =
-        useValues(billingLogic)
+    const {
+        billing,
+        billingLoading,
+        isOnboarding,
+        showLicenseDirectInput,
+        isActivateLicenseSubmitting,
+        billingError,
+        isManagedAccount,
+    } = useValues(billingLogic)
     const { reportBillingShown } = useActions(billingLogic)
     const { preflight, isCloudOrDev } = useValues(preflightLogic)
     const { openSupportForm } = useActions(supportLogic)
@@ -152,7 +159,7 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
                 <div className="mb-4">
                     <BillingCTAHero product={platformAndSupportProduct} />
                 </div>
diff --git a/frontend/src/scenes/billing/billingLogic.tsx b/frontend/src/scenes/billing/billingLogic.tsx
index d0861f330498..6ca00c3d6761 100644
--- a/frontend/src/scenes/billing/billingLogic.tsx
+++ b/frontend/src/scenes/billing/billingLogic.tsx
@@ -441,6 +441,12 @@ export const billingLogic = kea<billingLogicType>([
             },
         ],
         creditDiscount: [(s) => [s.computedDiscount], (computedDiscount) => computedDiscount || 0],
+        isManagedAccount: [
+            (s) => [s.billing],
+            (billing: BillingType): boolean => {
+                return !!(billing?.account_owner?.name || billing?.account_owner?.email)
+            },
+        ],
     }),
     forms(({ actions, values }) => ({
         activateLicense: {
diff --git a/frontend/src/types.ts b/frontend/src/types.ts
index b78d070246fc..6b4e31e32665 100644
--- a/frontend/src/types.ts
+++ b/frontend/src/types.ts
@@ -1815,6 +1815,10 @@ export interface BillingType {
         target: 'paid' | 'teams' | 'enterprise'
         expires_at: string
     }
+    account_owner?: {
+        email?: string
+        name?: string
+    }
 }
 
 export interface BillingPlanType {


Reviews:
user: login: greptile-apps[bot]
body: 
## PR Summary

This PR adds functionality to hide upgrade CTAs from managed accounts and display account owner information in the UI, improving the experience for managed accounts and aligning with sales team efforts.

- Added `isManagedAccount` selector in `frontend/src/scenes/billing/billingLogic.tsx` to determine account status based on owner presence
- Added new `account_owner` field with `email` and `name` properties to `BillingType` interface in `frontend/src/types.ts`
- Added `AccountOwner` component in `frontend/src/layout/navigation/TopBar/AccountPopover.tsx` with click-to-copy functionality
- Modified `CreditCTAHero` and `Billing` components to conditionally hide upgrade CTAs for managed accounts
- Added event tracking in `eventUsageLogic.ts` for account owner information interactions

<sub>6 file(s) reviewed, 1 comment(s)</sub>
<sub>[Edit PR Review Bot Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews&utm_content=posthog_30247)</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T18:37:50Z
user: login: zlwaterfield
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T19:19:49Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T09:04:20Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T09:14:47Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T09:32:44Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T14:25:48Z
user: login: zlwaterfield
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T14:29:36Z
user: login: zlwaterfield
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T14:30:37Z
user: login: zlwaterfield
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T14:34:10Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T15:33:31Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T15:35:25Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T15:35:53Z
user: login: pawel-cebula
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T15:36:37Z
user: login: zlwaterfield
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T16:01:15Z

Review comments:
diff_hunk: @@ -110,6 +113,36 @@ function CurrentOrganization({ organization }: { organization: OrganizationBasic
     )
 }
 
+function AccountOwner({ name, email }: { name: string; email: string }): JSX.Element {
+    const { reportAccountOwnerClicked } = useActions(eventUsageLogic)
+
+    return (
+        <LemonButton
+            onClick={() => {
+                void copyToClipboard(email, 'email')
+                reportAccountOwnerClicked({ name, email })
+            }}
path: frontend/src/layout/navigation/TopBar/AccountPopover.tsx
user: login: greptile-apps[bot]
body: style: The void operator is unnecessary here since copyToClipboard already returns void
created_at: 2025-03-20T18:36:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,12 +15,12 @@ export const CreditCTAHero = (): JSX.Element | null => {
     const { width, ref: heroRef } = useResizeObserver()
     const { featureFlags } = useValues(featureFlagLogic)
 
-    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } =
+    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount, isManagedAccount } =
         useValues(billingLogic)
     const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic)
 
     const isEligible = creditOverview.eligible || featureFlags[FEATURE_FLAGS.SELF_SERVE_CREDIT_OVERRIDE]
-    if (creditOverview.status === 'paid' || !isEligible) {
+    if (isManagedAccount || creditOverview.status === 'paid' || !isEligible) {
path: frontend/src/scenes/billing/CreditCTAHero.tsx
user: login: zlwaterfield
body: I'd rather this check go in billing for credit overview logic so it stays all together. 
created_at: 2025-03-20T19:17:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
                 <div className="mb-4">
                     <BillingCTAHero product={platformAndSupportProduct} />
                 </div>
             )}
 
-            <CreditCTAHero />
+            {!isManagedAccount && <CreditCTAHero />}
path: frontend/src/scenes/billing/Billing.tsx
user: login: zlwaterfield
body: Same as other comment, we can do this in billing
created_at: 2025-03-20T19:18:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
path: frontend/src/scenes/billing/Billing.tsx
user: login: zlwaterfield
body: This change probably conflicts with your other PR - also managed accounts shouldn't be on free accounts so I think this won't be needed. 
created_at: 2025-03-20T19:18:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -239,6 +273,12 @@ export function AccountPopoverOverlay(): JSX.Element {
                     </LemonButton>
                 ) : null}
                 <InviteMembersButton />
+                {billing?.account_owner?.email && billing?.account_owner?.name && (
path: frontend/src/layout/navigation/TopBar/AccountPopover.tsx
user: login: zlwaterfield
body: This looks awesome - we should make sure to add a story with an updated fixture so we have a snapshot for this. LMK if you need an hand with that. 
created_at: 2025-03-20T19:19:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
path: frontend/src/scenes/billing/Billing.tsx
user: login: pawel-cebula
body: > This change probably conflicts with your other PR

Yup will see what gets merged first and resolve conflicts then

> also managed accounts shouldn't be on free accounts so I think this won't be needed.

I assumed so too initially but then thought that maybe an account gets AE/CSM assigned in Vitally when they reach out and start convo but before they sign. Will confirm with Mine.
created_at: 2025-03-21T09:04:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,12 +15,12 @@ export const CreditCTAHero = (): JSX.Element | null => {
     const { width, ref: heroRef } = useResizeObserver()
     const { featureFlags } = useValues(featureFlagLogic)
 
-    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } =
+    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount, isManagedAccount } =
         useValues(billingLogic)
     const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic)
 
     const isEligible = creditOverview.eligible || featureFlags[FEATURE_FLAGS.SELF_SERVE_CREDIT_OVERRIDE]
-    if (creditOverview.status === 'paid' || !isEligible) {
+    if (isManagedAccount || creditOverview.status === 'paid' || !isEligible) {
path: frontend/src/scenes/billing/CreditCTAHero.tsx
user: login: pawel-cebula
body: Do you mean to include `is_managed_account` in the `/billing` API response (derived from `account_owner`)? Or to incorporate it into `credits_overview` returned from `/billing (either by influencing `eligible` or as a separate property on `credit_overview` ?
created_at: 2025-03-21T09:14:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
path: frontend/src/scenes/billing/Billing.tsx
user: login: pawel-cebula
body: Simon replied

> Q: Can an account be managed (get AE/CSM assigned in Vitally) before becoming a paying customer?

> A: Yes they might do if the AE is managing them through a trial

> Q: Got it and technically could they already get AE/CSM assigned before starting a trial? E.g. when they reach out to the team as a prospect. Or AE/CSM would only get assigned once at least on trial?

> A: We’d only assign them in Vitally once having spoken with them and got them on a trial

So technically it's not needed since we'd hide this already if they're on the trial but I'd still lean towards keeping this check to make it future proof in case sales process changes?
created_at: 2025-03-21T09:32:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -239,6 +273,12 @@ export function AccountPopoverOverlay(): JSX.Element {
                     </LemonButton>
                 ) : null}
                 <InviteMembersButton />
+                {billing?.account_owner?.email && billing?.account_owner?.name && (
path: frontend/src/layout/navigation/TopBar/AccountPopover.tsx
user: login: pawel-cebula
body: Good callout, I've added `account_owner` [here](https://github.com/PostHog/posthog/pull/30247/commits/5190806d895ce6d2984c621bb66e3b166225b03f) to the fixture and then modified the `Navigation` story to open the menu and the updated navigation snapshots now show the opened menu and account owner.

I have one side-effect issue now because adding `account_owner` impacts the credits CTA snapshot as it uses the same `_billing` fixture. I've tried overriding `account_owner` [here](https://github.com/PostHog/posthog/pull/30247/commits/0c542f942807ef951912d74a62d7aa4870bebb25) but it didn't seem to work. Any ideas on what I might be missing?

(I guess removing those `isManagedAccount` checks would solve it indirectly but I still wonder if we shouldn't keep them in case sales process changes - see [here](https://github.com/PostHog/posthog/pull/30247#discussion_r2007182303) for context)
created_at: 2025-03-21T14:25:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,12 +15,12 @@ export const CreditCTAHero = (): JSX.Element | null => {
     const { width, ref: heroRef } = useResizeObserver()
     const { featureFlags } = useValues(featureFlagLogic)
 
-    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } =
+    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount, isManagedAccount } =
         useValues(billingLogic)
     const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic)
 
     const isEligible = creditOverview.eligible || featureFlags[FEATURE_FLAGS.SELF_SERVE_CREDIT_OVERRIDE]
-    if (creditOverview.status === 'paid' || !isEligible) {
+    if (isManagedAccount || creditOverview.status === 'paid' || !isEligible) {
path: frontend/src/scenes/billing/CreditCTAHero.tsx
user: login: zlwaterfield
body: Add the check for if it's a managed account into `credits_overview` (https://github.com/PostHog/billing/blob/main/billing/models/customer.py#L2565). 

So it they are a managed account return eligible as false. 
created_at: 2025-03-21T14:29:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
path: frontend/src/scenes/billing/Billing.tsx
user: login: zlwaterfield
body: We do have cta in other places so it's not really hiding all of them but I'm ok with this change for now. 
created_at: 2025-03-21T14:30:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -239,6 +273,12 @@ export function AccountPopoverOverlay(): JSX.Element {
                     </LemonButton>
                 ) : null}
                 <InviteMembersButton />
+                {billing?.account_owner?.email && billing?.account_owner?.name && (
path: frontend/src/layout/navigation/TopBar/AccountPopover.tsx
user: login: zlwaterfield
body: I think you're change the wrong fixture - look at `BillingWithCreditCTA`, the snapshot name is the same as the story function name. 
created_at: 2025-03-21T14:33:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -239,6 +273,12 @@ export function AccountPopoverOverlay(): JSX.Element {
                     </LemonButton>
                 ) : null}
                 <InviteMembersButton />
+                {billing?.account_owner?.email && billing?.account_owner?.name && (
path: frontend/src/layout/navigation/TopBar/AccountPopover.tsx
user: login: pawel-cebula
body: 🤦‍♂️ yup that was it
created_at: 2025-03-21T15:33:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
                 <div className="mb-4">
                     <BillingCTAHero product={platformAndSupportProduct} />
                 </div>
             )}
 
-            <CreditCTAHero />
+            {!isManagedAccount && <CreditCTAHero />}
path: frontend/src/scenes/billing/Billing.tsx
user: login: pawel-cebula
body: Removed
created_at: 2025-03-21T15:35:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,12 +15,12 @@ export const CreditCTAHero = (): JSX.Element | null => {
     const { width, ref: heroRef } = useResizeObserver()
     const { featureFlags } = useValues(featureFlagLogic)
 
-    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } =
+    const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount, isManagedAccount } =
         useValues(billingLogic)
     const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic)
 
     const isEligible = creditOverview.eligible || featureFlags[FEATURE_FLAGS.SELF_SERVE_CREDIT_OVERRIDE]
-    if (creditOverview.status === 'paid' || !isEligible) {
+    if (isManagedAccount || creditOverview.status === 'paid' || !isEligible) {
path: frontend/src/scenes/billing/CreditCTAHero.tsx
user: login: pawel-cebula
body: Done on `billing` side and removed here.
created_at: 2025-03-21T15:35:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,13 +159,13 @@ export function Billing(): JSX.Element {
                 </LemonBanner>
             ) : null}
 
-            {!billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
+            {!isManagedAccount && !billing?.has_active_subscription && !billing?.trial && platformAndSupportProduct && (
path: frontend/src/scenes/billing/Billing.tsx
user: login: pawel-cebula
body: Got it, will keep it then and try to track down other places where we might want to hide them (might do that as a follow up so that we can merge this?)
created_at: 2025-03-21T15:36:37Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-20T18:47:57Z
body: **Size Change:** +278 B (0%) 

**Total Size:** 9.75 MB



<details><summary>ℹ️ <strong>View Unchanged</strong></summary>

| Filename | Size | Change |
| :--- | :---: | :---: |
| `frontend/dist/toolbar.js` | 9.75 MB | +278 B (0%) |

</details>



<a href="https://github.com/preactjs/compressed-size-action"><sub>compressed-size-action</sub></a>
author_association: CONTRIBUTOR
user: login: posthog-bot
created_at: 2025-03-21T09:44:32Z
body: ## 📸 UI snapshots have been updated

**2** snapshot changes in total. **0** added, **2** modified, **0** deleted:

- **`chromium`**: **0** added, **2** modified, **0** deleted ([diff for shard 5](https://github.com/PostHog/posthog/pull/30247/commits/ba4fb63e6ffb6e116e6a42cfe8c683adeca6ffb7))
- `webkit`: **0** added, **0** modified, **0** deleted

Triggered by [this commit](https://github.com/PostHog/posthog/pull/30247/commits/e52fce42c4a9d0aad61af51c81f1a7728ca45c03).

👉 **[Review this PR's diff of snapshots.](https://github.com/PostHog/posthog/pull/30247/files#:~:text=frontend/__snapshots__/)**
author_association: CONTRIBUTOR
user: login: posthog-bot
created_at: 2025-03-21T12:39:28Z
body: ## 📸 UI snapshots have been updated

**2** snapshot changes in total. **0** added, **2** modified, **0** deleted:

- **`chromium`**: **0** added, **2** modified, **0** deleted ([diff for shard 4](https://github.com/PostHog/posthog/pull/30247/commits/7e39513aa2c3f22d240f6529de60d3691af380dd))
- `webkit`: **0** added, **0** modified, **0** deleted

Triggered by [this commit](https://github.com/PostHog/posthog/pull/30247/commits/2fb2353489467798cc1de3f38fc9b291b489bc50).

👉 **[Review this PR's diff of snapshots.](https://github.com/PostHog/posthog/pull/30247/files#:~:text=frontend/__snapshots__/)**
author_association: CONTRIBUTOR
user: login: posthog-bot
created_at: 2025-03-21T14:03:56Z
body: ## 📸 UI snapshots have been updated

**2** snapshot changes in total. **0** added, **2** modified, **0** deleted:

- **`chromium`**: **0** added, **2** modified, **0** deleted ([diff for shard 4](https://github.com/PostHog/posthog/pull/30247/commits/8bbdc0bdb443d2baf503911e78b6b9994e677007))
- `webkit`: **0** added, **0** modified, **0** deleted

Triggered by [this commit](https://github.com/PostHog/posthog/pull/30247/commits/b43e343bc408ca399710acde3f81cef368306643).

👉 **[Review this PR's diff of snapshots.](https://github.com/PostHog/posthog/pull/30247/files#:~:text=frontend/__snapshots__/)**
author_association: CONTRIBUTOR
user: login: posthog-bot
created_at: 2025-03-21T15:10:07Z
body: ## 📸 UI snapshots have been updated

**2** snapshot changes in total. **0** added, **2** modified, **0** deleted:

- **`chromium`**: **0** added, **2** modified, **0** deleted ([diff for shard 5](https://github.com/PostHog/posthog/pull/30247/commits/50f0ab527066106d664a3706299a08108e5942e0))
- `webkit`: **0** added, **0** modified, **0** deleted

Triggered by [this commit](https://github.com/PostHog/posthog/pull/30247/commits/146a50b0a7bd61f3683184a44c65d3845142831a).

👉 **[Review this PR's diff of snapshots.](https://github.com/PostHog/posthog/pull/30247/files#:~:text=frontend/__snapshots__/)**
author_association: CONTRIBUTOR
user: login: posthog-bot
created_at: 2025-03-21T15:19:33Z
body: ## 📸 UI snapshots have been updated

**1** snapshot changes in total. **0** added, **1** modified, **0** deleted:

- **`chromium`**: **0** added, **1** modified, **0** deleted ([diff for shard 5](https://github.com/PostHog/posthog/pull/30247/commits/596785912b426585928bfd188f87c912194749f6))
- `webkit`: **0** added, **0** modified, **0** deleted

Triggered by [this commit](https://github.com/PostHog/posthog/pull/30247/commits/0427962b5176fe9b94a0099590c66ac34f877e1e).

👉 **[Review this PR's diff of snapshots.](https://github.com/PostHog/posthog/pull/30247/files#:~:text=frontend/__snapshots__/)**
author_association: CONTRIBUTOR