Search...

XenForo forum installation, securing, and configuring

I’ve been using, moderating and administrating forums since they emerged after BBS and Usenet era (Wiki links). At the time of writing, XenForo (the official website link) is the best the-least-bad forum software in the world (at least in my opinion and for my use-case). This article is basically my notes on my XenForo installation and configuration – so I can get help and advice from people who actually know what they’re doing. 🙂
Oh, you can check out the BikeGremlin Forum here. 🙂

xenForo 2.3 version specifics and update/upgrade

Why I built the BikeGremlin forum

Table Of Contents (T.O.C.):

  1. Installation
  2. Security
    2.1. SPAM prevention
  3. Forum setup and configuration
    3.1. Emails
    3.2. Languages
    3.3. Style and push notifications (PWA)
    3.4. General settings
    3.5. Connected account providers
    3.6. Editing terms, privacy policy, and footer (copyright)
    3.7. Connecting Google Analytics
    3.8. Adding Google Custom (“programmable”) search
    3.9. No GIFs – no party!
    3.10. <head> section customization – Favicon setup
    3.11. robots.txt file
  4. User groups and permissions
    4.1. User registration process
  5. Performance – LiteSpeed vs Redis cache
    5.1. Implementing cache
  6. Why, God, WHY?!
  7. Custom stuff
    7.1. Custom navigation and admin/mod only visible menu
    7.2. List users with unconfirmed emails
    7.3. Custom CSS
    7.4. Scroll progress bar on top
    7.5. Registration form custom text
  8. Google AdSense and GDPR
    8.1. AdSense breaking layout fix
    …8.1.1. In-article ad problems
    …8.1.2. Anchor ads on desktop problem
    …8.1.3. AdSense & XenForo problems conclusion
  9. Updating XenForo


1. Installation

This procedure is very simple and straightforward – nicely explained on XenForo’s website in an article called Installing XenForo (what else? 🙂 ).

Note: you must create a database, a database user, and set the user’s password, before you run the installation. The procedure is basically identical to WordPress installation procedure.

Recommended PHP version and extensions:

PHP version 8.0
Update, February 2024:
The latest XenForo version v2.2.15 comes with PHP 8.2 recommended

Update, July 2024:
For xenForo 2.3:
Minimum PHP is 7.2, recommended is 8.3;
Minimum MySQL 5.7, recommended is 8.0;

Extensions:

  • imagick
  • exif
  • phar (for Gzip support)
  • mbstring
  • gmp
  • zip

Your admin dashboard may show:
“Suhosin enabled: No”

That’s OK. As far as I know, Suhosin (link to the project’s page) makes more problems than it solves (I suppose that info is shown for tech. support & troubleshooting purposes).

You could make a “php-info.php” file (simple text file, but with a .php instead of the .txt extension), with this code:

<?php phpinfo(); ?>

Upload it to you’r forum’s directory, and go to: “yourdomain.com/php-info.php” to see if you have all the needed extensions enabled (and general PHP info like version etc.). Make sure to not leave that file though – delete it after testing, just for increased security.

– T.O.C. –


2. Security

The first thing I did was edit the .htaccess file by adding this at its beginning:

# BEGIN BikeGremlin edit

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^.well-known - [L]

# directory listing protection
Options -Indexes

# clickjacking attack protection
Header always append X-Frame-Options SAMEORIGIN

# MIME sniffing protection
Header set X-Content-Type-Options nosniff

# XSS protection
Header set X-XSS-Protection "1; mode=block"

# redirect from naked to www and https:
RewriteEngine on
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) https://www.bikegremlin.net%{REQUEST_URI} [L,R=301]

</IfModule>

# END BikeGremlin edit

XenForo forum user “digitalpoint” wrote an awesome guide with some tips on securing the forum using Cloudflare’s Zero Trust, here’s a link to that guide:
Cloudflare optimizations for XenForo

I’ve protected /install and admin-related paths with CloudFlare zero trust. To do this I just added a new “Application” for the forum (see my Cloudflare Zero Trust setup tutorial for details).


For better or for worse, I’ve decided to configure and implement Cloudflare Turnstile spam protection (it should work like a non-intrusive reCaptcha). XenForo offers a good integration for that:
Setup -> Options -> Basic Options -> Enable CAPTCHA for guests -> Use Cloudflare Turnstile

There, I could follow the Cloudflare Turnstile link with a simple guide for configuration.

Checking to confirm that Cloudflare Turnstile works for the register and login pages
Checking to confirm that Cloudflare Turnstile works for the register and login pages
Click on the image to see it full-sized

– T.O.C. –


2.1. SPAM prevention

Cloudflare is good, but it is probably a good idea to set up a few more spam-protection layers (why security is best done in layers). XenForo offers easy to set up integrations with following (free) services:
Setup -> Options -> Spam management

  • StopForumSpam
  • DNSBL
  • Akismet
  • Cloudflare Turnstile

– T.O.C. –


3. Forum setup and configuration


3.1. Emails

The first thing I did was go to:
Setup -> Options -> Email options
and configure the forum to send emails using my MXroute server.

Configuring XenForo to use my MXroute SMTP server for sending emails
Configuring XenForo to use my MXroute SMTP server for sending emails
Click on the image to see it full-sized

Tools -> Test outbound email
lets you test and confirm if you’ve configured it all properly.

Now, my MXroute account is limited to 300 outbound emails per hour. That’s not huge, not for a big forum.

In that same menu, there is an option called:
“Automated bounced email handler”
Enable it, to prevent sending emails that get nowhere.

I’ve created two separate additional email addresses. One for bounced, and another one for unsubscribe emails.

– T.O.C. –


3.2. Languages

Next up was the language setup:
Appearance -> Languages & phrases -> Languages -> + Add language;
Where I added Serbian language (Serbocroatian).

Now was the time to make the post and page addresses look neatly:
Setup -> Options -> Basic options
Then checking the checkboxes under:
“Use full friendly URLs” and
“Romanize titles in URLs”

Every option has a nice, simple explanation of what it does – neat.

Setup -> Options -> Appearance
lets you select the default language (which will be active until users choose a different one).

This seems quite awkward. Apparently, I’m required to translate all the strings and phrases myself. I also find the computer-related terms in my native to be confusing (habit, probably). That would make offering support more difficult (if a user refers to something using the translation – as I never use interfaces in my native – LOL 🙂 ). So, I’ve decided to ditch the idea of a bilingual interface, for better or for worse.

– T.O.C. –


3.3. Style and push notifications (PWA)

I’ve created a new style (called it “BikeGremlin Style,” yes 🙂 ), to save all the edits in it. Setting it to inherit everything from the “Default style” and then customizing.

This part is important for the PWA setup:
Appearance -> Style -> Style properties -> Basic options
There, I uploaded all the icons.

In the Page setup of the same menu, I set the Max. page width to 1250 px, and wide response break point at 1100 px.

Once all the icons are uploaded and configured properly, you can go to the PWA settings and enable the option for push notifications (some users like having that option).

XenForo’s PWA setup manual.

– T.O.C. –


3.4. General settings

Setup -> Options -> Node & forum list
Here, I’ve checked the option to “Create pages for categories” – which means clicking on a forum category will open a page listing its subcategories. Otherwise, clicking a category only scrolls the screen to show that category on top.

– T.O.C. –


3.5. Connected account providers

This might help with visitor registration by providing registration with Facebook and similar.

Linkedin login support seems to be botched – Sign in with LinkedIn deprecated (XenForo forum bug report link).

Facebook API seems to require a registered business.

So, apart from registering and logging in with an email and a password, I’ve managed to configure the following alternative (easier, probably more convenient) sign in options:

  • Google account
  • GitHub account
  • Microsoft account

Microsoft only allows a time-limited API (max. 2 years). And I’m not a huge fan. So I ditched that integration, after having confirmed that it works. 🙂

– T.O.C. –


3.6. Editing terms, privacy policy, and footer (copyright)

To edit these, I had to go to:
Appearance -> Phrases
and then find the things I wanted to customize, notably:

  • terms_rules_text
  • privacy_policy_text

It’s all basic HTML, and here are a couple of nice, free, online HTML editors:

I have also tried editing the footer, using this code, editing the template for:
extra_copyright

Note:
I paid for the XenForo license that allows for removing their default footer copyrigh (with a rel=”sponsored” link), but I wanted my footer to link and advertise what I consider to be the best the least bad (what?! I’m a pessimist, OK? 🙂 ) forum software in the world – that’s why I’ve included XenForo and Giphy links in the footer’s “final” version.

This is a basic version which is completely static:

<p>&copy; 2015 - 2023 <a title="BikeGremlin" href="https://www.bikegremlin.com/" target="_blank"><strong>BikeGremlin</strong></a> &bull; Powered by bacon, electricity &amp; <a title="XenForo" href="https://xenforo.com/" target="_blank"><strong>XenForo</strong></a></p>

Using this PHP code for the current year didn’t seem to be working:

// NOT WORKING:

<?php echo date("Y"); ?>

// NOR THIS:

<?php strftime("%Y"); ?>

Gox suggested I should try JavaScript – and that worked. Here’s the current date (year in this case) script that works with XenForo:

<script>document.write(/\d{4}/.exec(Date())[0])</script>

That allowed me to make the footer so I never have to update it for the current year, it should auto-update.

Here is the full code of my XenForo forum’s footer (see after this, below, for the improved code):

<p>&copy; 2023 - <script>document.write(/\d{4}/.exec(Date())[0])</script> <a title="BikeGremlin" href="https://www.bikegremlin.com/" target="_blank"><strong>BikeGremlin</strong></a> &bull; Powered by bacon, <a title="XenForo" href="https://xenforo.com/" target="_blank"><strong>XenForo</strong></a> &amp; <a title="GIPHY" href="https://giphy.com/" target="_blank"><strong>GIPHY</strong></a></p>

Update October 2024:

This code should be more performant than using “document.write”:

<p>&copy; 2023 - <span id="currentYear"></span> 
    <a title="BikeGremlin" href="https://www.bikegremlin.com/" target="_blank"><strong>BikeGremlin</strong></a> 
    &bull; Powered by bacon, 
    <a title="XenForo" href="https://xenforo.com/" target="_blank" rel="noreferrer noopener nofollow"><strong>XenForo</strong></a> 
    &amp; 
    <a title="GIPHY" href="https://giphy.com/" target="_blank" rel="noreferrer noopener nofollow"><strong>GIPHY</strong></a>
    <script>document.getElementById("currentYear").textContent = new Date().getFullYear();</script>
</p>

– T.O.C. –


3.7. Connecting Google Analytics

No need for any custom coding or extensions and similar (unlike WordPress).
Setup -> Options -> Search engine optimization (SEO)
And just copy/paste your Google Analytics tracking ID (“Google Analytics web property ID”).

– T.O.C. –


3.8. Adding Google Custom (“programmable”) search

Google does search a lot better – and it doesn’t put stress on the forum hosting server. That’s why I wanted to include that option to my forum.

In a separate (WordPress-related) article, I’ve explained the procedure of opening and configuring a Google Custom Search account.

But how do I add my Google custom search (now called Google Programmable search) code to my forum?

Appearance -> Styles -> Templates
find the “search_form” template and add your code at the end (or at the start if you want it to be shown first):

<xf:comment>BEGIN Google Programmable Search Form</xf:comment>
<div class="block-container">
  <div class="block-body block-row">
    <h1 class="p-title-value">Forum search by Google</h1>

    <script async src="https://cse.google.com/cse.js?cx=YOUR-GCSE-CODE-HERE"></script>
    <div class="gcse-search"></div>

    <div>
      <gcse:searchresults>
      </gcse:searchresults>
    </div>
  </div>
</div>
<xf:comment>END Google Programmable Search Form</xf:comment>

Update:

I’ve also created a separate search page. Why? Well, for several reasons:

  • It can work even if I disable the forum’s built-in search option. This will reduce any extra server load in case of very high demand & traffic – I like building things that can easily scale, right from the start.
  • I can make it clearly visible when visitors are watching all the topics (I aim to encourage people to use the search and find the info they need).
  • The page views of the search page are counted, so I can see if people are using the search without any additional visitor trackers or similar (more privacy is good).

Here’s what that looks like at the time of writing:

How I made that extra menu option is explained in section 7.1 (just disregard the “admin-only” stuff if you want it to be visible to all the visitors, of course).

For the page itself, I did:
Forums -> Nodes -> + Add node
and then chose the “Page” option.

Then I just copy/pasted the above listed code, and checked the “Log and count visits to this page” option. Of course, I gave it a Title (“Smart Forum Search”) and “URL portion” (“bg_search”), so the link to my search page is:
https://www.bikegremlin.net/pages/bg_search/

I could then easily make a custom menu navigation (section 7.1) item that leads to that link.

I suppose that I could still edit the “search_form” to show only my Google custom search (instead of completely removing that option for visitors), but I will leave the option of using the normal search bee for now.

– T.O.C. –


3.9. No GIFs – no party!

Animated GIFs can be pretty cool when added to posts (even when “fashionably overdone” as it happens with LES Black Friday deal threads). But they take up a lot of storage space, compared to static images.

Fortunately, XenForo offers a neat, out-of-the box integration with GIPHY. Giphy’s API is awesome – it lets you integrate GIFs stored and served from their servers. Awesome! 🙂

– T.O.C. –


3.10. section customization – Favicon setup

According to the latest Google’s doccumentation, it is no longer enough to just upload a favicon to your website’s root folder.

Now, you must place an invisible link to your favicon’s .ico file in your home page’s header. Here’s an example of what that link looks like for this website:

<link rel="icon" href="https://io.bikegremlin.com/favicon.ico">

The path to the favicon file can be either absolute or relative. Here’s an example of a relative path, with the favicon file named “favicon.ico” and placed in the website’s root directory:

<link rel="icon" href="/favicon.ico">

Google article explaining the new favicon policy:
https://developers.google.com/search/docs/appearance/favicon-in-search

For more details on the needed code and favicon formats (and resolution), see my article:
How to add favicon link to the WordPress header?


How to edit the <head> … </head> section for Xenforo?

Appearance -> Styles -> Your Theme(s) -> Template ->
PAGE_CONTAINER

There, you can add your code. Find the </head>, make a new line break above it, and add this (before the </head> line):

<!-- BEGIN BikeGremlin invisible favicon links -->
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<!-- END BikeGremlin invisible favicon links -->

This method is good for adding the Google AdSense code too, as discussed in chapter 8.

– T.O.C. –


3.11. robots.txt file

The robots.txt file contains instructions for crawlers. This is done manually. You need to create and upload the “robots.txt” file. I’ve created one that blocks most SEO tools’ robots, and directories (including my custom search page “/pages/bg_search/”) that no crawler should be wasting its time on visiting or indexing.

You should place the “robots.txt” file in your (sub)domain’s root directory.

The file also contains a link to my forum’s sitemap (this can be either an .xml or a sitemap.php file).

User-agent: PetalBot
User-agent: AspiegelBot
User-agent: AhrefsBot
User-agent: SemrushBot
User-agent: SemRush
User-agent: DotBot
User-agent: MauiBot
User-agent: MJ12bot
Disallow: /

User-agent: Amazonbot
Disallow: /threads/*/reply

User-agent: *
Disallow: /pages/bg_search/
Disallow: /search/
Disallow: /whats-new/
Disallow: /find-threads/
Disallow: /watched/
Disallow: /account/
Disallow: /members/
Disallow: /attachments/
Disallow: /goto/
Disallow: /posts/
Disallow: /login/
Disallow: /admin.php
Allow: /

Sitemap: https://www.bikegremlin.net/sitemap.xml

– T.O.C. –


4. User groups and permissions

XenForo has this sorted out pretty neatly by default.

I added a group called “Registered-confirmed.” Users from that group can post comments without prior moderators’ approval.

Groups & permissions -> User group promotions
menu let me configure conditions when users are automatically promoted from “Registered” to “Registered-confirmed” group.

A stupidity on my part:

By default, unregistered visitors (guests) are not allowed to view attachments.

Hence, when I wrote and published a tutorial on how to register and post a comment on my forum, guests could only see the small 150-pixel thumbnails of the screenshots in the tutorial. After Googling (apparently the wrong terms) and searching the forum, I posted a question on the XenForo support forum.

Apparently, my keyboard was faster than my brain – and I did not take my own advice related to tech. support. A minute after having written the problem down and posted it on the support forum, I remembered the user permissions about the attachments (that’s how XenForo calls any attachments, including the images).

Yes, allowing the guest users (“Unregistered / Unconfirmed”) to view the attachments has solved the problem:

Groups & permissions -> User group permissions -> Unregistered / Unconfirmed
-> Forum permissions -> View attachments to posts (set to “Yes”)

– T.O.C. –


4.1. User registration process

I wrote two brief tutorials for new members, because today, there are millions of people who’ve never ever used forums (and don’t even konw what a forum is). I published those as articles on my forum.

Then, I made a short HTML code that includes the email confirmation explanation in my native as well as in english, and added it here:
Appearance -> LanguagesEnglish (US) -> Phrases -> Edit phrase:
user_email_confirmation_body_html

<p><strong>English:</strong> Hi {username}, in order to complete your registration or reactivate your account at {board}, you need to confirm your email address by clicking the "Confirm your email" button below.</p>

<p><strong>Srpskohrvatski:</strong> Ćao {username}, da biste završili registraciju, kliknite na dugme "Confirm your email" dole.</p>

Here is what that looks like (in the mean time, I added a space before “Ćao” in the Serbocroatian section 🙂 ):

XenForo custom email confirmation note
XenForo custom email confirmation note

I also created a welcome e-mail with the basic instructions (how to post on a forum, yes, some people needed help):

Setup -> Options -> User Registration -> New User Welcome (section)

Checked the “Send welcome email on registration,” chose the HTML format option, and added this (text and links to my above-linked tutorial articles):

<p><strong>English:&nbsp;</strong>Welcome to the BikeGremlin forum. :)</p>
<p>Your account has been approved.</p>
<p>A brief tutorial (you can <strong>skip the section 1</strong>, since you've already done that :) ):<br /><a title="How to register and post a question/comment on the BikeGremlin forum" href="https://www.bikegremlin.net/threads/how-to-register-and-post-a-comment-question-on-bikegremlin-forum.24/" target="_blank"><strong>How to finish your registration and post a question or a comment</strong></a></p>
<p><strong>Srpskohrvatski: </strong>Dobrodo&scaron;li na BikeGremlin forum.&nbsp; :)</p>
<p>Va&scaron; nalog je odobren.</p>
<p>Kratko uputstvo (možete <strong>preskočiti sekciju 1</strong>, jer ste to već obavili :) ):<br /><a title="Kako se registrovati i postaviti pitanje/komentar na BikeGremlin forumu" href="https://www.bikegremlin.net/threads/kako-se-registrovati-i-postaviti-pitanje-komentar-na-bikegremlin-forumu.25/" target="_blank"><strong>Kako da zavr&scaron;ite registraciju i postavite pitanje ili komentar</strong></a></p>
<p>Relja Novović</p>

– T.O.C. –


5. Performance – LiteSpeed vs Redis cache

My server is LiteSpeed and that has been awesome for WordPress caching. Apparently, there is also a LiteSpeed XenForo add-on (link to its website).

It appears that the add-on is no longer maintained, according to the XenForo’s Resource section:
https://xenforo.com/community/resources/litespeed-cache-for-xf2-community.6248/

Redis cache add-on, on the other hand, seems to be still maintained:
https://xenforo.com/community/resources/redis-cache-by-xon.5562/

However, the last update date for the LiteSpeed plugin is just days before the latest XenForo version publish date (at the time of writing this). Perhaps the LiteSpeed folks just didn’t have any bugs to fix in the meantime?

What is the difference between LiteSpeed and Redis anyway?

LiteSpeed can cache any page that is created on the forum (this includes a forum page with a list of posts). It does that extremely well with WordPress and I can only assume (hope?) it is similar with XenForo.

Redis, on the other hand, can also cache any database querries. If one user searches for “best bicycle bearing grease,” the results of that forum search will be cached for the next user who does that search (oversimplified, but that’s roughly how it works).

Now, with WordPress, LiteSpeed cache plugin can use Redis for caching objects (as explained in the previous paragraph). It can “integrate” it, if Redis is present and properly configured on the server (as is the case with MDDHosting shared & reseller hosting servers). I couldn’t find any info on Redis in the LiteSpeed for XenForo installation manual.

At the time of writing, BikeGremlin Forum is running on PHP 8.0 and XenForo v2.2.13. As far as I know, a minor patch or two will be coming up in a few months, and a major update to version 2.3 is also in the making (and beta-testing). With a major change to 3.0 in sight.

From what I could gather, extensions don’t always work properly right away with a new version of forum software – especially in case of any major overhauls.

For these reasons, I’ve decided to keep running the “vanilla” forum version – with minimal changes. It’s running very smoothly now. When more people join the forum and if I notice any performance issues, I’ll see how to solve them – “crossing that bridge when I reach it” as the Americans say.

– T.O.C. –

5.1. Implementing cache

My forum is slowly growing, so I decided to start looking into some caching optimizations. I started with the XenForo’s cache docummentation.

These are the Redis setup instructions (MDDHosting offers Redis object cache even in shared hosting environments! 🙂 ) – to be added to the src/config.php file:

$config['cache']['enabled'] = true;
$config['cache']['provider'] = 'Redis';
$config['cache']['config'] = [
    'host' => '127.0.0.1',
    'password' => 'password'
];

In my case, that would be (no password):
Update – configure only socket, not the port, especially with XenForo 2.3.x (the code has the port config commented out using “//” , but I added the strike-over just to make it more clear – XenForo 2.2.x seems to have just disregarded the port configuration since it’s not using it – you live and lear 🙂 ).

//BEGIN BikeGremlin Redis
$config['cache']['enabled'] = true;
$config['cache']['provider'] = 'Redis';
$config['cache']['config'] = [
    'host' => '/home/my_cpanel_username/redis.sock',
//    'port' => 6379
];
//END BikeGremlin Redis

I decided to give it a test with LiteSpeed addon as well, just to see how and if it works. These are the LiteSpeed for XenForo installation instructions.
Update, August 2024:
Check if the LiteSpeed cache works with your XenForo version. These are my up-to-date notes on that for the XenForo 2.3.x:
https://io.bikegremlin.com/34518/xenforo-2-3-specifics-and-upgrade/#2.1

To install from a zipped archive, you must first add this line to the src/config.php file:

//BEGIN BikeGremlin allow install from archives
$config['enableAddOnArchiveInstaller'] = true;
//END BikeGremlin allow install from archives

After you’ve run the installation, to have the LiteSpeed work, the following must be added to the .htaccess file in the root directory of your XenForo forum installation:

#BEGIN BikeGremlin LiteSpeed addon
# LiteSpeed XenForo cache
<IfModule litespeed>
    CacheLookup public on
    RewriteEngine On
    # cache
    RewriteCond %{HTTP_COOKIE} !(xf_lscxf_logged_in|xf_user|xf_session_admin) [NC]
    RewriteCond %{REQUEST_URI} !/install/ [NC]
    RewriteRule .* - [E=Cache-Control:max-age=360,E="cache-vary:xf_style_id,xf_language_id"]
    # no cache
    RewriteCond %{HTTP_COOKIE} (xf_lscxf_logged_in|xf_user|xf_session_admin) [NC]
    RewriteRule .* - [E=Cache-Control:vary=loggedin,E=Cache-Control:no-cache]
</IfModule>
#END BikeGremlin LiteSpeed addon

Now, you can use this need LiteSpeed’s tool to easily check if your LiteSpeed cache is working:
https://check.lscache.io/

– T.O.C. –


6. Why, God, WHY?!

Forums are awesome. While WordPress sucks when it comes to handling comments – especially questions and response types of comments.

XenForo setup and configuration are pretty simple compared to most other forum software I’ve played with. But that is not all (I sound like a salesman now – LOL 🙂 ):

  • Practically every setting is clearly explained within the menu itself.
  • XenForo docummentation is good and well-written.
  • There’s an awesome support forum.
  • Most settings are pretty well configured out-of-the-box (i.e. by default).

So far so good (says a man falling from a 10-storey building)… 🙂

On my cycling website, I wrote in more details about why I thought building a forum is a jolly good idea.

On my forum, I wrote in a lot more detail about why I chose XenForo vs its alternatives.

– T.O.C. –


7. Custom stuff

7.1. Custom navigation and admin/mod only visible menu

To make a menu visible to only admins, or mods, go to:
Setup -> Public navigation

Add Navigation (top-right corner button), and set the display condition:

Admins only:

$xf.visitor.is_admin

Moderators only (and admins, of course):

$xf.visitor.is_moderator

Here’s an example:

– T.O.C. –


7.2. List users with unconfirmed emails

I wanted to quickly list users with unconfirmed emails – so I can check and delete those who’ve been unconfirmed for month(s), or try emailing them first to see what the problem is.

After some playing with the member searh options, I figured out that this code will list users with unconfirmed emails, sorted by their registration dates:

https://www.example.com/admin.php?users/list&criteria[user_state][0]=email_confirm&order=register_date

Replace the “https://www.example.com” with your domain & forum path.

I combined this with the custom menu described in section 7.1.

This way, any moderators (and admins) can quickly check it out.

How to figure this out (the query parameters)?

I went to user search:
Users -> Search for users

There, I set the search parameters. If the search returns more than one result, then you can click on the option “Sort by: Username” at the top of the search results. Whichever option you choose (even if you use the Username), your browser’s address bar will show the link along with all the search results.

If a search has only one, or no results, then you won’t get the “Sort by:” option, and won’t get to see the search query used.

Here is the code to list “Discouraged users:”

https://www.example.com/admin.php?users/list&criteria[Option][is_discouraged]=1&order=last_activity

– T.O.C. –


7.3. Custom CSS

After having updated to XenForo 2.3.X version, I didn’t like the way Google search box text looks like when using the dark mode.

So, to try and fix that, I went to:
Appearance -> Styles -> My_Style -> Templates

There, I searched for the “extra.less” template (that one should be used for custom CSS as far as I know), and added this code:

/* Customizing the search input text colour */
input.gsc-input {
    color: #000000;
}

I also wanted to change the search suggestions font colour (the ones that pop below when you start typing). This is the code I used for that:

/* Customizing the suggestions text colour */
.gssb_c .gssb_e {
    color: #000000;
}

/* Customizing the suggestions hover colour */
.gssb_c .gssb_e:hover {
    color: #00000F;
}

I also wanted to customize the widget font sizes:

/* Customizing widget font size */

.p-body-sidebar .block-footer,
.p-body-sidebar .block-minorHeader {
    font-size: 16px; /* Adjust as optimal */
	font-weight: bold; /* Make the title stand out */
}

.p-body-sidebar .block-container ul {
    font-size: 14px; /* Adjust as optimal */
}

.p-body-sidebar .contentRow-main--close > div:last-child {
    font-size: 14px; /* Adjust as optimal */
}

– T.O.C. –


7.4. Scroll progress bar on top

After having made a visible article scroll progress bar on WordPress, I decided to do the same for my XenForo forum. 🙂

In the XenForo admin panel, I went to
Appearance -> Templates
extra.less

/* BEGIN BikeGremlin custom scroll progress bar */

#scrollProgressBar {
  position: fixed;
  top: 0;
  left: 0;
  width: 0%;
  height: 7px;
  background-color: #9b2fc9; /* Purple color */
  z-index: 99999;
}

/* END BikeGremlin custom scroll progress bar */

Then, I edited the PAGE_CONTAINER template. Added the following code just after the opening “<body” tag:

<!-- BEGIN BikeGremlin custom scroll progress bar 1/2 -->

<div id="scrollProgressBar"></div>

<!-- END BikeGremlin custom scroll progress bar 1/2 -->

NOTE / digression:
XenForo recommends using this format for adding comments to your code:

<xf:comment>BikeGremlin's comment here</xf:comment>

<!-- However, for easier readability
 (when using syntax highlighting),
 I prefer using the standard HTML comments,
 as shown in this very comment. -->

Let’s move on. In that same template, I added this before the closing “</body” tag:

<!-- BEGIN BikeGremlin custom scroll progress bar 2/2 -->

<script>
  document.addEventListener("scroll", function() {
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
    var docHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
    var scrollPercent = (scrollTop / docHeight) * 100;

    document.getElementById("scrollProgressBar").style.width = scrollPercent + "%";
  });
</script>

<!-- END BikeGremlin custom scroll progress bar 2/2 -->

You can check it out, here: 🙂
https://www.bikegremlin.net/

– T.O.C. –


7.5. Registration form custom text

I wanted to add some text discouraging users from registering with a throwaway email. I went to:

Appearance -> Templates
register_form

There, I found the email section, and added my custom code:

<xf:macro id="register_macros::email_row"
				arg-fieldName="{{ $regForm.getFieldName('email') }}"
				arg-value="{$fields.email}" />

<!-- BEGIN BikeGremlin custom email notification -->

<!-- Adding a brief explanation about email privacy and usage. -->
<xf:formrow>
    <span>
        Your email address is kept private and will not be used for spam.
        We only use it to contact you if necessary or to help you reset your password.
        Please provide a valid email.
        <a href="https://www.bikegremlin.net/threads/forum-rules-and-faq.382/#post-1651" target="_blank">More info</a>.
    </span>
</xf:formrow>

<!-- END BikeGremlin custom email notification -->

			<xf:comment>Spam catcher field</xf:comment>
			<xf:if is="{{ rand(0, 2) == 1 }}">
				<xf:textboxrow name="email" value="" type="email" autocomplete="off" rowclass="formRow--limited"
					maxlength="{{ max_length($xf.visitor, 'email') }}"
					label="{{ phrase('email') }}"
					explain="{{ phrase('please_leave_this_field_blank') }}" />
			</xf:if>

I used “span” instead of a new paragraph (“p”) to avoid having a huge spacing/gap. It worked OK. 🙂

If you wish to have the text look like the other explanatory text on that page (not stand out), you could use the same, already defined, CSS styling, like this:

<!-- BEGIN BikeGremlin custom email notification -->

<!-- Adding a brief explanation about email privacy and usage. -->
<xf:formrow>
    <div class="formRow-explain">
        Your email address is kept private and will not be used for spam.
        We only use it to contact you if necessary or to help you reset your password.
        Please provide a valid email.
        <a href="https://www.bikegremlin.net/threads/forum-rules-and-faq.382/#post-1651" target="_blank">More info</a>.
    </div>
</xf:formrow>

<!-- END BikeGremlin custom email notification -->

– T.O.C. –


8. Google AdSense and GDPR

Here is the relevant XenForo community discussion on GDPR & cookies.

Here are my notes on this – still unconfirmed as I’m waiting for my XenForo domain to be approved for AdSense.
Update, December 2023:
BikeGremlin forum has been approved for AdSense, and I can confirm that the below-described stuff actually works. 🙂

You can (and should) enable AutoAds for your XenForo domain. Then, you can use Google’s own cookie consent service – so you don’t have to pay for a separate service just for that.

My article about WordPress AdSense integration explains how to enable AdSense Auto ads (in section/chapter 3), and how to enable AdSense GDPR & cookie consent popups (section 4).

You can disable any other Auto ads options if you wish to, so you can manually place ads where you wish, and just harness the AdSense cookie consent options.

To add Auto ads code to your forum – use the same method as for adding favicon code to the header, explained in chapter 3.10.

The below-explained method also works, but technically it doesn’t add the code to the <head> section.

  • Alternative method BEGIN

Setup -> Advertising -> + Add advertisement

Choose the option “Container header” for the position and copy/paste your AdSense auto ads code there:

The code example (replace the “XXXXXX” with your AdSense publisher number for it to work on your forum):

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXXXXX"
     crossorigin="anonymous"></script>

The display criteria lets you configure the auto ads to be removed for any logged in members, or for the members of certain user groups (haven’t tested this either, still waiting for AdSense approval).

  • Alternative method END

Now, here is the code for the AdSense GDPR cookie revocation, which should be on your privacy policy page:

<a href=”javascript:googlefc.callbackQueue.push(googlefc.showRevocationMessage)”>Click here to revoke your choice</a>.

Yet to figure out and test a CPRA cookie revocation link/code.

To place the ads manually, what I did was:

Created an AdSense ad format and copied its code for manual placement (how to create AdSense units and get the code for manual placement).

Then, in the XenForo admin:

Appearance -> Widgets -> + Add widget

Copy/pasting the code in the “Template” section of the new widget (which I named “Adverts”).

Here is the example from my forum, containing a link to my patreon support, a list of forums I recommend, a header that says “Adverts” and the AdSense code for a vertical manually placed advert (replace the “XXXXXXX” and “NNNNN” with your AdSense code to make it work for your forum, of course):

<hr />
<p>
<a title="BikeGremlin Patreon support" href="https://www.patreon.com/bikegremlin" target="_blank">
<strong>Help BikeGremlin stay online</strong></a> with a Patreon donation:
<br />
<form action="https://www.patreon.com/bikegremlin"><input type="submit" value="Support BikeGremlin" /></form>
</p>

<hr />
<p>
<a title="Bike Forums .net" href="https://www.bikeforums.net/" target="_blank"> <strong>BikeForums.net</strong></a> is the best cycling-related forum in the world!
<br />
<img src="https://www.bikegremlin.net/bg-images/bikeforums-net-200x79.png" alt="Bike Forums .net" width="200" height="79" />
<br />
<em><a title="2Bike.rs Forum" href="https://www.2bike.rs/forum/" target="_blank">
<strong>2bike.rs</strong></a> je najbolji biciklistički forum na srpskohrvatskom</em>
</p>

<hr />
<p>
<a title="LowEndSpirit .com" href="https://lowendspirit.com/" target="_blank"> <strong>LowEndSpirit.com</strong></a> is a good forum for IT-enthusiasts on a budget (web-hosting, networks, computers...).
<br />
<img src="https://www.bikegremlin.net/bg-images/lowendspirit-com-200x33.png" alt="LowEndSpirit .com" width="200" height="33" />
</p>

<hr />

<h3 class="block-minorHeader">Adverts</h3>

<!-- io-text-display-vertical -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-XXXXXXXXXXXXX"
     data-ad-slot="NNNNNNNN"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>

<hr />


– T.O.C. –

8.1. AdSense breaking layout fix

8.1.1. In-article ad problems

Update:
The solution described below is a hit-and-miss. Works for some posts, but not for all. So, I have decided to disable all in-content ad formats, including the “Banner ads” (the last picture in this chapter shows the in-page ad options settings).

Based on my experience, on desktop, AdSense will try to insert adverts into posts where URLs are embedded. That is: where users didn’t manually click on the URL adding option in the editor, but just copy/pasted a link (or just wrote a link).


To fix that, you must disable the “Multiplex ads” (apparently, they are as bad as the cinema/theatre design with the same name 🙂 ).

The option to disable this is in:
Your ad settings -> In-page formats.

So, click on the edit pencil in your AdSense “Ads” menu:


Click on the “In-page formats” option:


Uncheck the “Multiplex ads” checkbox:


– T.O.C. –


8.1.2. Anchor ads on desktop problem

Another problem with XenForo and AdSense on desktop computers: the anchor ads (those pinned to the bottom of the screen) cover the navigation arrows, so they aren’t visible (nor clickable).

To fix this, you can disable the anchor ads on desktop:
Ad settings -> Overlay formats ->
uncheck the “Turn off anchor ads on screens wider than 1000px, like desktop” checkbox.

– T.O.C. –


8.1.3. AdSense & XenForo problems conclusion

Both Google and XenForo are making money from people who run forums with AdSense. However, for any troubleshooting, you are on your own.

It’s practically impossible to talk to a human from Google’s support (does that really even exist for us mere mortals?). As far as XenForo is concerned, AdSense is a third party software so “all works on our end” (they didn’t say those words, but that’s what it boils down to).

This is the typcial “Catch 22” problem. You can’t really blame any of the companies (it certainly won’t help you – LOL), but you’re still on your own and basically fucked (well, not completely – as I’ve explained, you can disable the ads… and your revenue). 🙂

– T.O.C. –


9. Updating XenForo

Compared to most other forum software I’ve played with, XenForo update I did was very easy.

I got a notice in my admin dashboard that a newer version is out – with a button to click and update it. Here’s what I did, step-by-step:

  • Made a staging forum install with the same setup, and did the update on staging first, to confirm it’s all good (then just repeated the process on the production forum install).
    – Had that from the start for testing other customizations.
  • Checked to see that the forum is running the latest recommended PHP version for the current forum version (not for the update).
    – In this case, it was PHP 8.0 for the XenForo 2.2.14 version.
  • Setup -> Options -> Board active -> de-checked the “Board is active” checkbox.
    – Visitors can’t read or write, they just see the notice I set there.
  • Click on the update button and wait for the update to finish.

Now, before I could re-check the “Board is active” checkbox, I had some custom code to fix:

Appearance -> Outdated templates

XenForo outdated template warning
XenForo outdated template warning


There, I could click on my old template to “merge” it with the new template version.

Xenforo outdated template merge
Xenforo outdated template merge


The picture above shows the difference (the custom code I had added) between the old and the new template. I could just click the merge button to let XenForo add the code to the new template.

  • Then, I set the PHP version to the latest recommended for the new XenForo version.
    – PHP 8.2 for the XenForo 2.2.15 version.
  • Finally, I checked the forum admin area and the hosting server for any error logs.

All that was left to do was to re-check the “Board is active” checkbox and confirm it’s all good (then, repeat the process I did on staging in the production version).

July 2024 update:

xenForo 2.3 update specifics

– T.O.C. –


Last updated:


Originally published:




Please use the BikeGremlin.net forum for any comments or questions.

If you've found any errors or lacking information in the article(s) - please let me know by commenting on the BikeGremlin forum.
You can comment anonymously (by registering with any name/nickname), but I think it is good to publicly document all the article additions (and especially corrections) - even if their author chooses to remain anonymous.

Tools and other products that I use (and can recommend)

TOC
Skip to content