7

I want to collect the unique amount of visitors on my website and store them in a database. Even when someone without an account accesses the website the visitor count goes up. How can I accomplish this?

I know I have to fetch the users IP address or something along those lines but I don't know how to fetch the IP address of a user without an account when the page loads

Currently I have this DB table

Visitors
 - ip
 - date_visited

Route

Route::get('/', function () {
    $ip = Request::ip();
    return view('welcome', compact('ip'));
});
Rainier laan
  • 1,101
  • 5
  • 26
  • 63

4 Answers4

5

Try to use Request::ip() to get the ip;

$ip = Request::ip();

For Laravel 5.4 +:

$ip = $request->ip();
// or
$ip = request()->ip();

And I think you can use middleware and redis to calculate this count, this will reduce the db's pressure.

TsaiKoga
  • 12,914
  • 2
  • 19
  • 28
  • Thank you for your response, however I add this code to my route (See updated post) and turn my webhook on. It always says 127.0.0.1 even though my phone has a different IP. I asked a friend to access the website aswell and it says 127.0.0.1 – Rainier laan Jan 24 '20 at 12:17
  • @Rainierlaan do u test it locally? – TsaiKoga Jan 24 '20 at 12:47
  • I know it has been 3 years but wanted to say that it worked :P – Rainier laan Apr 20 '23 at 08:15
3

One good solution in this case is to create an middleware that tracks all your users. We can put any kind of business logic in the middleware.

<?php

namespace App\Http\Middleware;

use Closure;

class TrackUser
{
    public function handle($request, Closure $next)
    {
        /* You can store your user data with model, db or whatever...
           Here I use a repository that contains all my model queries. */
        $repository = resolve('App\Repositories\TrackUserRepository');

        $repository->addUser([
            'ip'   => request()->ip(),
            'date' => now(),
        ]);

        return $next($request);
    }
}

Then add the middleware to App\Kernel.php:

  • Add it to $middleware if you want it to be an global middleware that runs on every request.
  • Add it to $middlewareGroups if you want it to only run on every web-route.
  • Add it to $routeMiddleware if you want to specify in routes/web.php when the middleware should apply.

You should also consider moving any logic in the middleware inside a "try catch"-statement, it minimized the risk that your user gets halted by any errors caused be the "tracking"-code.

try {
    $repository = resolve('App\Repositories\TrackUserRepository');

    $repository->addUser([
        'ip'   => request()->ip(),
        'date' => now(),
    ]);
} catch (\Exception $e) {
    // Do nothing or maybe log error
}

return $next($request);
Deepak Keynes
  • 2,291
  • 5
  • 27
  • 56
2

It's better to use combination of user_agent and ip to have more accurate results, many user may have the same IP but usually have different user agents:

request()->userAgent();
request()->ip();

Alternatively if you're using web middleware (not api), Laravel starts a session for each client. You can change your session driver and use database instead of default file.

This way Laravel will store a record for each client on sessions table containing all info you need and even more:

Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->unsignedInteger('user_id')->nullable();
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity');
});

As you can see, there is ip_address, user_agent and last_activity. The user_id will be null for guest users and has value for authenticated users.

See Laravel docs to config your session driver to use database.

Hafez Divandari
  • 8,381
  • 4
  • 46
  • 63
  • As a reminder, you can use `$table->ipAddress()` to store IP Address data. [Docs](https://laravel.com/docs/8.x/migrations#column-method-ipAddress). – ibnɘꟻ Nov 29 '21 at 05:51
0

As @tsaiKoga mentioned how you will get ip address.

create a new table for for ip address and their visits timestamp .

check IF IP does not exists OR time()-saved_timestamp > 60*60*24 (for 1 day) ,edit the IP's timestamp to time() (means now) and increase your view one else do nothing!

Moreover, You can get IP by $_SERVER['REMOTE_ADDR']

More ways for getting IP is mentioned here. https://stackoverflow.com/a/54325153/2667307

Reviewed the comment which returns 127.0.0.1

Please try:-

request()->server('SERVER_ADDR');

OR you may use

$_SERVER['SERVER_ADDR'];

OR

$_SERVER['REMOTE_ADDR']

Shashank Shah
  • 2,077
  • 4
  • 22
  • 46