Using Google Analytics To Track Fragments
Solution 1
Mochini's answer uses Google Analytics V2. Bellow you can see how to do it on V4 and V3:
- V4:
Application:
public class YourApplication extends Application
{
public synchronized Tracker getTracker() {
try {
final GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(this);
return googleAnalytics.newTracker(R.xml.analytics);
}catch(final Exception e){
Log.e(TAG, "Failed to initialize Google Analytics V4");
}
return null;
}
}
res/xml/analytics.xml (you can name it anything, it does not need to be called "analytics")
<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="TypographyDashes">
<!--Replace placeholder ID with your tracking ID-->
<string name="ga_trackingId">UA-XXXXXXXX-X</string>
<!--Enable automatic activity tracking-->
<bool name="ga_autoActivityTracking">true</bool>
<!--Disable automatic exception tracking-->
<bool name="ga_reportUncaughtExceptions">false</bool>
</resources>
build.gradle:
compile 'com.google.android.gms:play-services:7.3.0'
Fragment superclass:
public abstract class TrackedFragment extends Fragment{
@Override
public void onResume() {
super.onResume();
final Tracker tracker = yourApplicationInstance.getTracker();
if(tracker != null){
tracker.setScreenName(getClass().getSimpleName());
tracker.send(new HitBuilders.ScreenViewBuilder().build());
}
}
}
-
V3
import android.os.Bundle; import android.support.v4.app.Fragment; import com.google.analytics.tracking.android.EasyTracker; import com.google.analytics.tracking.android.Fields; import com.google.analytics.tracking.android.MapBuilder; import com.google.analytics.tracking.android.Tracker; public abstract class TrackedFragment extends Fragment{ private Tracker tracker; @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); this.tracker = EasyTracker.getInstance(getActivity()); } @Override public void onResume() { super.onResume(); this.tracker.set(Fields.SCREEN_NAME, getClass().getSimpleName()); this.tracker.send( MapBuilder.createAppView().build() ); } }
Source: https://developers.google.com/analytics/devguides/collection/android/v3/migration
Solution 2
This an example using FragmentActivity
and fragments:
-
Create XML file in value folder (
values/analytics.xml
):<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Replace placeholder ID with your tracking ID --> <string name="ga_trackingId">XX-xxxxxxxx-x</string> <!-- Enable Activity tracking --> <bool name="ga_autoActivityTracking">true</bool> <!-- Enable debug --> <bool name="ga_debug">true</bool> <!-- The screen names that will appear in your reporting --> <string name="com.example.myapp.FragmentActivity">Fragment activity</string> <!-- The inverval of time after all the collected data should be sent to the server, in seconds. --> <integer name="ga_dispatchPeriod">20</integer> </resources>
-
In your
FragmentActivity
class, add this:@Override protected void onStart() { super.onStart(); EasyTracker.getInstance().setContext(this.getBaseContext()); EasyTracker.getInstance().activityStart(this); // Add this method } @Override protected void onStop() { super.onStop(); EasyTracker.getInstance().activityStop(this); // Add this method }
-
Create new class in your package:
TrackedFragment.java
public class TrackedFragment extends Fragment { private Tracker tracker; private String activityId; private String fragmentId; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); EasyTracker.getInstance().setContext(getActivity().getApplicationContext()); this.tracker = EasyTracker.getTracker(); this.fragmentId = getClass().getSimpleName(); this.activityId = getActivity().getClass().getSimpleName(); } @Override public void onResume() { super.onResume(); this.tracker.sendView("/" + this.activityId + "/" + this.fragmentId); } }
-
Finally, your fragment should extend from
TrackedFragment
like:public class NewFragment extends TrackedFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.newfragment, null); } }
Solution 3
Tracking methods section suggests that you just need to call EasyTracker.getInstance().setContext(getActivity());
first, then you can use the tracker in "other classes".
manual screen tracking section suggests that you can track a Fragment
view with myTracker.sendView("Home Screen");
Solution 4
Another approach for V3 (since onResume()
is tied to the Activity and not the Fragment. This works well when the parent/child relationships are well-known.
Parent Fragment sends initial event onStart()
:
public class ParentFragment extends Fragment {
private Tracker mTracker;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTracker = EasyTracker.getInstance(getActivity());
}
@Override
public void onStart() {
super.onStart();
mTracker.set(Fields.SCREEN_NAME, "Parent Fragment");
mTracker.send(MapBuilder.createAppView().build());
}
}
Child Fragment overrides both onStart()
and onStop()
:
public class ChildFragment extends Fragment {
private Tracker mTracker;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTracker = EasyTracker.getInstance(getActivity());
}
@Override
public void onStart() {
super.onStart();
mTracker.set(Fields.SCREEN_NAME, "Child Fragment");
mTracker.send(MapBuilder.createAppView().build());
}
@Override
public void onStop() {
super.onStop();
mTracker.set(Fields.SCREEN_NAME, "Parent Fragment");
mTracker.send(MapBuilder.createAppView().build());
}
}
Solution 5
Tiago's version can't be used in the new goole analytics v4. Instead, use this code from Google's docs
package com.google.android.apps.mobileplayground;
import com.google.android.apps.mobileplayground.AnalyticsSampleApp.TrackerName;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
/**
* Class to exercise Event hits.
*/
public class EventFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.event, container, false);
setupEvent(view, R.id.video1Play, R.string.videoCategory, R.string.videoPlay, R.string.video1);
setupEvent(view, R.id.video1Pause, R.string.videoCategory, R.string.videoPause,
R.string.video1);
setupEvent(view, R.id.video2Play, R.string.videoCategory, R.string.videoPlay, R.string.video2);
setupEvent(view, R.id.video2Pause, R.string.videoCategory, R.string.videoPause,
R.string.video2);
setupEvent(view, R.id.book1View, R.string.bookCategory, R.string.bookView, R.string.book1);
setupEvent(view, R.id.book1Share, R.string.bookCategory, R.string.bookShare, R.string.book1);
final Button dispatchButton = (Button) view.findViewById(R.id.eventDispatch);
dispatchButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Manually start a dispatch (Unnecessary if the tracker has a dispatch interval)
GoogleAnalytics.getInstance(getActivity().getApplicationContext()).dispatchLocalHits();
}
});
return view;
}
private void setupEvent(View v, int buttonId, final int categoryId, final int actionId,
final int labelId) {
final Button pageviewButton = (Button) v.findViewById(buttonId);
pageviewButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Get tracker.
Tracker t = ((AnalyticsSampleApp) getActivity().getApplication()).getTracker(
TrackerName.APP_TRACKER);
// Build and send an Event.
t.send(new HitBuilders.EventBuilder()
.setCategory(getString(categoryId))
.setAction(getString(actionId))
.setLabel(getString(labelId))
.build());
}
});
}
}
Peter Djeneralovic
Updated on June 18, 2020Comments
-
Peter Djeneralovic about 4 years
Just need to know the proper way to implement Google analytics to track when a user is on a fragment in real time this is what is do now
@Override public void onResume() { super.onResume(); Tracker myTracker = parentActivity.getTracker(); myTracker.setCustomMetric(1, (long) 1); myTracker.sendView("Music View"); }
the getTracker class is in my main activity and just returns the instance of tracker in the main activity
Any help would be much appreciated!
-
Taranfx over 10 yearsold API, Tiago's answer uses newer api
-
Kyle Ivey over 10 years
getActivity()
will return null in a fragment'sonCreate()
. Tracker setup should probably be done inonActivityCreated()
-
M.Sameer over 10 yearsWhat about onStop() or onPause() ? Do we need to inform GA that the screen is no longer active or will it know that when another one becomes active ?
-
Eric Woodruff over 10 yearsI think it would know. If you look at other answers below, it shows that they are tracking onStop as going back to the parent screen, which is probably not necessary as that screen has its own tracking.
-
iamreptar about 10 yearsThis code will overcount the number of times the user is on the
Fragment
. I would initialize theTracker
inonActivityCreate
(cred: @KyleIvey). If your Fragment is usingsetRetainInstanceState(true)
, then I would take it a step further and use a global variable to keep you from sending theMapBuilder
after orientation changes, switching apps, etc. -
Sam almost 10 yearsIs there any known way of doing this without using a subclass? e.g. for tracking activities you can use application's ActivityLifecycleCallbacks.
-
Bitcoin Cash - ADA enthusiast over 8 years@Sam You could use a dependency injection framework to inject the Tracker object, but you would have to do that in every Fragment of yours... I don't see a way around it.
-
Nick over 7 yearsThis approach (using onResume) will yield false data if you use fragments within a viewpager; your tracking events will fire on activity load all at once regardless of individual fragment visibility and will never fire again as the user moves back and forth through the fragments. Unfortunately, the suggested workaround of using setUserVisibileHint wont work outside of viewpagers so you'll gerally have to apply a solution on a fragment-by-fragment basis.
-
venkat over 7 yearssimply superb!!!!! this is very good than google android docs... thanks to post this snippet.