skip to Main Content

I wrote this function that allows the user to view the date of the last login (not the current login). Now I would also like to show the location and device with which the login was made. I tried to search but could not find any solution to my problem. Can anyone shed some light on this? I appreciate any help.

// Function that set last login
add_action('wp_login', 'set_last_login', 0, 2);
function set_last_login($login, $user) {
  $user = get_user_by('login',$login);
  $time = current_time( 'timestamp' );
  $last_login = get_user_meta( $user->ID, '_last_login', 'true' );
  if(!$last_login) {
    update_user_meta( $user->ID, '_last_login', $time );
  } 
   else {
    update_user_meta( $user->ID, '_last_login_prev', $last_login );
    update_user_meta( $user->ID, '_last_login', $time );
  }
}

// Function that get last login
function get_last_login($user_id, $prev = null) {
  $last_login = get_user_meta($user_id);
  $time = current_time( 'timestamp' );
  if(isset($last_login['_last_login_prev'][0]) && $prev) {
  $last_login = get_user_meta($user_id, '_last_login_prev', 'true' );
  } 
  else if(isset($last_login['_last_login'][0])) {
    $last_login = get_user_meta($user_id, '_last_login', 'true' );
  } 
  else {
    update_user_meta( $user_id, '_last_login', $time );
    $last_login = $last_login['_last_login'][0];
  } return $last_login;
}

Trying to get something like this
enter image description here

2

Answers


  1. Detect Location:

    You might want to consider using the HTML5 Geolocoation API.

    Otherwise, the IP may tell you something about the location:
    How to get Real IP from Visitor?

    Other options for location detection includes:

    Geolocator-PHP

    Google Geocoding API

    Maxmind (php)

    Detect Device:

    https://github.com/serbanghita/Mobile-Detect/

    https://www.codexworld.com/mobile-device-detection-in-php/

    http://mobiledetect.net/

    Login or Signup to reply.
  2. A bit of context, location is "Accept to share" based, on browsers (at least on desktop), meaning after a prompt from the browser, you (the user) need to accept to share your location.

    You should be able to get the latitude and longitude through javascript via the Location Web API and then get the adress from the Nominatim OpenStreetMap API.

    We could then pass everything to PHP through ajax and store it as a user metadata.


    Basic example

    The following is not production ready. It is a working proof of concept.

    Retrieving the user location

    First thing first, to use Ajax we need jQuery. We also need to pass the Ajax url to our script to be able to process the request. We will also need to pass Nonce for security reason. This is done through the wp_localize_script() function.

    <?php
    
    /**
     * Enqueue jquery.
     *
     * @see https://releases.jquery.com/
     */
    wp_enqueue_script( 'jquery-min', 'https://code.jquery.com/jquery-3.6.1.min.js', array(), '3.6.1', true );
    
    //Add jquery integrity key
    add_filter( 'script_loader_tag', function ( $tag, $handle, $src ) {
    
        if ( 'jquery-min' === $handle ) {
    
            $tag = str_replace(
                "></script>",
                " integrity='sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=' crossorigin='anonymous'></script>",
                $tag
            );
    
        };
    
        return $tag;
    
    }, 10, 3 );
    
    //Enqueue my-script
    wp_enqueue_script( 'my-script', trailingslashit( get_template_directory_uri() ) . 'assets/js/my-script.js', array( 'jquery-min' ), wp_get_theme()->version, true );
    
    /**
     * Pass the ajax admin url and a freshly generated nonce to our script.
     *
     * Apparently we should now use wp_add_inline_script instead of wp_localize_script to expose a global object that needs to be used by your script.
     * @see Jules Colle comment in the User Contributed Notes section.
     * @see https://developer.wordpress.org/reference/functions/wp_add_inline_script/#user-contributed-notes
     */
    wp_localize_script( 'my-script', 'localize', array(
        '_ajax_url' => admin_url( 'admin-ajax.php' ),
        '_ajax_nonce' => wp_create_nonce( '_ajax_nonce' ),
    ) );
    

    As we said before, we can use the Nominatim OpenStreetMap API, which is free (currently end of 2022), to reverse the location based on the latitude and longitude, and send the result to our backend for processing.

    if ( navigator.geolocation ) {
        
        /**
         * Use the browser Geolocation API.
         * Prompt the user to share his location.
         * 
         * @see https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API
         */
        window.navigator.geolocation.getCurrentPosition( function( position ) {
    
            let lat = position.coords.latitude;
            let lon = position.coords.longitude;
    
            /**
             * Reverse geocoding.
             * 
             * @https://nominatim.org/release-docs/latest/api/Reverse/
             */
            $.getJSON(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${ lat }&lon=${ lon }`, function( object ) {
                
                let adress = object.address;
                
                //Send the ajax request.
                $.ajax( {
                    type: 'POST',
                    url: localize._ajax_url,
                    data: {
                        _ajax_nonce: localize._ajax_nonce,
                        action: '_wpso_73934145',
                        openStreetMapObject: adress,
                    },
                    success: function ( response ) {
                        console.log( response.data );
                    },
                } );
            } );
        } );
    };
    

    Our javascript ajax request needs to be answered by our PHP action function which will trigger our update_user_meta() function.

    <?php
    
    add_action( 'wp_ajax__wpso_73934145', function () {
    
        if ( check_ajax_referer( '_ajax_nonce' ) ) {
    
            $user_id = get_current_user_id();
      
            $openStreetMapObject = $_POST['openStreetMapObject'];
    
            $meta_key = '_user_position';
    
            $meta_value = array(
                'openStreetMapObject' => $openStreetMapObject,
            );
    
            update_user_meta( $user_id, $meta_key, $meta_value );
    
            wp_send_json_success( $meta_value );
    
        } else {
    
            wp_send_json_error();
    
        };
    
        wp_die();
    
    } );
    

    On the front end we can access our metadata through get_user_meta().

    <?php
    
    $user_id = get_current_user_id();
    
    $meta_key = '_user_position';
    
    if ( metadata_exists( 'user', $user_id, $meta_key ) ) {
    
        $meta_value = get_user_meta( $user_id, $meta_key, true);
    
        var_dump( $meta_value );
    
        var_dump( $meta_value['openStreetMapObject']['city_district'] );
    
    } else {
        
        echo 'You need to share your location';
    
    };
    

    Retrieving the user device

    In regards to the device we can retrieve the user agent. To decrypt the user agent and understand what it stand for I would suggest reading the Mozzila User-Agent developer documentation guide.

    <?php
    
    add_action( 'init', function () {
    
        if ( is_user_logged_in() ) {
    
            $user_agent = $_SERVER['HTTP_USER_AGENT'];
    
            var_dump( $user_agent );
    
        };
    
    } );
    

    Alternatives

    Reverse search the user IP which would let us retrieve the user approximate location without prompting them.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search