Total number of topics / Topics par month on the category page

I used the search function, but I didn’t find any information on that though I’m sure this have been discussed before…

When I’m logged in on my forum (as an admin), here’s how the category page appears:

As a newly registered user, or as a guest, here’s how it appears:

Why is the Topics column content different? Is it possible to have the same content in both cases? How do I choose what I show here?

3 Likes

The short answer is that you - as an admin - have a different category list. As an admin, you have access to private categories. I say admin here to keep it simple, but this also applies to regular users that have access to private categories. So, the total number of categories on your list is higher. Note that I’m only talking about categories, not subcategories. You can ignore subcategories for now.

So, how does this relate to whether Discourse shows you 2 / week or 17 / month or 4.4k?

It is designed to be an indication of activity and, to make it more relevant, it takes into account the total number of categories you have access to.

So how does all of this magic work? Let’s start with some basic information that Discourse stores for each category. Each category has these four properties:

topics_day: 12
topics_month: 95
topics_week: 53
topics_year: 874
topics_all_time: 13982

Each represents the number of new topics created in the category or in one of its subcategories within that timeframe. Let’s ignore the day and year timeframes because they’re irrelevant here.

Let’s look at some code:

discourse/category-list.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

and let’s specifically focus on this part

What’s happening here? Well, we start with the all as a default timeframe. Then we see minCategories

minCategories here is the deciding factor for what I described above. It’s a magic number of sorts. In English, all it does is it takes the number of top-level categories available to you and multiplies it by 0.66

So, let’s say you have 5 categories. We multiply that by 0.66 and we get 7.92

Then, Discourse loops through each category and checks the topics_week property. If it has new topics this week, it’s considered active for the week, and it counts as 1. Discourse then tallies up the number of categories considered active. That number is then compared to 7.92 we got above.

You can see that here

if (filteredCategories.length >= minCategories) {
  statPeriod = period;
  return true;
}

If the number is larger than 7.92 (8 or more active categories this week) Discourse will then show 11 / week next to each category if applicable.

Well, what if the number of weekly active categories is lower than 7.92? Discourse will then check the same but with monthly activity.

If the number is larger than 7.92 (8 or more active categories this month) Discourse will then show 22 / month next to each of those categories if applicable.

If neither the weekly or monthly number of active categories is larger than 7.92, Discourse will fall back to the default period of all and show the topics_all_time number or 4.4k like in your screenshot.

Note: Besides the week/month timeframes, if applicable, the total or all is always shown on mobile.

So, let’s try and figure out the issue in your post. A new user sees 22 / month and you as an admin see 4.4k, what gives?

Well, remember this?

The short answer is that you - as an admin - have a different category list. As an admin, you have access to private categories.

So, let’s do some math…

Your site has 7 top-level categories visible to our example new user. So the magic number is

7 * 0.66 = 4.62

In other words, you need to have 5 categories with new topics this week in order for Discourse to show 11 / week. This is not the case on your site since you only have 4 that match the criteria - remember, it’s new topics, not replies.

So, Discourse then checks monthly activity, and in your case, you have 6 categories that have had new topics this month. 6 is larger than 4.62 so, our example user sees 4 / month like in your screenshot.

Now, let’s do some math for you as an admin. I don’t know how many private categories you have but let’s assume that you have 4 private categories. In that case, the total number would be 11 categories, and the magic number would be

11 * 0.66 = 7.26

So for you to see 11 / week, you would need at least 8 categories with new topics this week. If not, it will fall back to monthly activity, and you would need at least 8 categories with new topics this month to see 4 / month. If neither of those applies, you’d then get 4.4k like in your admin screenshot.

With that said, the magic number in Discourse - 0.66 - seems a bit high and might benefit from some reduction to accommodate for sites with a large number of moderately-active categories. 40% of site categories being active is still pretty decent. You can also try your luck and ask for a site setting to control that in a #feature topic.

Short of that, you can bypass all of this in a theme component. Something like this in the common header tab of your theme.

<script type="text/discourse-plugin" version="0.8">
  const { on } = require("discourse-common/utils/decorators");
  const { number } = require("discourse/lib/formatter");
  const I18n = require("I18n").default;

  // category is considered active if it had at least this many topics this week
  const WEEK_THROSHOLD = 2;

  api.modifyClass("component:parent-category-row", {
    pluginId: "category-activity-indicator",
    @on("didReceiveAttrs")
    setCategoryActivityStats() {
      const category = this.category;

      if (category.topics_week < WEEK_THROSHOLD) {
        return;
      }

      const statPeriod = "week";
      const stat = category[`topics_${statPeriod}`];
      const unit = I18n.t(`categories.topic_stat_unit.${statPeriod}`);

      category.setProperties({
        pickAll: false,
        stat: I18n.t("categories.topic_stat", {
          count: stat,
          number: `<span class="value">${number(stat)}</span>`,
          unit: `<span class="unit">${unit}</span>`,
        }),
        statTitle: I18n.t(`categories.topic_stat_sentence_${statPeriod}`, {
          count: stat,
        }),
      });
    },
  });
</script>

The only thing you need to change is WEEK_THROSHOLD to the number of new topics created this week in a category at which it is considered active. The rest should just work.

6 Likes

Thank you for the above code, but it seems to work only on categories with up to max_category_nesting = 2 level.

Right now this code works on:

Parent
Parent > Sub

Not working for me with:

Grandparent > Parent > Sub

It does not break anything, it just gets applied up to default nesting (2) categories it seems.

Is there a way to modify it so it also works on max_category_nesting = 3?

Thanks!