Methods for URL Cloaking/Redirecting?

Hey guys,

Trying to find a simple way to cloak/redirect a larger amount of URLs as doing it manually would be quite tedious. I have tried Retour, but it would be very time-consuming to manually set up all the redirects and with the correct language translations as well. I currently have a pages field, and within each page, there is an external_url link field. I tried to set up a redirect.php template and use go(), but I can’t find a way to pass in the external_url variable from another template. Any ideas?

Thanks :slight_smile:

What’s the purpose of the pages field?

If I understand this correctly, then you want to redirect a page to an external url when the external_url field is filled in?

If that is the case, then you might as well add a conditional statement in the header that redirects to this url when the field is filled in.

The pages field lists reviews for external products. For each review I would like to have a “Go to Source” button that would be cloaked/redirected to an external URL and then a button that would say “See Our Review” which would go to the page itself. Is this setup possible?

Ok, that’s different from what I though.

Yes, of course can you show different buttons/links that that link to different location.

From the pages field you get a collection of page objects($page->fieldname()->toPages()), and then have access to all fields in these review pages.

What has this got do do with URL cloaking?

Sorry, I should’ve expanded on that a bit more. The external URL would be cloaked so instead of the full external link address it would be something like domain.com/redirect/review-name. Which would then redirect to the external link.

Ok, in that case I’d create a route for the redirecting with a pattern redirect/(:any) that then redirects there.

And then a page model for reviews that returns this redirect url for the button.

1 Like

I already have the review pages set up, with a field for the external URL, would it be possible to set up the redirect to just use this field? Or would I have to create a separate pages module for the redirects?

Yes, you would use this field in the route that does the redirecting.

I wasn’t talking about a module but a page model, that creates the cloaked URL: https://getkirby.com/docs/guide/templates/page-models

It’s not absolutely necessary, you can create this URL manually, but it’s nicer.

Great, the page model is what I was looking for… for the routing, would it be possible to pull in the field from the panel? So it would look something like this:

in config.php:

   'routes' => [
        [
          'pattern' => '/reviews/(:all)',
          'action'  => function goToRedirect() {
            go(cloakedUrl())
          }
        ]
      ]

and in models/reviews.php

class CloakedLink extends Page {
      public function cloakedUrl() {
        return $this->externalUrl(); //would be coming from panel
      }
    }

Yes, you would try to get the page from your pattern

'routes' => [
        [
          'pattern' => 'redirect/(:all)',
          'action'  => function ($uri) {
            // find the review page
            if ($page = page($uri) ) {
              go($page->externalUrl());
            }

          }
        ]
      ]

This model doesn’t make sense, the name is not correct and you need a model for your Review page, that doesn’t return the external URL but the cloaked URL.

class ReviewPage extends Page {
      
    public function cloakedUrl() {
        return url('redirect/' . $this->id());
    }
}

This model return the URL for the route pattern, you use it for your external button.

The route then does the redirect based on the content of the externalUrl field.

Ok great, I have that all set up in config.php and site/models/review.php. In the front end I currently have this snippet but it is returning empty.

<a href="redirect/<?= $review->cloakedUrl(); ?>">

Should I be retrieving the model link using something else?

Is $review a page of type review?

Yes it is, there is a parent page called “reviews” and then I’m forlooping through the child pages which become $review

Does the snippet itself not return anything or is thehref attribute empty?

Ah figured it out, was simply an issue with the name of the extended page. I had it as ReviewsPage, when it should’ve been ReviewPage. Redirect working as intended now :slight_smile: Thanks for all your help guys. Quick question, will it work okay with translations as well?

Would there be a way to add access to the regular page with this solution? For example, one link would be “Go to Product” which would use the redirect (domain.com/redirect/product-name), and the other would be a “See our Review” which would go to the corresponding child page (domain.com/reviews/product-name). Something like the example below, I’m just not sure how to check for which button is clicked.

public function cloakedUrl() {
      if( //external URL button clicked ) {
        return url('redirect/' . $this->id());
      } else {
        return url($this->url());
      }
  }

Would it be viable to add the redirect/ on the front end and then check if the URL includes it, so maybe something like:

public function cloakedUrl() {
          if(strpos($this->url(), 'redirect') !== true) {
            return url('redirect/' . $this->id());
          } else {
            return url($this->url());
          }
      }

For the standard link, you would just use the url() method, not the cloaked url.

I can’t believe I missed that, such a simple solution, thank you!

Hey guys, this solution is missing the functionality for translations, could something like this work (by setting it in the page model)?

    $language = $kirby->language();
	$lang_code = $language->code();

public function cloakedUrl() {
          return url($lang_code . 'redirect/' . $this->id());
      }

or should it be set in the routes, something along the lines of:

'routes' => [
        [
          'pattern' => 'redirect/(:all)',
          'action'  => function ($uri) {
            if ($page = page($uri) ) {
              go($page->translation()->ref_url());
            }

          }
        ]
      ]