FrontpageBonnier Publications A/S publish magazines in Denmark, Norway, Sweden, Finland and Holland. All the magazines have websites, some of which are quite significant and have a large amount of traffic and reasonable revenue, while others are simple presentation sites. Altogether Bonnier Publications (BP) has more than 40 sites in five different languages.

For many years, BP has used the Java-based CMS Polopoly for all their sites, but this has not been optimal and especially programming the sites was far too slow, even for the smallest adjustments.

During the summer of 2008, BP decided that their CMS technology needed replacing to enable their editorial staff and sales departments to take full advantage of the Internet's dynamic potential. They chose Drupal CMS, and Peytz & Co. was appointed strategic partner and asked to handle the platform migration.

From Java to Drupal

The task was handled in a cooperation between Peytz & Co. and BP’s own technical department, whereby Bonnier’s own developers were at the same time taught Drupal programming. Their developers quickly started playing with Drupal and PHP, some of them even in their spare time, so they were prepared for the new platform. Six months after launch, Bonnier’s own developers were developing larger Drupal sites themselves.

Design and advertisements

Grid based designIt was stressed from the beginning that the task was not to create new individual sites, but only to change the technological platform. It was also a requirement that banner advertisement formats etc. should be standardised. We therefore implemented a common design-grid for all websites that ensured that the required advert formats would fit into all sites, but still allowing each individual sites to have its own unique identity.

In reality it is difficult just to move a site from one technical platform to another. Partly because the design needed to be changed anyway, so it would fit into the new standard grid, but also because pages are built very differently in Drupal. Additionally the CSS and markup needed to be created from scratch. With this in mind it seemed pointless replicating known errors and mistakes. On the other hand the task involved a large number of websites and developing all of them from scratch would require more resources than were assigned.

In practice a great number of compromises were agreed upon, whereby the largest site by far ( was recreated from scratch, while other sites received smaller or larger overhauls.

In connection with the redesign, a number of rules were created for cross promotion and cross-linking (including reusing content) between the individual sites, resulting in the sites to a far greater extent being able to drive traffic to each other in the future.

This case study is based on the website (I Form is Danish and translate to “In Shape”) has received a full makeover, including adjusting the concept and a new design. is published in Denmark, Norway, Sweden and Finland. An online editorial staff of 4 in Denmark handle most of the production. Some articles are translated and reused, but not all. Both Sweden and Finland have local editorial offices.

The development team

The I Form team has consisted of many different people from different companies. Here at Peytz & Co. we participated with four PHP developers(, naxoc, Ralla, andershal), one system administrator(c960657), one HTML/CSS specialist and a project manager. Design inspiration was delivered by Loft 37 and further developed by Bonnier Publication’s own designer. Bonnier contributed with one PHP developer and three editorial staff that handled content. Additionally a process manager from Bonnier kept the project on track and coordinated the functionality needed across the multiple Bonnier sites. The jogging-planner’s HTML and JavaScript was delivered by Fonqi.

Server setup

In addition to Bonnier’s sites, we also develop and host sites on our platform for other customers. Our development environment has been designed to allow developers to access and program many different sites simultaneously, including having multiple programmers working on the same site at the same time. We use CVS and were originally running a standard Multisite with an "all" folder for all the modules shared across sites and a "site" folder for all the site-specific modules. This setup quickly became an obstacle, because we could not maintain any proper overview when updating modules on 50 different sites at the same time.

Peytz Drupal WizardWe faced a dilemma: on the one hand we wanted to be able to work on shared modules regarding daily operations. On the other hand it was very necessary to be able to upgrade modules on different sites independently of each other. We solved this by developing our own tool: Drupal Wizard.

Drupal Wizard

"Drupal Wizard" is a type of package handling system that helps us keep an overview of the CVS tags in our own code and contrib-code. Drupal Wizard thereby keeps the track of which module versions are being used on which sites.
With Drupal Wizard, developers can place the file at the same level as settings.php and then control versions using CVS. In addition to this there are scripts to handle the update of modules on both our development- and live servers.


All our developers work on the same two development servers and basically only require a ssh access. This solution is very flexible and gives new developers an easy start. We have configured our servers so all developers have their own personal area ( The address points to their CVS checkouts for each project/site. Each developer has his or her own database.

In addition to this we have a staging area ( for code that has been checked into CVS. We expect the staging area to be functional, but not necessarily completely developed. The staging area is updated automatically for each CVS commit made by a developer.

The next area is pre-production (, where we manually update the project’s CVS. This is the final level before going live and we therefore only expect code that is fully functional and that fulfils the customer's requirements to be updated.


The site is hosted on a cluster of Web servers that are all behind a reverse proxy. When going online, the PHP code is rsynced to each individual server using a deployment script. A database server with a replications slave is used as a "hot" backup.

Amazon S3

Our fileserver is an Amazon S3. Drupal communicates with the S3 using an in-house developed stream wrapper with a local cache. Private files with HTTP caching are used in the reverse proxy. This setup has required certain local changes in the core Drupal upstream code and a number of changes in the contrib modules:

Data import

Up to now, Bonnier had used the commercial CMS Polopoly versions 8 and 9. Polopoly allows existing data to be exported as XML, but as that data also resides in a MySQL database, we chose to move the whole database to the new Drupal server. At the time it seemed like an easier solution to "simply" take the data from the Polopoly table and to import it into Drupal.

However it later turned out that Polopoly had placed certain data from some articles in a file system rather than in the database. While we couldn’t figure out the reason for this, we could create a set of rules that govern when data would be fetched from the database and when it would be fetched from the file system. It was purely trial and error getting the Polopoly database/file system to function.

The old I Form had more than 3000 articles that had been accumulated over the years. The migration of the articles was also handled semi-automatically, allowing Bonnier to double check the relevance of the articles. They ended up migrating under 50% of the articles and thereby discarded many obsolete articles. This method also resulted in cleaning up the many articles that contained incorrect HTML.

In practice we handled the migration by creating article lists based on the old site structure. The editorial staff clicked on each individual article, that then opened in Drupal's node edit form. The editors checked that the article appeared to be correct and the correct images were linked up. Because we were using Drupal's standard node edit form and had filled out a correct node object, the article was also saved correctly when the editor clicked "save".

Importing jogging routes

I Form has a very successful jogging route planner that visitors have used for many years to create and save around 430.000 Danish and around 50.000 Swedish jogging routes. These routes also needed to be migrated to Drupal, but unlike the articles, we chose to fully automate this process. We created a function that used Drupal's batch functionality. The function migrated 200 routes for each batch job by creating node objects and saving them using the call to save () function. We typically let the programme run overnight, whereby it could migrate around 100.000 routes at a time.

Content types

We have chosen to spread out our content types as much as possible, to give the greatest possible flexibility.


Article node editWe have used standard articles as much as possible across the site. The node types consist of multiple sections that primarily use cck fields for content. Most of the other node types use more or less the same sections as these.

Asides from taxonomy, language selection, menu settings etc., an article also consists of the following:

"Teaser" section

This section contains the fields that are used as a teaser for the article in other areas of the site. You can choose between title, text and image for the teaser - which do not have to be the same as the actual article. In addition a custom text link can be created instead of the default "Read more" text and the user can choose between one of the seven different design colours for the teaser.

Teaser’s data logic first checks whether there is any data in this section. If the teaser section is empty the programme looks in the deck field from the main section. The programme checks for an image in the teaser section first, then the topbox section and finally in the main section.

"Topbox" section

The design allows the possibility of inserting a large image at the top of an article. This image can either be the full width of the design, or have a blue text box on the right hand side. This is controlled by the top box section.

"Main" section

This is the article’s primary fields that contain the main text. The primary text field uses the DME module, that uses defined tags to insert images. Images are also chosen in this section and defined in the CCK node reference.

"Infobox" section

This section contains a text field for the title and a text area for one of the sidebars.

"Related articles" section

TabsIn this section articles with related content can be linked together via a node reference field. The user has the option of adding a title in a simple text field. I Form has decided that there should always be 10 related articles, so in addition to the articles chosen by the journalist, the system will automatically add the remaining articles up to 10 using the Drupal taxonomy system.

"Recommended nodes" section

Nodes can be selected from a node reference list. This is similar to the article reference, but is shown differently in the design. The selected nodes are shown in a list that is similar to the site’s overview pages.

Here one can also select whether an article should be featured in the "Recommended" section in the site’s right column.

"Toolbar" section

The design includes a consistent lilac coloured toolbar at the top of the articles. This bar contains a title, some links and a drop-down menu with additional links. All this information is automatically selected for the article from the category taxonomy. Users have the possibility to override the automatic choices and also to completely remove the Toolbar from the article.


Simple node type with the possibility of implementing a specific form from the calculator module. Each form consists of some custom elements, that when submitted use a customised calculation that gives visitors results for e.g. calorie consumption, alcohol content and BMI figures.


The contest node has three fields. The competition questions are typed into a simple text field that uses predefined syntaxes to allow any number of questions. When the competition is active, this field is interpreted and converted to radio buttons (see the chapter about the Contest module).

There is a "thank you for your participation" field and a field for the terms and conditions of the competition. Unless special conditions apply to a competition, a standard value is used for this field.

One can choose to add a taxonomy word to the node, that corresponds to a permission (as in "yes please, I would like to receive a weekly newsletter".)


A simple node type that allows the implementation of iframes. Parameters like source, width, height, scrollbar etc can be set. This node additionally uses the teaser section and toolbar section.


All images on this site use this node and are implemented as node reference fields. The node is therefore in reality a central image database that allows easy access to reuse images. The actual images are uploaded using the ImageField module. The image can be tagged with a title, description and taxonomies.


Route plannerAll jogging routes created via the jogging route planner use this node. The actual data collection of route data is not handled via the usual node edit form, but instead via a custom form. Data is thereafter compiled as a node object and saved in the same way as when importing/migrating data.

Multiple users can add the same route to their profile. This is handled by a user reference field on the node.


This is primarily used for static articles, like for example articles about I Form, advertising information etc. The advantage of this type of article is that we can exclude advertisements from the article and that the nodes do not appear in any type of lists


This type is used to tease content that is not a node. Apart from the fields described in the teaser section, this type also includes a CCK link field to internal or external links.


The test module differs from the competition module by allowing test questions to span multiple pages. By pages we mean that having answered the first questions, the user needs to click on "next page" to continue the test.

As in the competition module, the test module also has a field that allows users to type in an unlimited number of questions with a predefined syntax, but unlike the competition module there are no right and wrong answers. Instead each question is rewarded with a number of points that the author of the test added together with the questions on the syntax field. When the visitor completes the test the number of points are added together.

Test also has a field to attach test result nodes. The test result node allows any number of test results to be attached - each with a point range. If the visitor scores for example 12 points and there is a test result node with the point range 0-20 attached, this node will be shown to the visitor as the final step of the test.

Test/Questionnaire result

A test result is very similar to an ordinary article. As described in the previous paragraph about test node types, it shows the visitor relevant information based on his or her test answers. The reason that we do not use an ordinary article to present the test results, is that it is far easier to filter out a node type from views, search results and other lists.

User registration

Bonnier currently promote their sites individually, but despite this we have chosen that visitors only need to register once regardless of which sites they visit on the new platform. This ensures that Bonnier has the possibility of cross promoting their sites and that visitors are spared the burden of having to register the same information many times if they visit different Bonnier sites. It is however important for Bonnier to explain the advantages of this to their visitors.

All the sites share the user tables in a shared database. We are currently facing the challenge of making the user database accessible from the other sites that have yet to be migrated to the Drupal platform. Visitors need to be validated by sites that currently reside on other servers and that use other CMS platforms.


Proprietary modules


The calculator module consists of a handful of unique forms. Each form processes the data inputted by the visitor and returns results that for example are usually calorie consumption, alcohol percent and BMI figures.


TestThe competition module Contest is dependent on the Questions module. The Questions module is the syntax interpreter that is used for both competitions and tests. It interprets the questions written by the author of the competition and converts them to a form with radio buttons and validates the answers when the user has completed the contest.

The backend interface allows the administrator to draw a winner, export the participants data to an excel file and view a list of participants. You can additionally configure the permissions for the competition (see the paragraph about the competition node). This is done directly in the taxonomy interface, where you can select whether the user as a default should have a “Yes Please” permission checkbox ticked or not. One can also choose not to allow users to be able to make that choice – so that they automatically have given permission by entering the competition.

Crop cache

This module makes two new actions available for the image cache presets.

We have called the first action ”Fixed crop”. It has four settings; minimum width, minimum height, x offset and y offset. Fixed crop shows a “crop image” popup link on the node edit page, close to the image field cck fields. This popup contains a jQuery cropper. When the desired area of the image has been selected, the width, height and offset is saved in the database with the image file id reference.

We have called the second action ”Master preset”. This action enables smaller up- or down-scaling of an already cropped image – while retaining the same area and aspect ratio as the original.

Emediate banners

This module controls the banners from the ad serving company Emediate. Emediate uses both iframes and javascript to embed adverts on pages and the module supports both. The module makes a number of predefined sized blocks available. The employee in charge of maintaining online ads can configure the blocks with an id that is sent to Emediate. Furthermore the module sends data to Emediate regarding the context that the banner ad was shown in when the customer clicked on it.

Menu context

This module enables the user to apply a context for menu items. Input is handled by the same interface that is used to create and modify menu items. The context is simply taxonomy. This context can be used in many places, for example in code that generates a context sensitive right box based on the context of the current page. If you are for example not on a node page, but instead on a page that consists of panels, you will not have a taxonomy available to decide the context. Instead the context is provided by the module.

This module is especially popular with the person responsible for banner advertising on the site. Previously it was not possible to include a context from e.g. the front page as it consists of panels, but now any taxonomy can be fetched.

Teaser box

BoxesBonnier wanted full control over the front page content and front page sections, both regarding content and design.
We used the Panels module as our foundation – as it gives us the possibility of creating pages that are divided into ’panels’ which can contain content. It also has an intuitive drag-n-drop user interface.

We have additionally developed a teaserbox module that enables the editor to choose an article or teaser, choose between various designs and finally choose the colour and various placements of text and images. Finally the result is placed in a panels pane.

Termed menus

Termed menus are basically a copy of the widely used contrib-module menutrails. The module ensures that if a user is on a node that is associated with a taxonomy that belongs to a menu item – the menu retains it’s context.

We found that it was necessary to write our own module, as menutrails does not support translation of menu items. We use one menu per language but menutrails only allows one menu to have trails.

Contributed modules

We use many contrib modules and have tried to adher to standard modules as much as possible. Almost all content types are built with CCK and we use Views for most data. For different language versions we use I18N and we have configured it to select the language based on the hostname.


Frontend (MetaDesign)

We have maintained a rigid structure for our HTML and CSS for some time and have continued this into our Drupal solutions. We therefore have a master theme that contains our own template structure for the modules we use most. We can thereby ensure that our html is always of the same high standard and that we once and for all have created the template files in the master theme.

RootCandy admin theme

We use the Rootcandy theme for the administrator backend and can highly recommend this theme. This is a high quality theme that makes the Drupal backend significantly more professional and pleasurable to work with. We will therefore be sticking to this theme in the future.


beckyjohnson’s picture

Could you talk more about how you set up the multi language part of your site? For example, how do you ensure that people get served the right language depending on country? How smoothly did content translation go? What did you learn by doing this?

Also, since you have a huge about of graphics on your site, what things did you do to optimize the site?

ddorian’s picture

need more info too

Xen’s picture

I'm not much into the language part, but I'll fill in until someone in the know shows up.. As the frontpage and sub-frontpages is manually administered, it's a matter of a module that selects front page according to language, and each country having its own menu. Views handles most lists (including taxonomy/term), and are simply configured with a language filter.

I don't know about graphics optimisation, imagecache resizes them to the right sizes, and we have a cluster for a frontend. The sticky part of that is that we're using Amazon S3 for storage, through PHP stream wrappers, which requires some patching in order to work. Theoretically, we could serve the images directly off S3 and ease the load on the servers a bit, but haven't worked much on that yet.

Leftcurl’s picture

I so love it each time I see that there's a new case study available. Without them I don't think Drupal would have made much sense to me. Thanks to this one and others I can feel that I myself is just scratching the surface. I really hope them keep coming, it's highly appreciated and it do truly inspire the mind! Thank you so much! :)

I have three simple questions regarding this writeup.
1. Why is the first image in the 'Content types' section only a thumbnail?
2. Why haven't you called me up on the phone and told me about the Rootcandy admin theme earlier?
3. You write that because Menutrails does not support translation of menu items, you found it neccessary to write your own module called Termed menus. Why not contribute to the Menutrails module with the added translation support? If you decide to contribute to it, I know that I will forgive you on the second question.. :)

Xen’s picture

1. Beats me.

2. You forgot to leave your number.

3. It's not that simple. Thing is that it's actually more of a rewrite. Instead of having a page where you associate terms with a (single) menu, termed menu adds a menu selection to the term edit page. So you can select a menu item from any (language specific) menu. Secondly it doesn't do breadcrumbs or OG, as we didn't have any need. So it's not easy to roll back into menu trails.

machi27’s picture

hi there,

first congrats, nice work there.

I am wondering how did u make the right image menu, does it work in multi language sites?
what do i have to do to keep parent active?? i am using local menu and it is not working, should i try another module??
could you please tell me where could i found some info to develope something similar?


naxoc’s picture

Thank you :)
The right tabbed image menus are actually views, so they just have a filter that manages language.

If you want to keep the parent active in the menu, try menu trails I am a little hesitant to put the menu trails clone we made up as a contrib module because it would be duplicating a module that is already working just fine.

jinlong’s picture

good work. i want to how many develpers did it?

drupal user league -my drupal

naxoc’s picture

There were 5 PHP developers on this project, one systems administrator and one CSS/HTML specialist.

abdullah5588’s picture

Wow... Very nice work..

Colors have been used beautifully. Very well done guys.

Information Planet
Oil Cups

aac’s picture

Thanks for a nice writeup!!
I liked the idea of creating a content type "image" for all the images on the site and use them in articles as node reference. I would be interested to implement it, so could you please explain it in some more detail.
Thanks for your response!!


andershal’s picture

The first sites we created were and These have image galleries as one of the main features and BP wanted to re-use the images in both articles and galleries.

The solution was to create a content type called "image" and make this the only one with "imagefield" cck field. Both "article" and "gallery" then uses "nodereference" cck field to relate image nodes. We have a hook_preprocess_node function that looks for related image nodes and load their imagefield content. This is run through imagecache to present the image.

Articles can also relate to galleries and the logic is something like this:

  1. Is there a main image reference - use it
  2. Are there any unused image references in the main content - use the first
  3. Is there a relation to a gallery? Use the Nth image reference from that gallery (N defaults to 0)

// Hal

BillW_PDX’s picture

Excellent site! Can you tell me what your timeline was like to build? How long did it take your 5 PHP developers and the rest of the team to build the body of the site?

andershal’s picture

I don't know the exact timeline for the entire project, but the development of the first main part of the site was concentrated from mid September through November (approximately 2 months). Then a smaller dev. team had 3-4 weeks to complete a rather complex "Training planner" application. Since then there have been minor changes, bugfixes(NO!!) and new features added.

// Hal

PeterZ’s picture

Great write up, thanks for sharing.

I'm interested in the transition from the Polopoly Java platform to a Drupal Php platform.

You mention that one reason for the change was time-to-market. It was taking too long to add new functionality on the Java based CMS. Now that you've launched the new site, can you comment on where you've seen and expect to see the main time-to-market gains?

Aside from time-to-market issues, are there other advantages and/or disadvantages you see between using the Java based and/or Php based solutions?



naxoc’s picture

I cannot really answer on the time-to market question, but on the Java/PHP based solution i would say that a PHP solution is more manageable.

There is also the issue of recruiting developers. Here in Denmark it has been really hard to get Java developers for a long time and I guess it is the same in the rest of the world. There are more PHP programmers, though I would not say that it is easy to get Drupal developers anywhere. I think it would be a lot easier to educate a PHP programmer to use Drupal than to train someone to use a Java solution.

Polopoly is very powerful, but is also very time consuming to configure. Each little change can potentially require a great deal of custom coding in Java. Drupal is easier to make changes to and deploy.

fender-dupe’s picture

this is such a cool site, i logged in and could not understand, but great site!!!!

jcnventura’s picture

The print version looks horrible when printed in A4 and portrait mode.

And yes, I am the maintainer of the print module :).


João Ventura

bigtonkertoys’s picture

This is a very attractive site, one of the best I've seen. It's up there with that fishing site that was recently featured on the front page.

kwad9’s picture

Fabulous site! How exactly did you create the RutePlanner module? It's really cool. I'm interested in doing something similar where users can create (and then share) bike routes, but I'm not sure how to approach it exactly. Any information you may provide is appreciated...