I need to have B2B and B2C split. I was thinking to use the same templates and work with conditionals in the templates. it's only for 20% of the content that is different, but still all urls should have a b2c/b2b segment to keep him within the right section

so i need:

  • weburl.com/nl/b2b/product/slug
  • weburl.com/nl/b2c/product/slug
  • weburl.com/nl/b2b/news/slug
  • weburl.com/nl/b2c/news/slug
  • ...

Any idea how i can do that? I'm open for alternatives as well.

Can't figure it out immediately with routes: enter image description here

  • What determines whether an entry belongs to "b2b" or "b2c"? Are they sections, categories, values from a select field or something else? Dec 1, 2015 at 15:29
  • Depends on the section. Products sheets will have some fields that are "double" (eg description for B2B is more technical), but most will be the same. News will have work with a business_category. The product listing will be the same for B2C and B2B etc... Dec 1, 2015 at 15:33
  • Well, if you want to have b2b or b2c as a part of the entries' canonical URLs, I'd definitely recommend building it into the sections' Entry URL Formats somehow. Obviously there are limits to what you can do with Twig in the URL format text input, so you might want to simplify things a little. Mike Pierce's answer below demonstrates how you could do it with a Business Category; why not just add that category field to all entries/sections? Dec 1, 2015 at 15:50

2 Answers 2


Answering this requires clearing up a couple of things:

Basically, all a route does is to tell Craft to load a certain template whenever the current URL matches a certain pattern. On its own, that template will be pretty dumb, and won't know anything about the content that you want to display – unless Craft can match the URL to an entry, in which case the entry variable will be made available to Twig.

In your case, this means that whenever an URL matching the b2b/products/{slug} pattern is requested, Craft will fire up the products/_entry template. However, since there aren't actually any entries matching that URL pattern (the actual entry URLs will look like products/{slug}, without the b2b segment) there won't be an entry variable available in your template. Hence the error message.

For more information about routing and how Craft parses URL requests and makes data available to templates, I recommend reading the official docs on the subject.

To attempt an answer: From your question, its not clear to me if you want /b2b/products/{slug} and /b2c/products/{slug} be the canonical URL formats for your entries, or if you just need the option to browse entries using those routes.

If you want to keep products/{slug} as the canonical URL format, but just need to browse to an entry via the b2b/products/{slug} route, you basically just need to define the entry variable "manually" inside the products/_entry template – i.e. tell Craft which entry you want to display. Put this at the top of your template:

{% set entry = entry is not defined ? craft.entries.section('products').slug(craft.request.lastSegment).first : entry %}

The above code will pull an entry from the Products section, with a slug matching the last segment of the current URL/request, if an entry variable isn't already defined. This means that the template will work for both routed and canonical URLs, and without an extra database hit for the latter.

It's probably a good idea to also add a conditional testing if the entry variable is actually a valid entry, and redirect to the 404 page if not:

{% if not entry|length %}
  {% exit 404 %}
{% endif %}

Keep in mind that with this setup, all entries – no matter if they belong to either B2B or B2C – from the Product section will be available for both the b2b/products/{slug} route and the b2c/products/{slug}. If that's an issue, you can – of course – add some sort of conditional to the template to verify if the current entry corresponds to the URL segment (this would follow the above example):

{% set businessCategorySegment = craft.request.getSegment(1) %}
{% switch businessCategorySegment %}
   {% case 'b2b' %}
       {# Test if entry belongs to B2B, if not - exit 404 #}
   {% case 'b2c' %}
       {# Test if entry belongs to B2C, if not - exit 404 #}
{% endswitch %}

If you need b2b/products/{slug} to be the actual, canonical URL for an entry, I'd recommend to not use routes – build the b2b/b2c segment into the Products section's URL format instead.

To accomplish this, you'll need to make use of Crafts ability to render entry variables (i.e. custom fields or meta data) as part of the URL format. This means that you'll have to have a custom field designating an entry as either B2B or B2C when it is saved. As per Mike Pierce's earlier answer, a Category Field will work well: First you create a category group called Business Group, then add two categories – B2B and B2C (with handles b2b and b2c, respectively), and finally a Category Field with the handle businessCategory. Limit the field to 1 category, and mark it as required when you add it to the Products section's field layout. Finally, you put the following as your section's URL format: {businessCategory|first.slug}/products/{slug}.

  • Epic answer, @mmikkel.
    – Brad Bell
    Dec 1, 2015 at 23:31
  • Epic +1! @mmikkel. Dec 2, 2015 at 10:24

My thoughts would be to use a Category and have that in the URL pattern of the entries.

Something like this:


And then each entry would have the business_category field set to either B2C or B2B.

  • I'm not entirely following. {business_category} is not dependent on what the admin entered but what the user selected in the top navigation or splash page. So the main challange is that it's coherent while he's browsing. Dec 1, 2015 at 16:01
  • Sorry, didn't realise that. Then my answer doesn't apply to your particular case obviously. Dec 2, 2015 at 10:13

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.