tpitale/legato

Wrong escape when using gte condition on dimensions

Closed this issue · 9 comments

fabn commented

Some dimensions allow numeric filters (e.g. sessionCount), however if you use it as in

filter(:loyal_users) { gte(:session_count, 10) }

produced query string is invalid because < and > are escaped and it should not happen. Here's the raised exception:

OAuth2::Error: {"errors"=>[{"domain"=>"global", "reason"=>"invalidParameter", "message"=>"Invalid value 'ga:sessionCount>=10' for filters parameter."}], "code"=>400, "message"=>"Invalid value 'ga:sessionCount>=10' for filters parameter."}:
{"error":{"errors":[{"domain":"global","reason":"invalidParameter","message":"Invalid value 'ga:sessionCount\u003e=10' for filters parameter."}],"code":400,"message":"Invalid value 'ga:sessionCount\u003e=10' for filters parameter."}}
from ../gems/oauth2-1.3.0/lib/oauth2/client.rb:119:in `request'

If you use the equality operator everything works.

Is there any quick fix to avoid this issue?

No quick fix. Looking now.

OAuth2 does not escape the query params in Legato. https://github.com/tpitale/legato/blob/master/lib/legato/request.rb#L25

sessionCount does not appear to be a dimension or metric I can find. Did you mean to match on sessions?
https://developers.google.com/analytics/devguides/reporting/core/dimsmets#view=detail&group=session&jump=ga_sessions

fabn commented

sessionCount is this https://developers.google.com/analytics/devguides/reporting/core/dimsmets#view=detail&group=user&jump=ga_sessioncount

and I'm able to query it with eql filter, e.g.

filter(:loyal_users) { eql(:session_count, 10) }
fabn commented

Ok, I've debugged this and it may not be an issue with legato gem itself. With equal condition is working because :matches => '==' and can be applied to dimensions, maybe >= is not a valid operator for dimensions.

However I'm able to query for sessionCount >= 10 through analytics interface so it should be a way to do that also with API.

Keep investigating.

Sorry. That is API V4. Legato only currently supports up to Core Reporting API V3.

I'm going to start a branch soon for V4 support. But they changed A LOT of the API.

fabn commented

Thanks for your answer, but meanwhile I found out that is supported also in V3. You only have to use a dynamic segment, in this way it works:

  segment :loyal_users do
    gte(:session_count, 10)
  end

Here's the produced params for the query I need:

data.to_params
{
              "ids" => "ga:xxxx",
       "start-date" => "2017-08-22",
         "end-date" => "2017-08-29",
          "segment" => "sessions::condition::ga:sessionCount>=10",
          "filters" => "ga:pageviews>=10",
           "fields" => "columnHeaders/name,rows,totalResults,totalsForAllResults",
        "quotaUser" => "YYYYYYY",
    "samplingLevel" => "HIGHER_PRECISION",
          "metrics" => "ga:pageviews,ga:newUsers,ga:sessions,ga:percentNewSessions",
       "dimensions" => "ga:source",
             "sort" => "-ga:pageViews"
}

So this issue can be closed because it's not an issue anymore ;)

@fabn Any chance you could share that filter with sessionCount.

Also … 🙄 GA API.

fabn commented

@tpitale full class (still work in progress) is this, pretty simple to use

class LoyalUsersVisits
  extend Legato::Model
  # Required metrics
  metrics :pageviews, :new_users, :sessions, :percent_new_sessions
  # dimensions
  dimensions :source
  # Filter by locale as given in dimension 4
  filter :by_locale, &lambda { |locale| matches(:dimension4, locale) }
  # Only count visits from "loyal users"
  segment :loyal_users do
    gte(:session_count, 10)
  end
end

Use it as any other legato class, e.g. LoyalUsersVisits.by_locale('en').loyal_users(profile)