Alert: DIGISTREET does not offer any jobs via WhatsApp. Such messages are fraudulent. Apply only through official channels. Stay mindful. Stay safe.

Finding where users give up before they register

Finding where users give up before they register - DigiStreet Media
App registration drop-off

Finding where users give up before they register

Updated 2 November 2026.

Two class names, MainActivity on Android and FlutterViewController on iOS, were 42% of all screen views in a GA4 property we audited on 6 October 2026. With those as your screen names there is no path through the app and no drop-off to read. Here is what we replaced them with.

Why your screens report says MainActivity

42% of screen views in this property were two values: MainActivity on Android and FlutterViewController on iOS. Everything a user saw was filed under one of them.

That is not a bug. Firebase logs a screen_view automatically on screen transitions and, when screen_class has not been set, fills the value from the Activity or UIViewController in focus. A Flutter app routes every screen through one view controller per platform, so the automatic value is correct and useless at the same time.

The consequence is specific. There was no path through the app, because every step carried the same name, and no per-screen drop-off, because there were no screens. On a product whose whole problem was people leaving before they registered, the screens report could not show one place where they left.

Screen names a person would recognise

Send screen_view yourself, with a screen_name somebody in the business would recognise. Nine names covered this app. The rule we use is to name the screen after what the user is doing, not after the class or the route. signup, otp, consent, profile, test_list, test_detail, test_question, result, checkout. Lower case, underscores, no version numbers in the name.

Log it where the screen actually becomes visible. Firebase’s documentation says to call it in onResume on Android and in viewDidAppear or onAppear on Apple platforms. Log it in the constructor instead and you will count screens nobody ever saw. On an app we build this list goes into the spec, because retrofitting it across 40 screens is a week nobody budgeted.

Screen names we sent manually in place of two class names that were 42% of all screen views in the property, 8 October 2026.
Screen screen_name sent Previously logged as What it lets you see
Sign-up form signup MainActivity or FlutterViewController How many people who opened the app ever reached the form
Code entry otp MainActivity or FlutterViewController The share who asked for a code and never got past it
Consent consent MainActivity or FlutterViewController Whether the consent screen loses people before registration
Profile profile MainActivity or FlutterViewController Whether a long profile form is the real barrier
Test catalogue test_list MainActivity or FlutterViewController Whether registered users ever reach a product
Test detail test_detail MainActivity or FlutterViewController Which assessments get considered and dropped
Test question test_question MainActivity or FlutterViewController Where inside a long test people stop, read with the step parameter
Checkout checkout MainActivity or FlutterViewController Whether payment or the form before it is the problem

The events that tell three failures apart

A funnel that runs from app open to registered tells you 70% leave. It does not tell you which 70%. There are at least three different people inside that number and they need three different fixes.

One, the person who never asked for a code, which is a screen problem: the form looked long, or the reason to register was not on the screen. Two, the person who requested a code and never verified, which is a delivery or a patience problem. Three, the person who verified and then stopped at the profile form or the consent screen, which is a form problem.

The events that separate them are sign_up_start when the form opens, otp_requested and otp_verified either side of the phone check, sign_up when the account exists, and sign_up_error carrying an error_reason of otp_timeout, otp_wrong, network or already_registered. Add step to sign_up_error and you know which field. consent_updated records the consent choice, and it is usually the event that explains a gap nobody can account for.

Building the funnel

Use a funnel exploration, closed, with each step as a single event. Ours ran first_open, sign_up_start, otp_requested, otp_verified, sign_up, profile_complete, test_start, test_complete.

Two settings matter more than the step list. Set it to a closed funnel so people have to pass through the steps in order, because an open funnel will flatter you by counting anyone who reached step four by another route. And check the date range against your retention setting: explorations and funnel reports are the reports GA4’s data retention limit actually affects. This property was set to 2 months. We raised it to 14, the maximum on a standard property.

Then break it down. Platform first, because Android was about 87% of key events against roughly 5% on iOS and the registration experience was not the same on both. Then method, because phone, Google and Apple sign-in fail at different rates and the blended number hides all three.

Sudhir Power: six months of Google Search Console clicks and impressions for the site we work on.
Sudhir Power, six months of clicks and impressions in Google Search Console, from the client’s own Search Console property.
Real client evidence

Sudhir Power

Search evidence, not app data. Sudhir Power is an SEO client and this is six months of clicks and impressions from their Google Search Console property. It is here because it is a measurement with a named source behind it. The app funnel described in this post was built for a client we are not naming.

Read the Sudhir Power case study

Reading it

Read the biggest absolute loss, not the worst percentage. A step that loses 60% of 40 people is a smaller problem than a step that loses 20% of 900, and the second one is usually earlier in the funnel.

Then read the pairs. otp_requested against otp_verified is delivery and patience. otp_verified against sign_up is whatever your app does between verification and account creation, which is usually a form nobody mentioned in the brief. sign_up against profile_complete is the profile form. profile_complete against test_start is whether a registered user can find a product at all.

One number you will want and may not have is how many people who opened the app never reached the sign-up form. That is first_open against sign_up_start. If that gap is the largest one, the problem is on the first screen and not in registration, and no amount of form work will fix it. That is a conversion problem on the first screen, and it is cheaper to solve than a rebuild.

What to fix first

Fix the step with the largest absolute loss that you can change within a release. On most apps that is the OTP screen or the profile form, and both are usually fixable without a design round.

Three changes that keep earning their keep. Cut the profile form down to the fields you need before you can show a result, and move the rest to later. Put a resend timer, a visible error message and a second sign-in method on the OTP screen. And show the first screen of value before asking for an account, where the product allows it.

That last one is a product decision rather than a tracking one. We argue for it anyway, and we would rather argue it with a funnel on the screen than with an opinion. It is the same work as conversion rate optimisation on a website, with a slower release cycle and no ability to patch it tomorrow afternoon.

Checking it on a real device before you trust a report

DebugView, on a physical phone, before anybody opens a report. On Android you turn debug mode on with adb shell setprop debug.firebase.analytics.app followed by your package name, and off again with the same command ending in .none. On Apple platforms you pass -FIRDebugEnabled as a launch argument in Xcode, and -FIRDebugDisabled to switch it off.

Then walk the app like a user and watch the stream. DebugView shows events from the last 60 seconds with their parameters and user properties, a per-minute count across the last 30 minutes, and a device selector so two developers do not end up reading each other’s events.

What you are checking is not whether events fire. It is whether the names and parameters are exactly what the plan said, case included, because Firebase event and parameter names are case sensitive and test_Start is a different event from test_start. Realtime next, then the Events report 24 to 48 hours later, then the funnel.

The weekly habit that keeps it honest

Open the funnel once a week with the product team in the room. Not monthly. An app release cycle is slower than a website’s, so a regression that shipped on the 3rd is much cheaper to catch on the 10th than on the 1st of next month.

Watch for three things. A parameter showing (not set) where it used to arrive. A step losing more people than last week with no release in between. And a screen name nobody recognises, which is how you find out a new screen shipped without a screen_view at all.

Put one name against it. On our side a single person owns the funnel and reads it before the weekly call, which is how the question in the call becomes what changed rather than what does this mean. Same arrangement on every app we maintain, from the first release onwards.

Frequently asked questions

1

Why does GA4 show MainActivity as my screen name?

Because screen_class has not been set, so Firebase fills it from the Activity or UIViewController in focus. In a Flutter app that is one class for every screen, which is why MainActivity and FlutterViewController were 42% of all screen views in the property in this post.

2

Should I turn off automatic screen tracking?

Usually no. Send manual screen_view events with proper screen names alongside it, and only disable the automatic version if you are getting duplicates. It is switched off with FirebaseAutomaticScreenReportingEnabled set to NO in Info.plist on iOS, or a google_analytics_automatic_screen_reporting_enabled meta-data entry in the Android manifest.

3

Which events do I need to find registration drop-off?

Six: sign_up_start, otp_requested, otp_verified, sign_up, sign_up_error with an error_reason, and consent_updated. Add a step parameter to sign_up_error and you can tell a long form apart from a failed code.

4

Should a GA4 funnel exploration be open or closed?

Closed, for a registration funnel. A closed funnel requires people to pass through the steps in order, while an open funnel counts anyone who reached a later step by another route and makes the drop-off look smaller than it is.

5

How far back can a funnel exploration look?

As far as your event data retention setting allows, which is 2 or 14 months on a standard property. Retention affects explorations and funnel reports rather than standard aggregated reports, so set it to 14 months today because the change does not apply backwards.

6

How long does this take to implement?

About a week of developer time for the screen names and the registration events on an app of this size, then 24 to 48 hours before the Events report is readable. Check it in DebugView on a real device the same day rather than waiting for the report.

Show us your funnel and we will tell you which step to fix first.

Get a quote

Kavish Arora

Written by

Kavish Arora

Kavish Arora is Co-Founder of DigiStreet Media, a digital marketing agency based in Noida working with over 250 brands across industrial, automotive, education, finance and consumer categories. He has spent 15+ years building brands, performance and SEO programmes for Indian and international clients, and co-founded DigiStreet Media, now in its 14th year. Read more about Kavish Arora .

Let's Build Something

Have a project like this in mind?

Tell Digistreet Media what you're trying to build and we'll tell you exactly how to get there.

Get In Touch →
Related posts

Awarded Digital Marketing Agency
4.8 from 250+ 5 star rating reviews

Let’s Imagine, Believe, Create Together

    Select Services*

      Select Services*