Skip to content

Commit 44281c4

Browse files
authored
Merge pull request #138 from ddxv/add-dau-mau-rev-to-apps
Add dau mau rev to apps
2 parents f238489 + 483fbd0 commit 44281c4

File tree

11 files changed

+357
-113
lines changed

11 files changed

+357
-113
lines changed
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
select * from frontend.company_domain_country;
1+
select
2+
company_domain,
3+
most_common_country,
4+
total_app_count
5+
from frontend.company_domain_country;

backend/dbcon/sql/query_growth_apps.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ SELECT
1111
installs_sum_1w,
1212
ratings_sum_1w,
1313
installs_avg_2w,
14+
installs_acceleration,
15+
has_reliable_baseline,
16+
monthly_active_users,
17+
monthly_iap_revenue,
18+
monthly_ad_revenue,
1419
installs_z_score_2w,
1520
installs_sum_4w,
1621
installs_avg_4w,

backend/dbcon/sql/query_single_app.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ SELECT
77
rating,
88
rating_count,
99
installs,
10+
weekly_active_users,
11+
monthly_active_users,
12+
monthly_ad_revenue,
13+
monthly_iap_revenue,
1014
installs_sum_1w,
1115
installs_sum_4w,
1216
ratings_sum_1w,

frontend/src/lib/AppOverviewSummary.svelte

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import type { AppFullDetail } from '../types';
3-
import { formatNumber } from '$lib/utils/formatNumber';
3+
import { formatNumber, getRevenueBucket } from '$lib/utils/formatNumber';
44
55
interface Props {
66
app: AppFullDetail;
@@ -83,6 +83,31 @@
8383
const weeklyInstalls = $derived(app.installs_sum_1w ? formatNumber(app.installs_sum_1w) : null);
8484
const weeklyRatings = $derived(app.ratings_sum_1w ? formatNumber(app.ratings_sum_1w) : null);
8585
const monthlyInstalls = $derived(app.installs_sum_4w ? formatNumber(app.installs_sum_4w) : null);
86+
const monthlyActiveUsers = $derived(
87+
app.monthly_active_users && app.monthly_active_users > 0
88+
? formatNumber(app.monthly_active_users)
89+
: null
90+
);
91+
const monthlyAdRevenue = $derived(Number(app.monthly_ad_revenue) || 0);
92+
const monthlyIapRevenue = $derived(Number(app.monthly_iap_revenue) || 0);
93+
const monthlyRevenueTotal = $derived(monthlyAdRevenue + monthlyIapRevenue);
94+
const monthlyRevenueBucket = $derived(
95+
monthlyRevenueTotal > 0 ? getRevenueBucket(monthlyRevenueTotal) : null
96+
);
97+
const monthlyAdRevenueShare = $derived(
98+
monthlyRevenueTotal > 0 ? Math.round((monthlyAdRevenue / monthlyRevenueTotal) * 100) : 0
99+
);
100+
const monthlyIapRevenueShare = $derived(
101+
monthlyRevenueTotal > 0 ? 100 - monthlyAdRevenueShare : 0
102+
);
103+
const releaseMonthYear = $derived(
104+
app.release_date
105+
? new Date(app.release_date).toLocaleDateString('en-US', {
106+
month: 'short',
107+
year: 'numeric'
108+
})
109+
: null
110+
);
86111
87112
// Format date helper
88113
const formatDate = (dateStr: string | undefined | null): string | null => {
@@ -100,7 +125,8 @@
100125
101126
// Ad and API tracking info
102127
const adCreativeCount = $derived(app.ad_creative_count ?? 0);
103-
const hasAdMonetization = $derived((app?.ad_monetized_creative_count ?? 0) > 0);
128+
const adMonetizedCreativeCount = $derived(app.ad_monetized_creative_count ?? 0);
129+
const hasAdMonetization = $derived(adMonetizedCreativeCount > 0);
104130
const apiLastCrawled = $derived(formatDate(app.api_last_crawled));
105131
const sdkLastCrawled = $derived(formatDate(app.sdk_last_crawled));
106132
@@ -113,25 +139,43 @@
113139
<h2 class="text-lg font-bold">{app.name} Summary</h2>
114140
<p>
115141
<strong>{app.name}</strong> is a
116-
{#if monetization}{monetization}{/if}
142+
{#if monetization}{monetization}{:else}mobile{/if}
117143
{platformName} app
118-
{#if categoryName}in the <span class="font-medium">{categoryName}</span> category{/if}{#if app.developer_name},
119-
developed by <span class="font-medium">{app.developer_name}</span>{/if}.
120-
{#if appAge}
121-
First released {appAge} ago{#if app.release_date}
122-
({new Date(app.release_date).toLocaleDateString('en-US', {
123-
month: 'short',
124-
year: 'numeric'
125-
})}){/if},{/if}
144+
{#if categoryName}in <span class="font-medium">{categoryName}</span>{/if}
145+
{#if app.developer_name}
146+
by <span class="font-medium">{app.developer_name}</span>{/if}.
147+
{#if releaseMonthYear}
148+
Released in <span class="font-semibold">{releaseMonthYear}</span>
149+
{#if appAge}({appAge} ago){/if}.
150+
{/if}
126151
{#if installsFormatted && isAndroid}
127-
the app has accumulated <span class="font-semibold">{installsFormatted}+</span> total installs
152+
It has about <span class="font-semibold">{installsFormatted}+</span> installs
128153
{/if}
129154
{#if ratingsFormatted}
130-
{#if installsFormatted && isAndroid}and{:else}the app has{/if}
155+
{#if installsFormatted && isAndroid}and{:else}It has{/if}
131156
<span class="font-semibold">{ratingsFormatted}</span> ratings
132157
{#if app.rating}
133158
with a <span class="font-semibold">{Number(app.rating).toFixed(2)}★</span> ({ratingQuality})
134-
average rating{/if}.
159+
average
160+
{/if}.
161+
{/if}
162+
{#if monthlyActiveUsers || monthlyRevenueBucket}
163+
Based on AppGoblin estimates,
164+
{#if monthlyActiveUsers}
165+
it reaches roughly <span class="font-semibold">{monthlyActiveUsers}</span> monthly active users
166+
{/if}
167+
{#if monthlyActiveUsers && monthlyRevenueBucket}and{/if}
168+
{#if monthlyRevenueBucket}
169+
generates around <span class="font-semibold">{monthlyRevenueBucket}</span> monthly revenue ({monthlyIapRevenueShare}%
170+
IAP / {monthlyAdRevenueShare}% ads)
171+
{/if}.
172+
{/if}
173+
{#if app.store_last_updated || app.version_code || app.content_rating}
174+
Store metadata{#if app.store_last_updated}: updated <span class="font-semibold"
175+
>{formatDate(app.store_last_updated)}</span
176+
>{/if}{#if app.version_code}, version <span class="font-semibold">{app.version_code}</span
177+
>{/if}{#if app.content_rating}, rated <span class="font-semibold">{app.content_rating}</span
178+
>{/if}.
135179
{/if}
136180
</p>
137181

@@ -157,14 +201,17 @@
157201
<p>
158202
<span class="font-medium text-primary-800-200">Advertising:</span>
159203
{#if adCreativeCount > 0}
160-
We've tracked <a href="{appBasePath}/ad-creatives" class="font-semibold"
204+
AppGoblin has tracked <a href="{appBasePath}/ad-creatives" class="font-semibold"
161205
>{formatNumber(adCreativeCount)} ad creatives</a
162-
> where this app is running paid user acquisition campaigns.
206+
> this app uses for paid user acquisition across ad networks.
163207
{/if}
164-
{#if hasAdMonetization}
165-
{#if adCreativeCount > 0}Additionally, the{:else}The{/if} app has been identified as showing
166-
<a href="{appBasePath}/monetized-ads">monetized advertisements</a> based on detected ad network
167-
creatives.
208+
{#if adMonetizedCreativeCount > 0}
209+
{#if adCreativeCount > 0}AppGoblin also{/if}
210+
{#if adCreativeCount === 0}AppGoblin{/if} detected
211+
<a href="{appBasePath}/monetized-ads" class="font-semibold"
212+
>{formatNumber(adMonetizedCreativeCount)} monetized ad creatives</a
213+
>
214+
shown inside the app.
168215
{/if}
169216
</p>
170217
{/if}

frontend/src/lib/AppSDKOverview.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</script>
1717

1818
{#if typeof myPackageInfo == 'string'}
19-
<p>Permissions, SDKs and trackers info not yet available for this app.</p>
19+
<p>Permissions, SDKs and trackers info not yet available for {myapp.name}.</p>
2020
{:else if myPackageInfo.company_categories && myapp.sdk_successful_last_crawled}
2121
<div class="">
2222
<p class="p-2 md:p-4">
@@ -41,6 +41,7 @@
4141
<WhiteCard>
4242
{#snippet title()}
4343
<span class="text-sm font-semibold">
44+
AppGoblin saw {myapp.name} uses
4445
{myPackageInfo.company_categories[category].length}
4546
{companyTypes.types.find((x: { url_slug: string }) => x.url_slug === category)
4647
?.name || category}

frontend/src/lib/FastestGrowingAppsTable.svelte

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import Check from 'lucide-svelte/icons/check';
2222
import X from 'lucide-svelte/icons/x';
2323
24-
import { formatNumber } from '$lib/utils/formatNumber';
24+
import { formatNumber, getRevenueBucket } from '$lib/utils/formatNumber';
2525
import ZScoreMeter from '$lib/components/ZScoreMeter.svelte';
2626
2727
type DataTableProps<CompaniesOverviewEntries, TValue> = {
@@ -91,6 +91,21 @@
9191
accessorKey: 'installs_z_score_4w',
9292
isSortable: true
9393
},
94+
{
95+
title: 'Monthly Active Users',
96+
accessorKey: 'monthly_active_users',
97+
isSortable: true
98+
},
99+
{
100+
title: 'Monthly IAP Revenue',
101+
accessorKey: 'monthly_iap_revenue',
102+
isSortable: true
103+
},
104+
{
105+
title: 'Monthly Ad Revenue',
106+
accessorKey: 'monthly_ad_revenue',
107+
isSortable: true
108+
},
94109
// Monetization indicators
95110
{
96111
title: 'IAP',
@@ -303,18 +318,21 @@
303318
<a
304319
href="/apps/{row.original.store_id}"
305320
style="cursor: pointer;"
306-
class="text-xs md:text-sm font-medium text-blue-600 hover:text-blue-800"
321+
class="block max-w-[170px] md:max-w-[260px] text-xs md:text-sm font-medium text-blue-600 hover:text-blue-800"
307322
>
308323
<div class="flex items-center gap-2">
309324
<img
310325
src={row.original.app_icon_url}
311326
alt={row.original.app_name}
312327
class="w-8 h-8 shrink-0 rounded"
313328
/>
314-
<div class="flex flex-col min-w-0">
315-
<span class="text-xs md:text-sm truncate">{row.original.app_name}</span>
316-
<span class="text-[10px] md:text-xs text-surface-500 truncate"
317-
>{row.original.developer_name}</span
329+
<div class="flex flex-col min-w-0 max-w-[120px] md:max-w-[210px]">
330+
<span class="text-xs md:text-sm truncate" title={row.original.app_name}
331+
>{row.original.app_name}</span
332+
>
333+
<span
334+
class="text-[10px] md:text-xs text-surface-500 truncate"
335+
title={row.original.developer_name}>{row.original.developer_name}</span
318336
>
319337
</div>
320338
</div>
@@ -327,14 +345,22 @@
327345
size="sm"
328346
showValue={false}
329347
/>
330-
{:else if ['installs', 'rating_count', 'installs_sum_1w', 'ratings_sum_1w', 'installs_avg_2w', 'installs_sum_4w'].includes(cell.column.id)}
348+
{:else if ['installs', 'rating_count', 'installs_sum_1w', 'ratings_sum_1w', 'installs_avg_2w', 'installs_sum_4w', 'monthly_active_users'].includes(cell.column.id)}
331349
<p class="text-xs md:text-sm">
332350
{#if (cell.getValue() ?? 0) === 0}
333351
-
334352
{:else}
335353
{formatNumber(cell.getValue() as number)}
336354
{/if}
337355
</p>
356+
{:else if ['monthly_iap_revenue', 'monthly_ad_revenue'].includes(cell.column.id)}
357+
<p class="text-xs md:text-sm">
358+
{#if Number(cell.getValue() ?? 0) <= 0}
359+
-
360+
{:else}
361+
{getRevenueBucket(Number(cell.getValue()))}
362+
{/if}
363+
</p>
338364
{:else if ['in_app_purchases', 'ad_supported'].includes(cell.column.id)}
339365
<div class="flex justify-center">
340366
{#if cell.getValue()}

0 commit comments

Comments
 (0)