CodeGym /Courses /ChatGPT Apps /Marketing and growth tied to product metrics

Marketing and growth tied to product metrics

ChatGPT Apps
Level 19 , Lesson 2
Available

1. Why ChatGPT App marketing is product analytics, not “noise”

In the classic web you can plug in Google Analytics, hang UTM tags on all links, add a couple of retargeting pixels — and call it a day. In the ChatGPT ecosystem it’s different. The user is inside the ChatGPT interface, and your App is a “guest” in that dialogue. Cookies, iframe, and Facebook Pixel don’t really live here.

This automatically makes product events the primary (and often the only) source of truth about growth. How often do people open the App? Do they reach the key scenario? Do they come back? How is this tied to revenue? These questions are answered not by an external counter, but by your MCP events and server-side analytics.

This is exactly where the term product‑led growth (PLG) logically surfaces: growth comes not from how many banners you bought, but from how well the product covers the user scenario and how you evolve it based on data.

Therefore, the main character of this lecture is the event funnel inside GiftGenius, not an external marketing channel. Channels will show up, but only as hypotheses that influence these events.

AARRR for GiftGenius: our own pirate funnel

The AARRR model (Acquisition, Activation, Retention, Revenue, Referral) fits a ChatGPT App perfectly — you just need to translate it into the event language of our application.

For GiftGenius it could look like this:

Stage What it means for GiftGenius Which event we log
Acquisition User launches GiftGenius in ChatGPT for the first time
app_opened
Activation User completes gift selection for the first time (receives ideas)
workflow_completed (first time)
Retention User returns after N days and uses the App again
subsequent workflow_completed / app_opened
Revenue User proceeds to checkout and successfully buys a gift
checkout_started, checkout_success
Referral User brings others (shares the chat, a link to the App)
referral_sent, referral_activated (optional)

It’s important that this funnel is described not by frontend clicks, but by “usage events” at the MCP/App level: user opened, went through the scenario, paid, returned. Unlike the web, where you sometimes track “every mouse move,” here analytics should be compact and meaningful: less about “where they clicked,” more about “what they did in the scenario.”

For the basic GiftGenius version we primarily focus on the first four levels (Acquisition, Activation, Retention, Revenue). Referral remains important, but is more of a next growth stage that you can enable once the product core and payments stabilize.

2. Designing the event model: from logs to analytics

In the observability module we already agreed to write structured JSON logs, not free-form “log novels.” Now we build a product event model on top of them.

The minimal idea: every important step in the App yields an event object. On the MCP side you can both log it and send it to an external analytics system (BI, ClickHouse, BigQuery — pick your poison).

The simplest event definition for GiftGenius might look like this:

// General event shape
type GiftGeniusEventType =
  | 'app_opened'
  | 'workflow_started'
  | 'workflow_completed'
  | 'ideas_shown'
  | 'idea_clicked'
  | 'checkout_started'
  | 'checkout_success'
  | 'checkout_failed';

interface AnalyticsEvent {
  type: GiftGeniusEventType;
  userId?: string;          // from auth, if available
  sessionId: string;        // ChatGPT session UUID
  timestamp: string;        // ISO string
  properties?: Record<string, unknown>;
}

It’s handy to introduce a small helper for sending events from the Next.js part of the application:

async function trackEvent(event: AnalyticsEvent) {
  await fetch('/api/analytics', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(event),
  });
}

On the server at /api/analytics you can decide what to do with it: store in a database, send to a logger, or stream into a data pipeline. The key is that all events share a unified format. In practice you will have the same set of product events but several points where they originate: some steps are easier to record right on the MCP server via logger.info, and some to send from the widget as an AnalyticsEvent to /api/analytics. What matters is not how many technical “pipes” you have, but that the event types ("app_opened", "workflow_completed", etc.) and their fields remain unified and consistent.

3. Acquisition: how to understand where users actually come from

The first task of marketing is to answer who is coming and how many. In a ChatGPT App this “arrival” is recorded by launching the App in a chat. What we want to log is "app_opened".

For GiftGenius you can do this on the widget side (reacting to the component mount) and on the server (for example, on the first callTool in a session). Server-side is more reliable to avoid render peculiarities, but we’ll look at the frontend for simplicity.

Example GiftGenius widget component that calls trackEvent on first render:

import { useEffect, useRef } from 'react';
import { trackEvent } from '../lib/analytics';

export default function GiftGeniusWidget() {
  const reported = useRef(false);

  useEffect(() => {
    if (reported.current) return;
    reported.current = true;

    trackEvent({
      type: 'app_opened',
      sessionId: crypto.randomUUID(),
      timestamp: new Date().toISOString(),
      properties: { source: 'chatgpt_app' },
    });
  }, []);

  return (
    <main>
      {/* ...main widget UI... */}
    </main>
  );
}

In practice you’ll want to obtain sessionId and userId from the existing context (for example, from _meta or an auth token), not generate them on the client. The point is that every GiftGenius launch should produce such an event.

Traffic source attribution is harder than on the web: referrers and UTM tags are limited. Teams typically use one of two strategies. First — assume the Store is the main traffic source and analyze only "app_opened" over time: if you roll out a new Store listing, watch for a spike in "app_opened" and subsequent funnel levels. Second — use explicit parameters: if you give a user a link like https://chat.openai.com/...&utm_source=blog2025, then on the first "app_opened" you can take this tag from the context and put it into the referral_source field.

So acquisition metrics look roughly like this: “count of "app_opened" per day,” “count of unique userId who launched the App per week,” “distribution by referral_source, if you have it.”

4. Activation: finding the “aha moment” inside GiftGenius

Acquisition alone means nothing if people immediately close the App. The second key layer is Activation. It’s the moment when a user first feels the App does something truly useful.

For GiftGenius it’s logical to associate this with workflow completion: the user enters information about the recipient, sets filters, and the App shows, say, 10 relevant ideas. That is when the user first sees the value.

It’s convenient to record this via a "workflow_completed" event. It’s better to log this step on the MCP server when you’ve compiled all gifts and are sending the result to the widget:

logger.info('event.workflow_completed', {
  type: 'workflow_completed',
  userId,
  sessionId,
  requestId,
  ideasCount: giftIdeas.length,
  timestamp: new Date().toISOString(),
});

Here, logger is your structured logger that you already added for SLO and cost instrumentation. We simply added a product event to it.

Your activation rate will be measured by "workflow_completed": activation_rate = (number of unique userId with at least one "workflow_completed") / (number of unique userId with "app_opened" over the period).

You can also look more coarsely: “the share of sessionId sessions that had a "workflow_completed".” What matters is that it’s a familiar metric to you: the higher the activation, the better the App’s start.

5. Retention: do users come back to your App

Retention for a ChatGPT App is a bit more nuanced than for a typical web product. On one hand, ChatGPT itself is a place people return to anyway. On the other, they might return to a slew of other Apps — not yours. We need to understand whether they come back to GiftGenius.

If you have authentication (module 10), you have a stable userId or tenantId. Then the classic definition is simple: a user is considered “retained” if, say, 7 days after their first "workflow_completed" they have a new "workflow_completed" or at least an "app_opened".

If you don’t have auth, you can use a weaker metric based on sessionId and heuristic userKey (for example, a hash of the OpenAI account if available in _meta), but in this lecture we’ll assume we do have userId.

As SQL-like logic, this looks roughly like (pseudo code):

-- first activation
WITH first_activation AS (
  SELECT user_id, MIN(timestamp) AS first_ts
  FROM events
  WHERE type = 'workflow_completed'
  GROUP BY user_id
),
retained_d7 AS (
  SELECT fa.user_id
  FROM first_activation fa
  JOIN events e
    ON e.user_id = fa.user_id
   AND e.timestamp >= fa.first_ts + INTERVAL '7 day'
   AND e.timestamp <  fa.first_ts + INTERVAL '14 day'
   AND e.type IN ('app_opened', 'workflow_completed')
)
SELECT COUNT(*) / (SELECT COUNT(*) FROM first_activation) AS d7_retention
FROM retained_d7;

You don’t have to write such SQL beauty in production, but you should understand the idea: retention is about whether people come back to use the App again, not just whether they reached a one-time payment.

6. Revenue: linking the funnel to money

The Revenue layer for GiftGenius anchors why we’re doing all this at all. In the commerce module we already added events around payments: "checkout_started", "checkout_success", "checkout_failed". These events become the key to product revenue metrics: conversion and average order value.

When a user clicks “Buy gift” and you create a checkout session (via ACP/Stripe), you should log an event on the MCP side:

logger.info('event.checkout_started', {
  type: 'checkout_started',
  userId,
  sessionId,
  requestId,
  amount: checkout.amount,
  currency: checkout.currency,
  timestamp: new Date().toISOString(),
});

When a successful webhook arrives from the PSP:

logger.info('event.checkout_success', {
  type: 'checkout_success',
  userId,
  sessionId,
  orderId,
  amount: payment.amount,
  currency: payment.currency,
  timestamp: new Date().toISOString(),
});

Now you can easily calculate conversion:

  • “from "workflow_completed" to "checkout_started"” — how often people go to payment at all;
  • “from "checkout_started" to "checkout_success"” — how well your commerce flow performs (card errors, fraud, payment UX).

At the same time these events connect to the cost logs from the previous lesson on cost control and cost instrumentation: by requestId or sessionId you know which tool calls and how many tokens/money the path to that purchase cost. This yields metrics like “average cost_per_paid_workflow” and “revenue minus cost per one successful order.”

7. Referral: when users bring others

The Referral layer in a ChatGPT App is a bit unusual. You don’t have your own push or email blasts, but users can share chats, links, and simply tell each other “search GiftGenius in the Store.”

Technically you can introduce "referral_sent" and "referral_activated" events if:

  • you give users a referral code or a parameter in the link to the App (?ref=friend123),
  • or you process referral_source/campaign in the "app_opened" context.

In the basic MVP version of GiftGenius you can leave Referral for later — first it’s important to build out Acquisition/Activation/Revenue and make sure the core of the funnel works. But it’s important to understand where to “attach” it: to the same event logs and metrics, not to a separate Excel with promo codes.

Visual funnel of GiftGenius

To keep the picture in mind, it’s useful to draw a small diagram:

flowchart LR
  A[app_opened] --> B[workflow_started]
  B --> C[workflow_completed]
  C --> D[checkout_started]
  D --> E[checkout_success]

Each edge here is a conversion you can measure. Marketing, UX changes, model experiments — all of it should eventually push one or more of these conversions up. If you’re doing something and can’t say which specific edge should improve, that’s suspicious.

Growth dashboards: which reports do you need first

Let’s imagine a minimal growth dashboard for GiftGenius. We’re not building a space-grade BI system here — we want at least a table we can look at every week.

Example of an aggregated daily report:

Day app_opened workflow_completed Activation‑rate checkout_success Conv. completed→paid Revenue (USD)
2025‑11‑01 120 60 50% 12 20% 600
2025‑11‑02 90 48 53% 9 19% 450
2025‑11‑03 200 80 40% 8 10% 400

It’s immediately visible that on the 3rd we “poured” acquisition (increased "app_opened"), but activation and conversion dropped — perhaps the traffic wasn’t the right fit or you broke something in the UX. Tables like this help distinguish good marketing from merely loud marketing.

On top of time, it’s useful to look at cohorts as well: users who came in a given week and their retention after 7/30 days. But to start, it’s enough to build simple day and week slices.

8. Marketing as a series of experiments on events

Now to the most “marketing” moment: how to connect external activities (articles, Store listing, partnerships) with what we see in the App’s events.

The key principle: any marketing idea is formulated as a hypothesis about which product metrics should change.

For GiftGenius, for example:

  • “If we improve the Store listing (icons, description, demo video), the number of "app_opened" from new users should grow and, ideally, the activation rate among them too.”
  • “If we write an article about choosing gifts for New Year’s and include a link to GiftGenius, then over the next 3 days we should see growth in "app_opened" with referral_source = "blog_ny2025", followed by "workflow_completed" in that cohort.”

Technically this is often implemented via an additional campaign or referral_source field in the "app_opened" event. For example, if upon App initialization you received a tag from the ChatGPT context:

trackEvent({
  type: 'app_opened',
  sessionId,
  timestamp: new Date().toISOString(),
  properties: {
    referral_source: openaiContext.referralSource ?? 'organic',
    app_version: '1.3.0',
  },
});

Now you can build “by campaign” reports: how many "app_opened" and "workflow_completed" among those who came with referral_source = "blog_ny2025", and how that differs from organic.

It’s important that we don’t consider marketing successful based only on “reach” measured somewhere else. If a blogger says their video had a million views, great — but for GiftGenius success means “growth of "app_opened" and "workflow_completed" inside our product.”

9. Example: a marketing experiment for GiftGenius

Let’s put it all together on a concrete scenario and carefully tie an external campaign to product events inside GiftGenius.

Suppose you want to test the hypothesis that an article in a popular gifts blog will bring the “right” users. In the article you link not directly to ChatGPT, but to your landing page, for example:

https://giftgenius.app/landing?utm_source=giftblog2025

The user arrives at a short landing with a description of GiftGenius and a button “Open in ChatGPT.” On the landing’s backend you read utm_source and store it in the user profile (or a separate table), for example as acquisitionSource = "giftblog2025". The landing button then points to your ChatGPT App in the Store, the user connects the App and starts using it.

When this user launches GiftGenius in ChatGPT and your backend receives the first call from the Apps SDK / MCP, you pull the saved acquisitionSource and add it to the product events. For "app_opened" it might look like this:

logger.info('event.app_opened', {
  type: 'app_opened',
  userId,
  sessionId,
  referral_source: user.acquisitionSource ?? 'organic',
  timestamp: new Date().toISOString(),
});

You mark "workflow_completed", "checkout_started", and "checkout_success" events the same way. Then the experiment boils down to comparing cohorts: users with referral_source = "giftblog2025" versus organic. If the “blog” cohort has a higher share of completed scenarios and payments with comparable or better revenue per user, the campaign can be considered successful; if only app launches grow while conversion to "workflow_completed" and "checkout_success" drops, the article is bringing mostly curious onlookers rather than buyers.

This approach is good because you once carefully “translate” the UTM tag from the web world into your internal referral_source field and then work only with the App’s product analytics — no magic and no attempts to pass URL parameters directly into ChatGPT.

At the same time you can track unit economics if you record CAC somewhere (how much the placement cost) and cost_per_task. Then the hypothesis turns into a more “financial” experiment: “Does this channel pay off?”

10. Privacy‑first analytics: don’t break policy or common sense

An important point — how not to become a little Facebook. Unlike the classic web, OpenAI is quite strict about privacy in ChatGPT Apps: you can’t track personal data, hoard extra PII, or send full conversation text anywhere.

Good analytics practice for GiftGenius looks like this:

  1. Don’t store raw user message text in events. Instead, log only “facts of the scenario”: scenario type, number of ideas shown, fact of successful payment.
  2. If you need to distinguish users, use pseudonymous identifiers (userId, tenantId), not email/name. Any PII is stored in an authenticated database; analytics operates with anonymized keys.
  3. Avoid fields in logs and events that can directly identify a person if not needed for the job (for example, the full shipping address clearly doesn’t belong in an event; its place is in the protected commerce database).
  4. Use aggregated analytics as much as possible: you care about activation rate and retention across hundreds of users, not identifying people by name.

And don’t forget we already had a module about audit & lifecycle: if a user asks to delete their data, your retention logic should respect that. That’s more for module 15; here, remember that analytics isn’t a carte blanche to collect any garbage.

11. Connection with cost instrumentation and SLO: marketing that counts everything

Technically, the ideal picture looks like this: you have a unified stream of structured events where each user session is matched with:

  • product events ("app_opened", "workflow_completed", "checkout_success");
  • cost data (tokens, cost_estimate, duration_ms per tool);
  • SLO metrics (latency and MCP/tool errors, availability).

Then any marketing and product decisions practically become data-driven automatically. You can ask:

  • “What’s the activation_rate for users from campaign X and what is the average cost of their successful workflow?”
  • “Do error_rate or p95 latency increase as Store traffic ramps up?”
  • “If we cut model cost in the ‘cost ↔ quality’ experiment from the previous lesson, did conversion to "checkout_success" drop and did per-user revenue decrease?”

And none of this requires inventing new systems — you just use the same logs and cost tools you introduced earlier.

In the end, ChatGPT App marketing isn’t about traffic per se; it’s about improving specific product metrics inside your application. Log the key scenario steps ("app_opened", "workflow_completed", "checkout_success"), link them with cost instrumentation and SLO, and formulate marketing activities as hypotheses about which exact link in the funnel you want to improve. If you keep this funnel and the privacy constraints in mind, product and growth decisions almost automatically become more meaningful and sustainable.

12. Common mistakes when working with product metrics and marketing

Mistake #1: marketing for traffic, not for activation.
Teams often celebrate a sharp rise in "app_opened" after some article or tweet and call the experiment a success without looking at activation and conversion. As a result they get lots of “tourists” that raise load and cost but don’t bring money and don’t become real users. The right approach is to always look further down the funnel: how many of the arrivals reach "workflow_completed" and "checkout_success".

Mistake #2: no stable user identifier.
Sometimes an App starts logging events without a stable userId or at least a tenantId. In this mode you can only count something like “number of events per day,” but not retention or cost_per_user. Adding correct user tracking later can be hard, especially if you already have strict privacy constraints. It’s better to design the identification scheme at the authentication stage (module 10) and use it in all events.

Mistake #3: tracking “every sneeze” instead of key events.
The first reaction to event analytics is to start logging absolutely everything: mouse hovers, every input focus, every re-render. In the ChatGPT context this is especially harmful: such events don’t map well to the usage model, create tons of noise, and increase privacy risk. It’s much more useful to limit yourself to a few key scenario events and analyze them well.

Mistake #4: marketing campaigns without attribution.
A common pattern: the team runs a campaign (article, video, partnership) but doesn’t tag incoming traffic and then wonders “did it work or not.” As a result, changes in metrics get blurred. It’s much better to use explicit referral_source or campaign fields in "app_opened" events — even via simple UTM-like parameters — and then compare those cohorts with organic.

Mistake #5: ignoring privacy constraints for the sake of “full analytics.”
Sometimes, in pursuit of detail, teams start writing request text, recipient’s personal data, addresses, and other PII into events. This is dangerous on two fronts: OpenAI/Store policies and real legal risk (GDPR, CCPA, etc.). Proper analytics is built on aggregated scenario features and anonymous identifiers, not on storing the entire conversation “just in case.”

Mistake #6: optimizing only for cost, ignoring quality and growth.
After the cost module it’s easy to go into “extreme savings mode,” trying to reduce tokens at any cost. If this lowers activation rate, retention, and "checkout_success", the savings are a false economy: you’re killing product value. Always keep in mind the triangle “cost ↔ quality ↔ growth”: any changes to prompts, models, and UX should be evaluated through both unit cost and product metrics.

1
Task
ChatGPT Apps, level 19, lesson 2
Locked
Minimal product analytics: /api/analytics + demo page
Minimal product analytics: /api/analytics + demo page
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION