Analytics Real Time Active Users on Particular Page - google-analytics

I want to get the count of active users based on separate pages. What I'm getting is the count of Active Users on whole website.
I am using this code,
$metrics = 'ga:screenviews';
$optParams = array('dimensions' => 'ga:screenName');
try {
$results = $service->data_realtime->get(
$GA_VIEW_ID,
'rt:activeUsers',
$optParams);
} catch (apiServiceException $e) {
// Handle API service exceptions.
$error = $e->getMessage();
}
Is there any extra parameters to be added for getting for a particular page.

Yes, you need to apply filters to your query. Also please note, that dimensions and metrics differ from general reporting API, and start with rt:, in metrics, dimensions, and filters as well. Extending your code would look something like this:
$metrics = 'rt:screenViews';
$optParams = array('dimensions' => 'rt:screenName',
'filters' => 'rt:screenName==somescreen);
try {
$results = $service->data_realtime->get(
$GA_VIEW_ID,
'rt:activeUsers',
$optParams);
} catch (apiServiceException $e) {
// Handle API service exceptions.
$error = $e->getMessage();
}
Although not the latest version, but the syntax of filter operators is explained here.
Please find the full list of real time metrics and dimensions here.

Related

Not the required data is displayed for the new user, because the data is taken from the cache of the previous user

I made a custom module that displays the weather in a particular city.
But I got these comments after the code review:
1. Interesting question, what happens to your cache data, if the site first comes to a person from the city of London, and then Paris?
As I understand it, it means that a person from Paris, when he enters the site, will see the weather in London, because it will be taken from the cache. But I put the data in the cache so that there are not too many requests, I made a request once, put the data in the cache, and the next time I took the data from the cache.
2. In the small function, you are calling the http://ip-api.com/json/ endpoint twice. What happens when the site is visited by a thousand people per minute?
Here, I do not understand what the problem is. If it meant that the connection limit to the resource would be exhausted, then how to solve this problem? In the getCity() function, put the data in the cache in the same way as I do in the build() function? But then the same problem comes up as in the first remark, if a person from another city visits the site, then the data from the cache (name of the city of London) will be taken and not the name of his real city. How then to be?
Can you please tell me what needs to be changed in my code?
Below I will write a slightly reduced code for my php file. Full version here: https://phpsandbox.io/n/sweet-forest-1lew-1wmof
// ....
use Drupal\Core\Cache\CacheBackendInterface;
use GuzzleHttp\Client;
//....
public function getCity() {
$ip = '193.62.157.66'; // static because for testing
try {
$response_ip = $this->httpClient->get('http://ip-api.com/json/' . $ip);
$response_data_ip = $response_ip->getBody();
$data_ip = json_decode($response_data_ip);
if ($data_ip->status == 'success') {
return $data_ip->city;
}
else {
return $this->configFactory->get('sydneypro_weather.settings')->get('weather_city');
}
}
catch (RequestException $e) {
return FALSE;
}
}
public function build() {
$client = $this->httpClient;
$api_key = $this->configFactory->get('sydneypro_weather.settings')->get('weather_api_key');
$cid = 'sydneypro_weather';
$weather_config = $this->configFactory->get('sydneypro_weather.settings');
if (!$weather_config) {
$this->logger->get('sydneypro_weather')->error('Config "sydneypro_weather.settings" is missing4');
return [];
}
if (empty($api_key) || empty($this->getCity())) {
return [
'#type' => 'markup',
'#markup' => $this->t('Please enter your API key and City in the Admin panel to see the weather'),
];
}
try {
if ($cache = $this->cacheBackend->get($cid)) {
$data = $cache->data;
}
else {
$response = $client->get('http://api.openweathermap.org/data/2.5/weather?q=' . $this->getCity() . ',&appid=' . $api_key . '&units=metric');
$response_data = $response->getBody();
$data = json_decode($response_data);
$this->cacheBackend->set($cid, $data, $this->time->getRequestTime() + 21600);
}
$build = [
'#theme' => 'weather_block',
'#data' => $data,
'#attached' => [
'library' => [
'sydneypro_weather/sydneypro_weather',
],
],
];
return $build;
}
// ....
You need to display some data according to a given city, so you should cache the data on a per-city basis, using a cache id that allows you to retrieve data for a specific city. In other words, $cid must contain a city name or identifier.
$city = $this->getCity();
$cid = 'sydneypro_weather:' . $city;
Using a variable for $city prevents getCity() to be called twice. Also you could set a cache that maps IP adresses to their corresponding city but it might not be a good idea as the number of (possible) distinct adresses populating the cache table could be very high.
Another approach would be to get the region/city of the user from his browser using javascript and/or cookies, and call the api only for those that does not share their location.

Doctrine update entity in loop, persist or flush?

I have multiple loops like :
$bets = $this->em->getRepository('AppBundle:Bet')->getBetsForMatch($match_id);
foreach ($bets as $key => $bet) {
$devices = $this->em->getRepository('AppBundle:Device')->findBy(array('user' => $bets->getUser()));
foreach ($devices as $key => $device) {
//HERE I SEND A PUSH NOTIFICATION
if($this->rms_push->send($message)){
$device->getUser()->setBadge($device->getUser()->getBadge() + 1);
$this->em->flush();
}
}
}
So, I get all bets for a match, for each bet I get all devices saved for the user, and after that I need to update my user with : $device->getUser()->setBadge($device->getUser()->getBadge() + 1);
For now, I flush each time but I think there is a better way, ideas ?
You need only one flush, out of your loop:
foreach ($bets as $key => $bet) {
$devices = $this->em->getRepository('AppBundle:Device')->findBy(array('user' => $bets->getUser()));
foreach ($devices as $key => $device) {
//HERE I SEND A PUSH NOTIFICATION
if($this->rms_push->send($message)){
$device->getUser()->setBadge($device->getUser()->getBadge() + 1);
}
}
}
$this->em->flush();
Calling $this->_em->persist($obj) involves to create a new entry.
If you need to create or update depending on the entry exists or not, look at EntityManager::merge .
To preserve memory usage for large number of entries, look at batch processing.
Note SensioLabs insight (PHP source code quality analysis) raises a warning if your code calls EntityManager::flush inside a loop.

How to get totalhits from Query

I want to get the total results for a query using elastica for symfony2
what I did :
$u = $this->container->get('fos_elastica.finder.documents_index.documents');
$maxItems=10;
$query = new \Elastica\Query\Bool();
$elasticaQuery = new \Elastica\Query\QueryString($key_words.'~');
$elasticaQuery->setFuzzyPrefixLength(3);
$query->addMust($elasticaQuery);
try {
$q = new \Elastica\Query();
$q->setQuery($query);
$q->setFrom(($page - 1) * $maxItems);
}
catch (Exception $e) {
}
$data = $u->find($q);
$data is always 10 documents but this is not the problem , the problem is how to get the total hits so I can use them in Pagination :)
The Elastica\ResultSet class has a method called getTotalHits() so you can do something like this after the search and get the full record count for totals/pagination/etc:
$hits = $resultSet->getTotalHits();
See source code here: Elastica ResultSet Class.
As an aside, the Elastica source code is incredibly well-structured and easy to read which more than makes up for it's lack of documentation. Well worth reading both the source and the unit tests if you get stuck.

Best practice for storing simple variables like 'total rows' in Symfony2

In my symfony2 application I need to display some totals at the top of all pages, ie "Already 200,154,555 users registered".
I don't want to run the query to come up with that count on every page load. The solution I've come up with is to create a "variable" entity that would have two columns, name and value. Then I would set up a console command that runs on cron which would update these variable entities (eg "totalPeople") with a query that counted all the rows of people, etc.
This feels a little heavy handed... Is there a better solution to this problem?
You could set global parameters and add a service to rewrite them. Then call the service from your Command.
Or directly set up a service to read/write a file (as a json array for example).
Or set up a option table with a row storing the data. It's not going to be a resource intensive query that way.
Here is what I'm using to store RSS feeds (after I parsed them)
public function checkCache($data=array(), $path = '')
{
foreach ($data as $service => $feed)
{
$service = strtolower($service);
$service = str_replace(' ', '-', $service);
$path = $path.'web/bundles/citation/cache/rss/' . $service . '.cache';
if ((!file_exists($path) || time() - filemtime($path) > 900) && $cache = fopen($path, 'w'))
{
$rss_contents = $this->getFeed($feed); //fetch feed content & returns array
fwrite($cache, serialize($rss_contents));
fclose($cache);
return $rss_contents;
}
else
{
$cache = fopen($path, 'r');
return unserialize(file_get_contents($path));
fclose($cache);
}
}
}
You can implement that on your backend for example so every time an admin logs it'll check for cache and refresh only if it's too old. Although I'm quite fond of the 4AM cron job solution too.
You could use the pagination feature of doctrine (if you use doctrine). That will leverage the "limit" part of your queries (even with joins) and will give you a total count of rows (via a count query).

Is there an API function to check whether a specific user is logged in?

Is there a Drupal API function that accepts a user ID and returns whether that user is currently logged in?
i.e. Is there a function like user_is_logged_in($some_uid)?
Here's a function I borrowed/modified from the advanced forum module to check if a specific user is online. It checks the sessions table for users within a certain time interval. Add it to a custom module and call as needed:
function MODULENAME_check_user_online($uid) {
$interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900);
$query = db_select("users", "u")->distinct()->fields("u", array("uid", "name"));
$s_alias = $query->join("sessions", "s", "u.uid = s.uid");
$query->addExpression("MAX({$s_alias}.timestamp)", "maxtime");
$query
->condition("{$s_alias}.timestamp", $interval, ">=")
->condition("{$s_alias}.uid", $uid, "=")
->groupBy("u.uid, u.name")
->orderBy("maxtime", "DESC");
$check_user_logged_in = $query->execute();
if ($account = $check_user_logged_in->fetchObject()) {
return TRUE;
}
return FALSE;
}
No there isn't, if you want one you will have to write it yourself. Take a look at the sessions table in the database.
Check the user module API here:
http://api.drupal.org/api/drupal/modules--user--user.module/6
more specifically
http://api.drupal.org/api/drupal/modules--user--user.module/function/user_is_logged_in/6

Resources