Tuesday, April 7, 2015

Detecting mobile app CPI frauds

Most CPI campaign work quite nicely. However, I saw this video which claim major click-frauds on Facebook ads from click-farms in specific countries. I've decided to re-check my last CPI campaign.

How I checked: by country, check the average session duration during the campaign. Filter only countries with average session duration less than 50% of the average.

Finding: At least 2 of the top 10 countries in the campaign clearly had a CPI fraud. The average session duration was less than 50% of the average, the CTR was x2-x4. Next time I'll look for it in real time. I've compared it with the data after the campaign & the session duration went back to normal.

Waste of money.

Bottom line: How I will search for ad frauds, at country level:
  1. Significantly low (or high) session duration
  2. Significantly high ad CTR rate

Sunday, January 11, 2015

Calculating Google Analytics event value variance & standard deviation

Here's I calculated the var & stddev of an event value (X) tracked by Google Analytics:
  1. Add a second event with the value X^2
  2. Calculate the variance using this formula: Var = E(X^2) - [E(X)]^2  (note that Google Analytics already calculates E(X^2) & E(X), which are, in this case the event's average).

Friday, November 28, 2014

Can Google Play Services introduce bugs to my apps without code update?

Here's a short list of FC bugs I think Google Play Services introduced remotely to my apps:

Wednesday, September 3, 2014

Removing app from Amazon App Store

Few years ago I had few apps published on Amazon App Store. Since the performance on that market wasn't impressive I didn't update them over time. Few weeks ago I decided to unpublish those apps.

Problem: No way to unpublish apps from the Amazon App Store.
Solution 1: Contact Amazon support and ask them to remove the app. They might want reasons and such.
Solution 2: Limit app distribution to the smallest market you can find on their list.

Monday, April 7, 2014

Upgrading Google Analytics for Android v2 to v4

I couldn't find a single place where all this information can be found, so here are the steps to upgrade Google Analytics for Android v2 to v4 (Google Play Services). This does not include the steps needed to integrate Google Play Services (some Manifest.xml & library includes):

  1. Move the analytics.xml from /res/values to /res/xml
  2. Add the following line to the Manifest.xml:
    <meta-data android:name="com.google.android.gms.analytics.globalConfigResource" android:resource="@xml/analytics" />
    
  3. Replace the campaign tracker in the Manifest.xml if need:
    <service android:name="com.google.android.gms.analytics.CampaignTrackingService" />
    <receiver android:name="com.google.android.gms.analytics.CampaignTrackingReceiver"
              android:exported="true">
       <intent-filter>
      <action android:name="com.android.vending.INSTALL_REFERRER" />
      </intent-filter>
    </receiver>
    
  4. Add the following code to the Application class:
  5. private Tracker mTracker = null;
    
    synchronized public Tracker getTracker() {
      if (mTracker == null) {
        GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
        mTracker = analytics.newTracker(R.xml.analytics);
      }
      
      return mTracker;
    }
    
  6. Activity tracking - replace:
    @Override
    public void onStart() {
      super.onStart();
      
      EasyTracker.getInstance().activityStart(this);
      mTracker = EasyTracker.getTracker();
    }
    
    @Override
    public void onStop() {
      super.onStop();
      
      EasyTracker.getInstance().activityStop(this);
    }
    
    
    with:
    @Override
    public void onStart() {
      super.onStart();
      
      mTracker = ((MyApplication)getApplication()).getTracker();
      GoogleAnalytics.getInstance(this).reportActivityStart(this);
    }
     
    @Override
    public void onStop() {
      super.onStop();
      
      GoogleAnalytics.getInstance(this).reportActivityStop(this);
    }
    
  7. Update events tracking to the new format:
  8. mTracker.send(new HitBuilders.EventBuilder()
      .setCategory(category)
      .setAction(action)
      .setLabel(label)
      .setValue(val)
      .build());
    

Sunday, December 29, 2013

java.lang.IllegalArgumentException: Can't pass bindargs for this sql :insert into....

I've optimized one of my Android apps to use compiled statement (SQLiteStatement) instead of direct SQL to improve performance.

After doing so, I started to get some unhandled exception reports, which had the following in common: Android 4.0.3, Turkish locale and the following stack trace:
java.lang.IllegalArgumentException: Can't pass bindargs for this sql :insert into android.database.sqlite.SQLiteProgram.compileAndbindAllArgs(SQLiteProgram.java)
android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java)
android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java)
android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java)
 
Solution: When using SQLiteStatement write SQL in uppercase letters.

Reason: After searching for some time I found this issue. The SQLiteStatement checks the type of the SQL inside. The checking process is simple string compare of the SQL prefix (INSERT/UPDATE/SELECT/etc..). The string compare in Android 4.0.3 seem to be culture dependent, and in Turkish locale uppercase 'insert' translate to 'İNSERT' (note the dot above the Turkish I') which gives an error in SQL.

Wednesday, December 4, 2013

Notes on using Google Play Game Services

Here are few tips & tricks that helped me [on going post]: