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}
.
b2b
orb2c
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?