There are lots of situations in which you need to run a series of microsites for your business or organisation — running a marketing campaign; launching a new product or service; promoting an event; and so on. When you’re with Drupal, though, what options do you have for running your microsites? In this article I review and evaluate the options in Drupal 8, make a recommendation and build a proof of concept.
So, I want to run some microsites …
A client brought me an interesting problem recently, something they need to solve for their production Drupal site. They are an international humanitarian agency who, alongside their main production website, want to run some microsites for a number of their public campaigns. Although they could run them on the main site, they’ve found too many limitations in trying to do that. Campaign teams, frustrated with the lack of flexibility and slow protocols for getting changes made to support their bespoke needs, have often gone off with their small budget and dynamic team to create something quick that fits their campaign with Squarespace or Wordpress or something.
That made the campaigners really happy. But, when the campaign or event lapsed, the campaign site quickly got out of date and went unloved, the campaign team moved on and no-one could remember how to log into the system and it became abandoned.
Hearing this story was so familiar — the same thing often happened when I was a senior developer at Oxfam International.
So, they said, could something be done about it? What, if anything, could be done with Drupal to support campaigners get their microsites running? What would give them the fast, bespoke solution to their microsite problems, whilst still keeping all the content well-managed and being able to share that content with the main site or other microsites?
I scratched my chin and had a think.
How about Drupal multisites?
Since some of its earliest versions, Drupal has included a feature for multi-sites — running several sites from a single codebase installation, sharing the core system, contributed and custom modules and themes. Each multisite has its own database, its own settings and configuration, its own content, and so on. Ideally, it also means updates can be done once.
So, multisites could be an option. Many people find them to be a real workhorse for their context, and often they are right on the money.
Why use multisites
The Drupal.org documentation for multisites includes a simple rule-of-thumb for when to multisite:
As a general rule on whether to use multisite installs or not you can say:
- If the sites are similar in functionality (use same modules or use the same drupal distribution) do it.
- If the functionality is different don’t use multisite.
(DrupalCon Austin [June 2014] held a interesting debate on Drupal multi-sites, its pros and cons, gotchas and suggestions, which is available on YouTube.)
There’s several compelling reasons to use them.
First, having a single codebase to maintain is a huge plus. Forked codebases can soon become orphaned, and unloved codebases become fraught with problems too quickly.
Second, multisites often mean there is also a single hosting platform to maintain, which is also a major advantage.
That can often mean, thirdly, that multisite installations can make better use of resources, both the server resources and financial, personnel or other physical resources. For example, since multi-sites share the same core and modules, that code need only go into the opcode cache once, saving server resources.
Caveat: is the end of multisites support on the horizon?
It should be noted that a proposal has been made to deprecate support for multisites in Drupal, with a view to removing it in the future.
The basic argument for this is that it’s an ‘old skool’ way of thinking about handling multiple sites. Git and Composer create practices and codebase structures that point in other directions.
The modern approach to multi-site is: git — Same code, different sites. Under your control. And well-maintainable.
There are a number of positive reactions to that proposal, which are variations on a theme:
+1. Multisite is a historical oddity at this point and I’d never tell anyone to use it.
But there are many more negative reactions, which largely go along these sorts of lines:
-1. Multisite has been a workhorse for a ton of Drupal sites and is well established in our code.
In that light, Drupal’s multi-site feature is likely to stay around for a while.
Classic problems with Drupal multisites …
It’s not all a bed of roses, though. There are some classic sticking points when working with Drupal multisites.
First off, handling traffic. One site’s traffic spike can be another site’s nightmare when the hosting resources are all hogged by The New York Times tweeting a link to a page on a site of yours; one site’s ‘BEST DAY EVA!’ can be the worst of times for all the rest.
The load on your database server may also be an issue. Multisites often use a single database server, and heavy load or slow queries in one DB can impact the performance of others. This might even be caused in the normal running of your Drupal sites, such as when running cron.
Running updates often causes headaches. When you update code, you’re updating all your sites at once. That means the updates are deployed, well, instantly across all your sites, but if they need update processes to run, such as updating the database, that can throw unexpected problems or errors.
And the worst of the worst: a small piece of poorly written, inadequately reviewed or tested code mysteriously jumps itself onto production — that never happens, right? No one ever lets that happen, do they? *ahem* — and takes down all your sites at once! It’s just an urban myth, a story to scare the children with at night, right? Never happens.
… and how to mitigate them
There are of course a number of ways to foresee these things happening and be ready for them.
On the performance questions, with smaller demands you can just ride it out — sites on the same hosting platform are fairly tolerant of resources being shared around, and the spare capacity is there for times just like there.
For larger performance demands, handling the pressure is a challenge in any hosting set-up, dedicated hosting just as much as shared. With modern cloud infrastructure, the option of scaling up your infrastructure or spinning up a new cluster when you’re experiencing ongoing heavy demand is much easier than in the past, especially if you plan for it as a possibility.
The next set of mitigations are all about best practice.
For starters, test, test, test. Don’t let any code onto production that hasn’t been tested thoroughly.
Have a solid release process that you always follow. If possible, include dev, staging and quality assurance stages. This should give you lots of points to catch things before they’re released onto your production sites.
Automate all the things. There are lots of ways of automating things to ensure they run consistently and quickly too, from shell scripts up to continuous integration tools. Use them.
And finally, be intelligent. With code changes that need database updates, for example, design your code so that it can be deployed to handle an interval before the database is updated. Or, with important but more volatile updates, be smart about choosing the time of day and week that you deploy it. Don’t ever push something out at 5pm on a Friday afternoon if you want to stay friends with your colleagues, your customers and your family.
Well, yes, in short, kinda. You could run microsites using Drupal’s multi-site feature. Things would work fine, though of course you’d have all the problems described above and have to take the mitigating actions.
However, it wouldn’t solve all the needs described above without some smart thinking. Plus, I’d suggest that you would also have some other problems to solve.
First, multisites all use different databases (sharing databases and tables is possible with Drupal multisites, but really unadvisable!) so the need of a single place for managing all the site content wouldn’t really be satisfied. The way around that would involve using web services, posting and pulling content from one site to another.
Neither would we have a unified search. There are fairly straightforward ways around that, using a tool like Apache Solr. The sites would need to share an index, with each document in the index including a site field, and there’s a contrib module that does that already (although no Drupal 8 version yet).
Lastly, and maybe more pertinently, you would still have all the ‘Drupalisms’ to live with. First of those is the visual design layer, the public user’s interface for the sites, what gets called the ‘theme layer’ in Drupal lingo. Many designers really dislike Drupal’s theme layer, and would really prefer to work with the pure frontend tools they use in other contexts. Drupal 8 has made major strides forward with the theme layer so it’s not as tough for designers as it once was, it’s true, but many (most?) frontend specialists would still rather not work with it.
Some consider influential Drupal figures consider multisites as ‘not enterprise grade’ and opinions like that are worth considering if your situation is enterprise scale.
Other approaches with Drupal
There are a few other ways of supporting microsites with Drupal that might be worth considering.
Domain Access
The Domain Access project was created to support just this kind of functionality. The project overview says as much:
The Domain Access project is a suite of modules that provide tools for running a group of affiliated sites from one Drupal installation and a single shared database. The module allows you to share users, content, and configurations across a group of sites.
This might work. However, there are many of the same problems with core multisites described above with this approach, with one additional one: everything in one database.
Our experience of using it, and this is echoed by others too, is that with a small number of very similar sites Domain Access can work well. With a larger number of fairly different sites, it’s a right pain and actually makes things quite difficult, requiring lots of complicated custom code.
Organic Groups
The Organic Groups suite of modules could be a solution for building microsites. The project allows users to create a ‘group’ within a Drupal site. The group can have its own users, admins, content, menus, even its own visual design. However, it would need every microsite to sit internally, within the main site, so does not solve the need to supporting external sites on their own domain. So, not really the perfect fit.
Best practice: with Git
I quoted above from @sun in the discussion on deprecating multisite support about the modern best practice:
The modern approach to multi-site is: git — Same code, different sites. Under your control. And well-maintainable.
This is certainly my standard recommendation and will give you many advantages: independence of sites for performance, design, etc; single codebase to maintain (though you’ll have a challenge developing and maintaining the variations you’ll want or need for each microsite); better control over updates; and so on.
You might even look writing an install profile to make a full distribution, though with Drupal 8 there is less of a need to do this. With Drupal 8, I’d advocate that you use Drupal Composer to build your site and just export your full site config into your repo (being careful to remove any sensitive settings from the repo with your .gitignore file).
Or you might also consider using Aegir to manage your multiple sites — use Drupal to deploy Drupal, if that’s not too much Inception.
Microsites and Drupal
So if multisites could work but would be a bit of a pain, the other Drupal approaches are even less appealing, and you’d rather not keep multiplying Drupal installations, how else could we do microsites with Drupal?
Well, there are two major moves in modern web development that might help here: RESTful web services, and decoupled CMS architectures (a.k.a. ‘headless’ CMS). My proposal for managing microsites in Drupal 8 depends on both these ideas:
Treat your Drupal site as a pure content management system (CMS) — a content hub that allows authors, editors and administrators to create, update and manage the content for which they’re responsible, but doesn’t have any meaningful frontend presentation layer to it.
Present the data of the content in the hub CMS via a RESTful API.
Implement a separate frontend for the visual presentation layer that communicates with the content hub CMS via the API.
There need be no limit to the number of frontends that use the CMS’s API (though practically you may limit access with firewalls, CORS or some other means) so you could power a primary public site, other sub-sites, native mobile apps or even another CMS or two, each potentially with their own visual design. The limit is your own imagination and situation.
RESTful web services and Drupal 8
A new addition to Drupal 8 is the RESTful Web Services API. REST resources can be exposed to allow other things to talk to/consume/feed a Drupal site. Many core entities have REST resources, but it is also fairly easy to build custom REST resources. (There a number of interesting web services contrib projects that are worth considering, such as the GraphQL project that presents a GraphQL schema, and the RELAXed Web Services project that extends the core REST resources.)
Design your own web services API
The freedom to build custom REST resources in Drupal 8 allows a lot of freedom in designing a RESTful API.
In a forthcoming blog post I’ll write in more about designing an API. For now, all I need to say is you need to actually design your API. Don’t simply use the out-of-the-box Drupal core REST resources — think about the RESTful API that would best serve the frontend you want to have.
My heartfelt recommendation is you do this, designing your API, using the skills of those who’re best at designing things — your designers. They understand best what your users want to do on your sites, will be able to describe what data they want for the frontend (content with/without markup, etc.) and help you design the API that is most appropriate to your needs.
There are some API design golden rules and best practices that you should consider. Also I’d recommend using an API design tool like Apiary.io or Swagger.io. They’re invaluable for many reasons, not least of which is the lovely documentation they generate and mock data servers they include that can help frontend devs get going quickly.
Decoupled frontend
With the content hub now presenting the managed content as RESTful data, we just need a standalone frontend system to present your website to your users: one for your primary site, and one for each of your microsites. Your frontend specialists can then work with the right tools for the task, then.
There are several advantages to consciously uncoupling the content management and the frontend.
Freedom: frontend specialists are free to the implement the user experience with native tools that are built for the job.
Performance: everything in this architecture can be streamlined. The CMS simply presents the content data. The frontend focuses on the display logic.
Experience: the website can respond to users in real time, communicating back and forth with the CMS to give real-time interactions in the browser.
Future proof: it becomes much easier to replace any part of the system as you require, such as redesigning the website without re-building the CMS.
Microsites in Drupal 8
So, how might we do this practically in Drupal 8? Here’s how I tackled it.
First, I thought about designing a quick prototype API that could be used to describe microsites and their content. I used Apiary.io to design it, and you can view the API at docs.campaignmicrosites.apiary.io.
Next, I installed a Drupal 8 instance with Drupal Composer to act as the editors’ content hub and created a ‘Campaign’ content type with some basic fields. This ‘Campaign’ content type is the core of the microsite support. Each Campaign creates a new microsite.
Since in this client’s conundrum the microsites can be internal (i.e. sit within the main public site) or external (i.e. on their own domain or sub-domain) I added two fields:
external site (true/false boolean)
external URL (URL)
These will allow requests for the microsite from within the main site to be redirected to the external URL, and will help in constructing the right data in the API resources.
I also adapted the core Article content to include an entity reference to a ‘Campaign’ node, and included a taxonomy reference field to indicate the ‘type’ of article — news; FAQ; info; etc.
The next task was to create the REST resources that matched the APIs I’d designed. For this I created a custom module, campaign_api, and created four classes, one for each of the API resource collections I’d designed, in the `Drupal\campaign_api\Plugin\rest\resource` namespace.
The quick and dirty code for the `get` method on the Campaigns resource looks like this:
Enable those resources (by clicking stuff with REST UI module installed, if you like), of course, and then create some content to populate the responses — one campaign called ‘DIY succulents’ and the other ‘Slow-carb cred’ (yep, I used some Hipster Ipsum).
Then you should be able to retrieve your data at the appropriate endpoints. A nice way of doing that is with the free Postman app (there’s a Chrome extension also). Postman makes a request to the endpoints you specify and pretty-prints the response. Marvellous!
The final part is the standalone frontend tool. For this I used React. I used React to build my frontend app, but there’s obviously plenty of other options depending on what the frontend needs to do. React worked for me because I just wanted the view layer, but Angular or Ember could be more appropriate if the frontend needed to be a more substantial app. You’d need to evaluate the frontend options carefully.
I’m not a frontend specialist, so my prototyping code is pretty fugly. Despite that, we’re able to serve two microsites simultaneously on different URLs, with a different theme, just by switching the campaign ID in the API request.
Bingo!
Deploying to production
There’s a few things I might do to deploy this to a production system.
Secure serving
As a good internet citizen, I’d want to put everything on SSL.
Frontend deployment
To deploy the frontend, I’d be looking at options to run the apps on a NodeJS server so that most of the scripts can run server side.
I’d probably want to put an Nginx instance in front of it, for SSL termination, caching static assets and reverse proxy.
Use Drupal multisites ;-P
I think there is actually a neat way of using Drupal’s multi-sites feature here: use a different domain for the RESTful API. For example:
Editorial interface: hub.yourdomain.com
API interface: api.yourdomain.com
Both of these point to your Drupal codebase but you can then handle requests differently on each domain. For example, you might add an authentication provider that checks the domain to give you some access control, so there’s no access to the editorial interface on the API subdomain, and none to the API on the editorial domain.
Caching etc.
This would then allow you to do some smart things with caches and other parts of your hosting stack, offloading much of the pressure on the codebase to the caching architecture and removing the actions of editorial staff from affecting the RESTful API’s performance.
Databases
It might also be possible to configure GET requests to only use a slave database, which could be useful for performance — though may be more hassle than it’s worth. POST, PUT, PATCH and DELETE requests would still need to go to the master.
In summary
This prototype worked really well for me and I was very happy with the results, and it gave me something very interesting to discuss with the client.
The advances made in Drupal 8 to operate with current standard web practices are good news for developers and for web projects big and small. For this prototype, the particular improvements with providing RESTful resources means that I was able to create a decoupled Drupal system to support a main website and unlimited microsites in an amazingly short space of time.
… and something to take away
If you’re interested in following up this thought experiment with my Drupal 8 prototype, I’ve put the code into a repo in GitHub:
ConvivioTeam/Convivio-ContentHub
Just …
… and you’re away.
(My React code is shamefully dirty, so I’m not prepared to share that at moment. ;-) I may tidy it up in the future and share it here.)
Main image: courtesy of Denys Nevozhai/Unsplash. https://unsplash.com/photos/guNIjIuUcgY
Convivio helps organisations to work better for people.
We do this mainly by helping them transform their services using digital tools, but also by spreading new ways of working.
Read our blog: blog.weareconvivio.com
Follow us on twitter: @weareconvivio
Get in touch: hello@weareconvivio.com
Visit our website at weareconvivio.com
Managing Microsites with Drupal 8 was originally published in Convivio on Medium, where people are continuing the conversation by highlighting and responding to this story.