Daily Lucky Numbers:
1
6
14
35
38
49

Visitor counter

Started by Dave, November 27, 2024, 09:52:19 AM

Previous topic - Next topic

Dave

I have been trying to write, with help from the internet, an HTML visitors counter. I know you can get them free from other sites and all you do is add an iframe to a code block, but I don't want that I want a counter that's mine and the code doesn't link back to another site.

The code I have so far works but for some reason is messes up the footer of some themes and I don't know why. Also the reset button is not visible either. Can some one point me in the right direction to solve it please?

The code is already added to a block on davejohnson.co.uk if you want to see it. I did have it installed on quizland but it breaks it on my tablet so I've disabled it there, also quizland uses tiny portal.

Any help is much appreciated

<html>
 <div>Visitors</div>
  <div class="website-counter"></div>
</body>
</html>

<style>
/* Center child elements */
body,
.website-counter {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
/* Styles for website counter container */
.website-counter {
  background-color: #ff4957;
  height: 30px;
  width: 50px;
  color: white;
  border-radius: 30px;
  font-weight: 700;
  font-size: 15px;
  margin-top: 10px;
}
/* Styles for reset button */
#reset {
  margin-top: 20px;
  background-color: #008cba;
  cursor: pointer;
  font-size: 18px;
  padding: 8px 20px;
  color: white;
  border: 0;
}
</style>
<script>

var counterContainer = document.querySelector(".website-counter");
var resetButton = document.querySelector("#reset");
var visitCount = localStorage.getItem("page_view");

// Check if page_view entry is present
if (visitCount) {
  visitCount = Number(visitCount) + 1;
  localStorage.setItem("page_view", visitCount);
} else {
  visitCount = 1;
  localStorage.setItem("page_view", 1);
}
counterContainer.innerHTML = visitCount;

// Adding onClick event listener
resetButton.addEventListener("click", () => {
  visitCount = 1;
  localStorage.setItem("page_view", 1);
  counterContainer.innerHTML = visitCount;
});

</script>
If you want play quizzes or games click below

Chen Zhen

#1
The issue is that you're using head & body tags on an existing html formatted page.
This willl break the page content outside of an iframe or object/embed & isn't necessary for what you're trying to do.

Your SMF 2.1 site uses JQuery by default therefore you can use that to make it more browser friendly.

HTML code:
<div class="visitor_data_body">
    <div>Visitors</div>
    <div class="website-counter"></div>
</div>
<script>
    $(document).ready(function() {
        $(".visitor_data_body").css({"display":"flex","justify-content":"center","align-items":"center","flex-direction":"column"});
        $(".website-counter").css({
            "display":"flex",
            "justify-content":"center",
            "align-items":"center",
            "flex-direction":"column",
            "background-color":"#ff4957",
            "height":"30px",
            "width":"50px",
            "color":"white",
            "border-radius":"30px",
            "font-weight":"700",
            "font-size":"15px",
            "margin-top":"10px"
        });

    });
    var visitCount = localStorage.getItem("visitor_page_view") === null ? 0 : localStorage.getItem("visitor_page_view");
    visitCount = !(/^\d+$/.test(visitCount)) ? 1 : Number(visitCount) + 1;
    localStorage.setItem("visitor_page_view", visitCount);
    $(".website-counter").html(visitCount);
    $( "#resetVisitorButton" ).on( "click", function() {
        visitCount = 1;
        localStorage.setItem("visitor_page_view", 1);
        $(".website-counter").html(visitCount);
    });
</script>


I left the onclick event for a reset button, but that button doesn't exist.
Do you want a reset button for the admin?
If you want that button I can do it in a PHP block so that you can ensure it's only the admin that has the reset option.

Chen Zhen

#2
Here is a PHP block that gives the admin a reset option when clicking on the counter container.
Change the language & css to your preference.

PHP code:
global $user_info;
list($title, $cursor, $ask) = !empty($user_info['is_admin']) ?
array('Click to reset the counter', 'help', 'Reset the page visit counter?') :
array('Page views', 'crosshair', '');
echo '
<div class="visitor_data_body">
<div>Visitors</div>
<div class="website_visit_counter"></div>
</div>
<script>
$(document).ready(function() {
$(".visitor_data_body").css({"display":"flex","justify-content":"center","align-items":"center","flex-direction":"column"});
$(".website_visit_counter").prop("title", "' . $title . '");
$(".website_visit_counter").css({
"display":"flex",
"justify-content":"center",
"align-items":"center",
"flex-direction":"column",
"background-color":"#ff4957",
"height":"30px",
"width":"50px",
"color":"white",
"border-radius":"30px",
"font-weight":"700",
"font-size":"15px",
"margin-top":"10px",
"cursor" : "' . $cursor . '"
});

});
var visitCount = localStorage.getItem("visitor_page_view") === null ? 0 : localStorage.getItem("visitor_page_view");
visitCount = !(/^\d+$/.test(visitCount)) ? 1 : Number(visitCount) + 1;
localStorage.setItem("visitor_page_view", visitCount);
$(".website_visit_counter").html(visitCount);' . (!empty($user_info['is_admin']) ? '
$( ".website_visit_counter" ).on( "click", function() {
if (confirm("' . $ask . '") == true) {
visitCount = 1;
localStorage.setItem("visitor_page_view", 1);
$(".website_visit_counter").html(visitCount);
} else {
return false;
}
});' : '') . '
</script>';

Dave

Wow thank you I wasn't expecting that so quick. I'll test it out in a minute
If you want play quizzes or games click below

Dave

That works great Chen thank you very much, I created the reset block also but at present I've disabled it.

Thanks again  :)
If you want play quizzes or games click below

Chen Zhen

FYI that doesn't really keep count of site-wide page visits.
The number only represents how many times the page is visited for the member's browser & for that session.

If you want it to keep a record of page views from anyone (members, guests/bots), then it needs to store data in the DB or to a file. Also you should possibly decide if you want it to reset at ie. 12 a.m. each day. I can make something that works like that if you want it to display a proper number to whomever can view the block.

Chen Zhen

#6
This is more realistic & I gave you a few more option...

PHP Block Code:
global $user_info, $modSettings;
$actCounter = true; // boolean : true = different counter for each action, false = same counter for every action
$buttonName = !empty($actCounter) ? 'Page Views' : 'Visitors';
list($title, $title2, $cursor, $ask, $ask2, $visitCount, $data) = !empty($user_info['is_admin']) ?
array('Click to reset the counter', 'Click to reset the current action counter', 'help', 'Reset the page visit counter?', 'Reset the page visit counter for this action?', array(), array()) :
array('Page views', '', 'crosshair', '', '', array(), array());

// don't bother changing code below this comment
$action = !empty($_REQUEST['action']) && !empty($actCounter) && is_string($_REQUEST['action']) ? strtolower($_REQUEST['action']) . '_' : 'visitor_count_';
$reset = !empty($_REQUEST['visitorReset']) && is_string($_REQUEST['visitorReset']) && $_REQUEST['visitorReset'] == $action && !empty($user_info['is_admin']) ? true : false;
$data = !empty($modSettings['website_visitor_count']) && json_validate($modSettings['website_visitor_count']) ? json_decode($modSettings['website_visitor_count'], true) : array();
$visitCount[$action] = empty($reset) && !empty($data) && !empty($data[$action]) ? intval($data[$action]) + 1 : 1;
$data[$action] = $visitCount[$action];
$setting = json_encode($data, JSON_INVALID_UTF8_SUBSTITUTE);
updateSettings(array('website_visitor_count' => $setting));
echo '
<div class="visitor_data_body">
<div>' . $buttonName . '</div>
<div class="website_visit_counter"></div>
</div>
<script>
$(document).ready(function() {
$(".visitor_data_body").css({"display":"flex","justify-content":"center","align-items":"center","flex-direction":"column"});
$(".website_visit_counter").prop("title", "' . (empty($actCounter) ? $title : $title2) . '");
$(".website_visit_counter").css({
"display":"flex",
"justify-content":"center",
"align-items":"center",
"flex-direction":"column",
"background-color":"#ff4957",
"height":"30px",
"width":"50px",
"color":"white",
"border-radius":"30px",
"font-weight":"700",
"font-size":"15px",
"margin-top":"10px",
"cursor" : "' . $cursor . '"
});

});
var posthash, visitCount = Number("' . $visitCount[$action] . '");
$(".website_visit_counter").html(visitCount);' . (!empty($user_info['is_admin']) ? '
$( ".website_visit_counter" ).on( "click", function() {
if (confirm("' . (empty($actCounter) ? $ask : $ask2) . '") == true) {
posthash = location.hash.replace("#", "");
if(posthash != ""){
location.hash = "";
}
window.location.href = window.location.href.replace(/\;visitorReset=\d+/g,"").replace(/\;+$/, "").replace(/\#+$/, "") + ";visitorReset=' . $action . '";
} else {
return false;
}
});' : '') . '
</script>';

Dave

Thanks Chen

Yes the idea was for site wide page visits going forward and no need for a reset, I didn't understand the idea of the reset button in the first place as the number should just increase day by day as visitors and members come to the site.

I'll have a look at your code in a few days
If you want play quizzes or games click below

Chen Zhen

#8
$actCounter = false;
Just make the above variable false & it will tally all visits in a lump sum from any page that uses the block.
The only person that can reset the counter is an admin.


Here is another code that is likely set up the way you want it....

PHP block code:
global $user_info, $modSettings;
$actCounter = false; // boolean : true = different counter for each action, false = same counter for every action
$buttonName = !empty($actCounter) ? 'Page Views' : 'Visitors';
// allow a reset option for speicific users -> use array(0) for all admins, user id# for specific admin [ ie. array(1) ] or multiple user id#'s for specific users [ ie. array (1,3,8) ]
// requires $adminReset to be true else it will be ignored
$adminId = array(1);
$adminReset = true;
if (empty($user_info['is_guest']) && !empty($adminReset)) {
$allowReset = empty($adminId[0]) && !empty($user_info['is_admin']) ? true : (in_array($user_info['id'], $adminId) ? true : false);
}
list($title, $title2, $cursor, $ask, $ask2, $visitCount, $data) = !empty($adminReset) && !empty($allowReset) ?
array('Click to reset the counter', 'Click to reset the current action counter', 'help', 'Reset the page visit counter?', 'Reset the page visit counter for this action?', array(), array()) :
array('Page views', '', 'crosshair', '', '', array(), array());

// don't bother changing code below this comment
$action = !empty($_REQUEST['action']) && !empty($actCounter) && is_string($_REQUEST['action']) ? strtolower($_REQUEST['action']) . '_' : 'visitor_count_';
$reset = !empty($_REQUEST['visitorReset']) && is_string($_REQUEST['visitorReset']) && $_REQUEST['visitorReset'] == $action && !empty($allowReset) ? true : false;
$data = !empty($modSettings['website_visitor_count']) && json_validate($modSettings['website_visitor_count']) ? json_decode($modSettings['website_visitor_count'], true) : array();
$visitCount[$action] = empty($reset) && !empty($data) && !empty($data[$action]) ? intval($data[$action]) + 1 : 1;
$data[$action] = $visitCount[$action];
$setting = json_encode($data, JSON_INVALID_UTF8_SUBSTITUTE);
updateSettings(array('website_visitor_count' => $setting));
echo '
<div class="visitor_data_body">
<div>' . $buttonName . '</div>
<div class="website_visit_counter"></div>
</div>
<script>
$(document).ready(function() {
$(".visitor_data_body").css({"display":"flex","justify-content":"center","align-items":"center","flex-direction":"column"});
$(".website_visit_counter").prop("title", "' . (empty($actCounter) ? $title : $title2) . '");
$(".website_visit_counter").css({
"display":"flex",
"justify-content":"center",
"align-items":"center",
"flex-direction":"column",
"background-color":"#ff4957",
"height":"30px",
"width":"50px",
"color":"white",
"border-radius":"30px",
"font-weight":"700",
"font-size":"15px",
"margin-top":"10px",
"cursor" : "' . $cursor . '"
});

});
var posthash, visitCount = Number("' . $visitCount[$action] . '");
$(".website_visit_counter").html(visitCount);' . (!empty($allowReset) ? '
$( ".website_visit_counter" ).on( "click", function() {
if (confirm("' . (empty($actCounter) ? $ask : $ask2) . '") == true) {
posthash = location.hash.replace("#", "");
if(posthash != ""){
location.hash = "";
}
window.location.href = window.location.href.replace(/\;visitorReset=\d+/g,"").replace(/\;+$/, "").replace(/\#+$/, "") + ";visitorReset=' . $action . '";
} else {
return false;
}
});' : '') . '
</script>';



This one currently can only be reset by user id#1 which is you.
It asks for confirmation before a reset so you don't do it by accident.
The user IDs that can use the reset are configurable & it can be disabled altogether.
All variables at the onset of the block are more or less self explanatory or have remarks for guidance.



Dave

If you want play quizzes or games click below

Chen Zhen


The PHP block works on a local & on my live sites but fails to work on your DJ website.
No errors on the page or in the log.. what's up with that?

Dave

#11
Quote from: Chen Zhen on December 05, 2024, 01:28:01 AMThe PHP block works on a local & on my live sites but fails to work on your DJ website.
No errors on the page or in the log.. what's up with that?


I see you've uninstalled the portal and reinstalled it again today so no point in me doing that.  Maybe one of the other blocks is causing the issue, as you don't say what the issue is I'll leave it to you to try to temp disable the other blocks, unless you've already tried that.

One thing I found out from installing another mod some while ago is that DJ was originally a 2.0 site that was converted to 2.1 and although I have stripped it down and re-installed the theme and sources folders obviously there is still the database that isn't really changed that much.

I'll do a backup of the database and then remove all the tables for the portal and re-install it. Then you can test on a new version of the portal and see if it still does it
If you want play quizzes or games click below

Dave

#12
UPDATE:

I uninstalled the tables and the mod and reinstalled it.

I added the code to the block and tested it but nothing showed so I checked it again and decided to 'Add Block' then I got this error
Database error in block code. Please check the code.
I'm now going to test the code on the clean test site and see what happens

UPDATE2:

It worked on a clean install of 2.1 but if I don't use it and then go back and try again it fails with the same error as DJ. It  works on Quizland though. I'm now going to try an older version of the portal

It's an error that shouldn't happen so I'm going to reinstall an old database from mid November and see if that helps, there has been no posts since then so no problem about losing anything
If you want play quizzes or games click below

Dave

#13
UPDATE3:

I start from a fresh 2.1.4 install with the test site.

I then installed the latest version of the portal. I then added the latest code for the Visitors that you posted, and when I clicked on 'Preview' it worked, but as soon as I clicked on 'Add Block' it gave me the database error as previously mentioned.

I'm now going to uninstall the portal again and remove all tables (when uninstalling completely by selection the delete all option it leaves 2 tables behind see attached) and see what happens then.
I'm going to export the database now and then compare it to a copy from after the portal is removed  and see what's changed.

I might then reinstall 2.1.4 again and compare that way too.

UPDATE4:

I uninstalled the portal and saved the database, then I started again with 2.1.4. upon comparing the tables there are still remnants of the portal in the settings table and even though the visitors counter wasn't installed there is code in there for that at line 2058 in the attached 'u286627211_SMF2anoportal' I have also attached a copy of a fresh database from the new install so you can compare as I did. I use Notepad++.

I have just checked the DJ database settings table and removed the
website_visitor_count {"visitor_count_":1}variable for it. Then added the code to a new block again and did a preview and the counter shows, see attached image, but as soon as you click on 'Add Block' the error
Database error in block code. Please check the code. comes back .

I'm not sure if that helps you or not. I will check Quizland database and see if there's a similar variable in there.

The same variable is there on Quizland website_visitor_count {"visitor_count_":994} it's the same except for the numbers


If you want play quizzes or games click below

Dave

#14
Last update.

I remembered I had a spare database on the Quiz host so I installed 2.1.4 on there and then installed the latest EHP and added the block and it works fine, so therefore it's a DJ thing.

I have now mirrored DJ with Quiz in respect of all the PHP settings. It was on PHP 7.4 (the reason for that is because I have an SMF2.0.19 test site set up so I can see the original themes that Skhilled, Twitch and I work on so when we're updating the new css files etc we can match as near as possible to the originals)

I've now set it to PHP8.3 and all the php options etc are now the same as Quiz.

I installed the EHPortal again and added the block code and it now works fine, so my best guess is that it was the PHP version that was at fault

I don't know if that's something you can address so that it's backwards compatible with older versions of PHP or even if you want to.

Anyway it's solved and now all I have to do is get DJ mods reinstalled and looking as it did before.

I hope this has helped.


Not sure if you've read this or not yet but here's some more info.

I have found out that for some reason when the database is saved the content of the blocks is not shown in the blocks table.
Below is the current blocks table with the welcome block having text etc added but as you can see it's not seen in the table, I wonder how it remembers it's there?

(1, 'User Info', 'sp_userInfo', 1, 1, 3, '', '', 1, 0, 0, 0, '', '', ''),
(2, 'Who&#039;s Online', 'sp_whosOnline', 1, 2, 3, '', '', 1, 0, 0, 0, '', '', ''),
(3, 'Board Stats', 'sp_boardStats', 1, 3, 3, '', '', 1, 0, 0, 0, '', '', ''),
(4, 'Theme Select', 'sp_theme_select', 1, 4, 3, '', '', 1, 0, 0, 0, '', '', ''),
(5, 'Search', 'sp_quickSearch', 1, 5, 3, '', '', 1, 0, 0, 0, '', '', ''),
(6, 'News', 'sp_news', 2, 1, 3, '', '', 1, 0, 0, 0, '', '', 'title_default_class~|title_custom_class~|title_custom_style~|body_default_class~windowbg|body_custom_class~|body_custom_style~|no_title~1|no_body~'),
(7, 'Welcome', 'sp_html', 2, 2, 3, '', '', 1, 0, 0, 0, 'sportal', '', 'title_default_class~|title_custom_class~|title_custom_style~|body_default_class~windowbg|body_custom_class~|body_custom_style~|no_title~1|no_body~'),
(8, 'Board News', 'sp_boardNews', 2, 3, 3, '', '', 1, 0, 0, 0, '', '', ''),
(9, 'Recent Topics', 'sp_recent', 3, 1, 3, '', '', 1, 0, 0, 0, '', '', ''),
(10, 'Top Poster', 'sp_topPoster', 4, 1, 3, '', '', 1, 0, 0, 0, '', '', ''),
(11, 'Recent Posts', 'sp_recent', 4, 2, 3, '', '', 1, 0, 0, 0, '', '', ''),
(12, 'Forum Staff', 'sp_staff', 4, 3, 3, '', '', 1, 0, 0, 0, '', '', ''),
(13, 'Calendar', 'sp_calendar', 4, 4, 3, '', '', 1, 0, 0, 0, '', '', ''),
(14, 'Top Boards', 'sp_topBoards', 4, 5, 3, '', '', 1, 0, 0, 0, '', '', ''),
(15, 'Visitors', 'sp_php', 6, 1, 3, '', '', 1, 0, 0, 0, 'sportal', '', 'title_default_class~catbg|title_custom_class~|title_custom_style~|body_default_class~|body_custom_class~|body_custom_style~|no_title~|no_body~1');

If you want play quizzes or games click below