{"id":1773,"date":"2026-07-17T13:00:00","date_gmt":"2026-07-17T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1773"},"modified":"2026-03-07T03:37:19","modified_gmt":"2026-03-07T08:37:19","slug":"cohort-analysis-deep-links","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/cohort-analysis-deep-links\/","title":{"rendered":"Cohort Analysis for Deep Links: Tracking User Groups"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Aggregate metrics hide important trends. &quot;10,000 deep link clicks this month&quot; tells you nothing about whether the users who clicked are retaining, converting, or churning. Cohort analysis solves this by grouping users who share a common trait (typically their acquisition date or source) and tracking their behavior over time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide covers cohort analysis for deep link performance. For deep link analytics broadly, see <a href=\"https:\/\/tolinku.com\/blog\/deep-link-analytics-measuring-what-matters\/\">deep link analytics: measuring what matters<\/a>. For conversion funnel analysis, see <a href=\"https:\/\/tolinku.com\/blog\/conversion-funnel-analysis-deep-links\/\">conversion funnel analysis for deep links<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><img decoding=\"async\" src=\"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/screenshot-analytics-1772819420927.png\" alt=\"Tolinku analytics dashboard showing click metrics and conversion funnel\">\n<em>The analytics dashboard with date range selector, filters, charts, and breakdowns.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Is Cohort Analysis<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A cohort is a group of users who share a characteristic. The most common cohort type is an acquisition cohort: all users who installed in the same week or month.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Acquisition Cohort Example<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Users who clicked a deep link and installed in Week 1 of July vs Week 2:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Cohort<\/th>\n<th>Installs<\/th>\n<th>D1 Retention<\/th>\n<th>D7 Retention<\/th>\n<th>D30 Retention<\/th>\n<th>Revenue\/User<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Jul W1<\/td>\n<td>2,400<\/td>\n<td>45%<\/td>\n<td>28%<\/td>\n<td>15%<\/td>\n<td>$3.20<\/td>\n<\/tr>\n<tr>\n<td>Jul W2<\/td>\n<td>2,800<\/td>\n<td>42%<\/td>\n<td>25%<\/td>\n<td>12%<\/td>\n<td>$2.80<\/td>\n<\/tr>\n<tr>\n<td>Jul W3<\/td>\n<td>3,100<\/td>\n<td>48%<\/td>\n<td>32%<\/td>\n<td>18%<\/td>\n<td>$4.10<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Week 3 had the highest quality users despite not having the most installs. Something changed (maybe a new campaign, creative, or targeting) that improved quality.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Source Cohort Example<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Group by the deep link source instead of date:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Source<\/th>\n<th>Users<\/th>\n<th>D7 Retention<\/th>\n<th>D30 Retention<\/th>\n<th>Conversion Rate<\/th>\n<th>Revenue\/User<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Email campaign<\/td>\n<td>1,200<\/td>\n<td>38%<\/td>\n<td>20%<\/td>\n<td>8.5%<\/td>\n<td>$4.50<\/td>\n<\/tr>\n<tr>\n<td>Push notification<\/td>\n<td>3,500<\/td>\n<td>30%<\/td>\n<td>14%<\/td>\n<td>5.2%<\/td>\n<td>$2.80<\/td>\n<\/tr>\n<tr>\n<td>Social share<\/td>\n<td>800<\/td>\n<td>42%<\/td>\n<td>25%<\/td>\n<td>10.1%<\/td>\n<td>$5.20<\/td>\n<\/tr>\n<tr>\n<td>QR code<\/td>\n<td>400<\/td>\n<td>35%<\/td>\n<td>18%<\/td>\n<td>7.0%<\/td>\n<td>$3.60<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Social share users have the highest retention and revenue, even though push notifications drive the most volume.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Retention Cohort Heatmap<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The retention heatmap is the most common cohort visualization. Each row is a cohort (week), each column is a time period after acquisition, and the cell value is the retention rate:<\/p>\n\n\n\n<pre><code>          Week 0   Week 1   Week 2   Week 3   Week 4   Week 5\nJun W1    100%     35%      22%      18%      15%      13%\nJun W2    100%     38%      25%      20%      17%      15%\nJun W3    100%     33%      20%      16%      13%      11%\nJun W4    100%     40%      28%      23%      19%      17%\nJul W1    100%     42%      30%      24%      -        -\nJul W2    100%     36%      24%      -        -        -\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reading this heatmap:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Jun W4 has the best retention curve. Something improved that week.<\/li>\n<li>Jun W3 has the worst retention. Investigate what changed.<\/li>\n<li>Jul W1 and W2 show continued improvement.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Building the Heatmap<\/h3>\n\n\n\n<pre><code class=\"language-sql\">SELECT\n  DATE_TRUNC(&#39;week&#39;, u.install_date) AS cohort_week,\n  FLOOR(EXTRACT(EPOCH FROM (e.event_date - u.install_date)) \/ 86400 \/ 7) AS weeks_since_install,\n  COUNT(DISTINCT u.user_id) AS cohort_size,\n  COUNT(DISTINCT e.user_id) AS active_users,\n  ROUND(COUNT(DISTINCT e.user_id)::DECIMAL \/ COUNT(DISTINCT u.user_id) * 100, 1) AS retention_pct\nFROM users u\nLEFT JOIN events e ON u.user_id = e.user_id\n  AND e.event_type = &#39;app_open&#39;\nWHERE u.install_date &gt;= &#39;2026-06-01&#39;\nGROUP BY cohort_week, weeks_since_install\nORDER BY cohort_week, weeks_since_install;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Deep Link Cohort Dimensions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">By Deep Link Route<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Group by the route the user first entered through:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>First Deep Link Route<\/th>\n<th>Users<\/th>\n<th>D7 Active<\/th>\n<th>Conversion<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td><code>\/products\/{id}<\/code><\/td>\n<td>3,200<\/td>\n<td>32%<\/td>\n<td>6.5%<\/td>\n<\/tr>\n<tr>\n<td><code>\/offers\/{id}<\/code><\/td>\n<td>1,800<\/td>\n<td>28%<\/td>\n<td>12.0%<\/td>\n<\/tr>\n<tr>\n<td><code>\/referral\/{code}<\/code><\/td>\n<td>900<\/td>\n<td>45%<\/td>\n<td>9.0%<\/td>\n<\/tr>\n<tr>\n<td><code>\/<\/code> (home)<\/td>\n<td>5,000<\/td>\n<td>22%<\/td>\n<td>3.0%<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Users who enter through a specific product or offer page have higher conversion than those who land on the home screen. Referral users have the highest retention.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">By Campaign<\/h3>\n\n\n\n<pre><code class=\"language-sql\">SELECT\n  dl.utm_campaign,\n  COUNT(DISTINCT dl.user_id) AS users,\n  ROUND(AVG(CASE WHEN e.d7_active THEN 1 ELSE 0 END) * 100, 1) AS d7_retention,\n  ROUND(AVG(CASE WHEN e.d30_active THEN 1 ELSE 0 END) * 100, 1) AS d30_retention,\n  ROUND(SUM(r.revenue) \/ COUNT(DISTINCT dl.user_id), 2) AS revenue_per_user\nFROM deep_link_clicks dl\nLEFT JOIN user_engagement e ON dl.user_id = e.user_id\nLEFT JOIN revenue r ON dl.user_id = r.user_id\n  AND r.event_date &lt;= dl.click_date + INTERVAL &#39;90 days&#39;\nWHERE dl.click_date &gt;= &#39;2026-06-01&#39;\nGROUP BY dl.utm_campaign\nORDER BY revenue_per_user DESC;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">By Device\/Platform<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Platform<\/th>\n<th>Users<\/th>\n<th>D7 Retention<\/th>\n<th>Conversion<\/th>\n<th>Revenue\/User<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>iOS<\/td>\n<td>4,500<\/td>\n<td>35%<\/td>\n<td>8.0%<\/td>\n<td>$4.80<\/td>\n<\/tr>\n<tr>\n<td>Android<\/td>\n<td>6,200<\/td>\n<td>28%<\/td>\n<td>5.5%<\/td>\n<td>$3.20<\/td>\n<\/tr>\n<tr>\n<td>Web (fallback)<\/td>\n<td>1,800<\/td>\n<td>15%<\/td>\n<td>2.0%<\/td>\n<td>$1.50<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">iOS users from deep links tend to retain and convert at higher rates. Web fallback users (who did not have the app) convert at much lower rates, highlighting the importance of app installation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Revenue Cohort Analysis<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Track cumulative revenue per user cohort over time:<\/p>\n\n\n\n<pre><code>Cumulative Revenue Per User (by install week):\n\n          Month 0   Month 1   Month 2   Month 3   Month 6   Month 12\nJan W1    $0.50     $2.10     $3.40     $4.50     $7.20     $11.00\nFeb W1    $0.60     $2.30     $3.80     $5.00     $8.10     -\nMar W1    $0.45     $1.90     $3.10     $4.20     -         -\nApr W1    $0.70     $2.50     $4.00     -         -         -\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This view shows whether user quality is improving or declining over time. Apr W1 has the highest early revenue, suggesting improving acquisition quality.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing Cohort Analysis<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Data Model<\/h3>\n\n\n\n<pre><code class=\"language-typescript\">interface CohortConfig {\n  dimension: &#39;install_date&#39; | &#39;source&#39; | &#39;campaign&#39; | &#39;route&#39; | &#39;platform&#39;;\n  granularity: &#39;day&#39; | &#39;week&#39; | &#39;month&#39;;\n  metrics: (&#39;retention&#39; | &#39;revenue&#39; | &#39;conversion&#39; | &#39;engagement&#39;)[];\n  dateRange: { start: string; end: string };\n  periods: number; \/\/ How many periods to track (e.g., 12 weeks)\n}\n\nasync function buildCohortReport(config: CohortConfig): Promise&lt;CohortReport&gt; {\n  const cohorts = await getCohorts(config.dimension, config.granularity, config.dateRange);\n\n  for (const cohort of cohorts) {\n    for (let period = 0; period &lt; config.periods; period++) {\n      for (const metric of config.metrics) {\n        cohort.periods[period][metric] = await calculateMetric(\n          cohort.userIds,\n          metric,\n          cohort.startDate,\n          period,\n          config.granularity\n        );\n      }\n    }\n  }\n\n  return { config, cohorts };\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Visualization<\/h3>\n\n\n\n<pre><code class=\"language-typescript\">function renderRetentionHeatmap(report: CohortReport): string[][] {\n  const rows: string[][] = [];\n\n  \/\/ Header row\n  const header = [&#39;Cohort&#39;, ...Array.from({ length: report.config.periods }, (_, i) =&gt;\n    `${report.config.granularity === &#39;week&#39; ? &#39;W&#39; : &#39;M&#39;}${i}`)];\n  rows.push(header);\n\n  \/\/ Data rows\n  for (const cohort of report.cohorts) {\n    const row = [cohort.label];\n    for (let p = 0; p &lt; report.config.periods; p++) {\n      const value = cohort.periods[p]?.retention;\n      row.push(value !== undefined ? `${value.toFixed(1)}%` : &#39;-&#39;);\n    }\n    rows.push(row);\n  }\n\n  return rows;\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Actionable Insights from Cohorts<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Identifying Quality Changes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If D7 retention drops from 35% to 25% between consecutive cohorts, investigate:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Did targeting change?<\/li>\n<li>Was a new creative introduced?<\/li>\n<li>Did onboarding change?<\/li>\n<li>Was there a bug in a new app version?<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Optimizing Channels<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If email deep link cohorts consistently outperform push notification cohorts, shift budget toward email or investigate why push users have lower quality.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Predicting LTV<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Early cohort behavior (D1, D3, D7 retention and revenue) predicts long-term value. Build models that use early cohort data to project D90 and D365 LTV.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tolinku for Cohort Analytics<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/tolinku.com\/features\/analytics\">Tolinku&#39;s analytics<\/a> support cohort analysis through click and conversion tracking by source, campaign, and route. Build cohort charts and funnels in the <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/analytics\/charts-and-funnels\/\">Tolinku dashboard<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For deep link analytics, see <a href=\"https:\/\/tolinku.com\/blog\/deep-link-analytics-measuring-what-matters\/\">deep link analytics: measuring what matters<\/a>. For app growth metrics, see <a href=\"https:\/\/tolinku.com\/blog\/app-growth-metrics\/\">app growth metrics: the 15 KPIs that matter<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Use cohort analysis to understand deep link performance over time. Group users by acquisition date, channel, or campaign for deeper insights.<\/p>\n","protected":false},"author":2,"featured_media":1772,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Cohort Analysis for Deep Links: Tracking User Groups","rank_math_description":"Use cohort analysis to understand deep link performance over time. Group users by acquisition date, channel, or campaign.","rank_math_focus_keyword":"cohort analysis deep links","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-cohort-analysis-deep-links.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-cohort-analysis-deep-links.png","footnotes":""},"categories":[14],"tags":[37,520,538,539,20,69,47,86],"class_list":["post-1773","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-analytics","tag-campaign-measurement","tag-cohort-analysis","tag-data-analysis","tag-deep-linking","tag-mobile-development","tag-retention","tag-user-engagement"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1773","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1773"}],"version-history":[{"count":2,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1773\/revisions"}],"predecessor-version":[{"id":2410,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1773\/revisions\/2410"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1772"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1773"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1773"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}