Isaac Garcia (Developer)
Katie Turley (Producer)
Happy Family is an organic food company and a division of Danone, the French food-products corporation.
Happy Family partnered with Bukwild to address some challenges with their aging Wordpress website. We migrated their content to Contentful and built a Nuxt.js front end. The project forged a strong relationship between Danone and Bukwild, and has led to multiple retainer agreements and talks of future projects with more Danone brands.
See it now
Leading a Team
I was fortunate to have two other developers with me. Isaac handled the Wordpress migration, then did the initial Algolia setup. Wilson built the majority of the content blocks. I handled the integrations while checking in frequently with the others and reviewing code.
Migrating from Wordpress
A variety of content on the Wordpress site needed to be migrated to Contentful. This included about a hundred products — with 55 tags grouped into eight taxonomies — as well as hundreds of products, articles, redirects, and FAQs. Working through these content types one by one, we wrote Node scripts that fetched the Wordpress content from the REST API, applied the necessary formatting, and then saved the entries using the Contentful CLI.
Building a Custom Repeater Field using the Contentful App Framework
Contentful's free tier includes 48 content types. But Contentful's lack of a repeater field means that a good chunk of those content types are inevitably used up to store repeating content — button lists, text lists, card lists. Having a repeater field would free up content types and really extend what's possible within the free tier.
Seeing an opportunity early in this project, I made a repeater field proof of concept using create-contentful-app, a boilerplate made by Contentful's development team. I built the React UI that's shown to CMS users, allowing them to add content (text, images, even other Contentful entries) and drag to re-order their repeater rows. Then I deployed it to our Contentful space and introduced it to our team.
Equipped with the repeater field, our team was able to rapidly build out all the block types we needed, while also conserving content types, paving the way for expanding the website's capabilities in the future.
Search Powered by Algolia
Given the filtering needs of the product listing page — 55 tags grouped into eight taxonomies — we knew using Algolia would save lots of time. I used vue-instantsearch, a Vue component library built on top of Algolia's InstantSearch.js. The UI supports refinements on multiple facets. I also routed the filter state to the page query parameters.
Google Tag Manager
Migrating the existing GTM tags was an undertaking. The first step was to compile a list, meet with the client, and eventually discard the majority. Then I went through each tag and figured out how it should work in a client-side navigating environment: some "smart" tags can detect client-side navigation, some tags have a pageview method that should be triggered, and some older tags must be completely re-fired on every client-side navigation.
The website needed to display different chat widgets on different sections of the site. To accomplish this, I created a layout-level Vue component that rendered the widget and invoked the relevant API commands to destroy and re-initialize the widget as necessary. The widget also showed an online/offline status based on customer service hours in US Eastern time zone, taking into account the current user's time zone offset.
More integrations and optimizations
PageSpeed: We ran a series of tests using Lighthouse and Netlify to isolate problematic code in the header and block wrapper component, and re-wrote portions of the main navigation and a block wrapper component, which improved our PageSpeed score. We also adjusted how some GTM tags loaded, which further improved our score.
Accessibility: We contracted an outside QA firm to conduct a rigorous accessibility audit, and we made upgrades related to ARIA attributes, keyboard navigation, and screen reader document flow.
SEO: To enable rich snippets in search results, we added JSON-LD and Open Graph structured data to the document head.
Destini: Provided a store locator modal on our product detail page.
Bazaarvoice: Provided product review widgets on our product detail page.
Listrak: Provided email capture for our newsletter signup form.