1

I have content on my site that can't be shown in some countries and requires a basic level of geo-targeting, based on the users profile and not by any form of IP geo-targeting.

I have set up an address field on the users profile with country and created a matrix block with a geo-targeting toggle (lightswitch field) for my entries. Then I'm using the below code to:

  1. Show all entries to logged out users (as we do not know their country at this point)
  2. Only show content with no geo-targeting or where the users country matches a country code of geo-targeted content.

    {% set category = craft.categories() .all() %}

{% set params = { section: 'articlesWhitepapers', typeId: 'not 7', relatedTo: category } %}

    {% set user = user is defined ? user : currentUser  %}

    {% set recentPosts = craft.entries(params)
    .with([ ['companyName.companyLogo', { kind: 'image' }, { withTransforms: ['featuredImage'] }], 'companyName',['author.userPicture', { kind: 'image' }, { withTransforms: ['featuredImage'] }]])
    .orderBy('RAND()')
    .limit(2)
    .all()
    %}
    {# Fetch the entries #}
    {% set entries = recentPosts %}


    {% for entry in entries %}
    {% set relatedCompany = entry.companyName? entry.companyName[0] : null %} 

        {% if craft.app.user.isGuest %}
        {# Show Everything Regardless #}

        {% include "home/_main-feat" %}

        {% else %}

        {# Check Geo Targeting #}

            {% for block in entry.addArticlePaper %}
            {# get the matrix block by type #}
                {% if block.type == "addArticleOrPaper" %}
                    {% if block.geoTargetContent %}

                        {% for country in block.orAddCustomGeoTargeting %}
                        {% set country = country.value %}

                        {# use the variable to filter the entries #}
                            {% if country == user.location.countryCode  %}

                            {% include "home/_main-feat" %}

                            {% endif %}

                        {% endfor %}

                    {% else %}

                    {% include "home/_main-feat" %}

                    {% endif %}
                {% endif %}
            {% endfor %}
        {% endif %}

 {% endfor %}

This is working great and the correct content is displayed. The problem is I always want to show two pieces of content and currently it is checking the limited results and returning either 0, 1 or 2 pieces of content as its using the if logic against only two results. How would I restructure the above to continue to allow my geo-targeting to work correctly whilst ensuring there are always two pieces of content shown? I have tried a few different ways but no luck so far!

many thanks in advance!!

1

You can restructure your code in two different ways here. But firstly let's see what's the issue with your current implementation. Currently you always fetch 2 entries with your entry query (assuming you have at least 2 entries in total). After that you even filter them further according to the user login status and the use country. This way you'll always end up with 2 or less entries remaining. What you want is always exactly 2 entries.

A) Build your query with the user country în mind. You may have a switch statement to build a query with the country filter and one without the country filter. If it's hard to bake the country into the entry query you could B) fetch all entries of that section and then filter them down to the country and count you want to have. (This could have performance caveats depending on how many entries you have. You may want to cache the query results. But watch out when caching user specific queries. You have to use unique caching keys otherwise user A could see the content of user B.)

I can't show you an exact implementation of the query with country because it's not totally clear to me what's going on in your sections and fields. You may explain the articlesWhitepapers section further.

| improve this answer | |
  • Thanks that makes sense as to what the issue is. I have 10k entries to search through and content updated daily so I think option A may be best. I did think about including it into the query but was unsure how to add matrix fields to the query? Any pointers? I know you can filter by .fieldName ('value') but don't think this works with Matrix? – Chrisl2310 Apr 20 at 15:11
  • Can you explain how the entry type with the matrix and the country field looks like? Then we could maybe find a decent query. – Johannes Apr 20 at 15:14
  • Sure. So there is entry with a matrix field called addArticlePaper. Within that is one matrix block called addArticlePaper as well with three fields: articleContent (A Redactor field used in the home/_main-feat include (which works fine), geoTargetContent (a light switch field), and orAddCustomGeoTargeting (A multi-select field with all country names as labels and country codes as values). – Chrisl2310 Apr 20 at 16:58
  • On my users I have an address field which uses country code also. So I want to show 2 entries and check if the lightswicth is active. If so only show entries that match the orAddCustomGeoTargeting with user.location.countryCode or that have the lightswitch disabled. Does that help? Let me know if you need more. Really appreciate your help! – Chrisl2310 Apr 20 at 17:01
  • I see, seems to me that this is almost not doable with entry queries. Are you able to restructure your fields so that the geo target information is a non-matrix field of an entry? – Johannes Apr 21 at 12:03
1

I managed to resolve thanks to For loop, if statement, then limit

I added the matchCount and find() sugestions instead and works like a dream!

Thanks for your help though!

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.