The Challenge
Sunday Golf, a premium golf apparel brand, needed to migrate from a legacy Shopify theme to the modern Dawn 2.0 architecture while implementing advanced features like bundle builders and mega menus. The challenge was maintaining exceptional performance while adding complex functionality.
Key Requirements
- Performance First: Must maintain sub-2.5s load times
- Bundle Builder: Custom bundle creation for product combinations
- Mega Menu: Complex navigation for extensive product catalog
- Checkout Extensibility: Custom checkout experience with upsells
- Mobile Excellence: Premium mobile shopping experience
- Zero Downtime: Seamless migration without business interruption
The Process
Phase 1: Architecture & Planning (Weeks 1-2)
Theme Analysis
- Audited existing theme structure and custom modifications
- Identified migration risks and dependencies
- Created comprehensive migration roadmap
- Established performance budgets
Dawn 2.0 Customization
- Evaluated Dawn 2.0 architecture and section rendering
- Designed custom app blocks for extensibility
- Planned bundle builder integration
- Architected mega menu system
Phase 2: Core Migration (Weeks 3-6)
Theme Implementation
{% comment %}
Custom Bundle Builder Section
Allows customers to create personalized golf gear bundles
{% endcomment %}
<div class="bundle-builder" data-section-id="{{ section.id }}">
<div class="bundle-configurator">
<div class="bundle-steps">
{% for step in section.settings.bundle_steps %}
<div class="step" data-step="{{ forloop.index }}">
<h3>{{ step.title }}</h3>
<div class="product-grid">
{% for product in step.products %}
<div class="product-card" data-product-id="{{ product.id }}">
<img
src="{{ product.featured_image | image_url: width: 400 }}"
alt="{{ product.title }}"
loading="lazy"
width="400"
height="400"
>
<h4>{{ product.title }}</h4>
<span class="price">{{ product.price | money }}</span>
<button class="add-to-bundle">Add to Bundle</button>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="bundle-summary">
<h3>Your Bundle</h3>
<div class="bundle-items"></div>
<div class="bundle-total">
<span>Total:</span>
<span class="total-price">$0.00</span>
<span class="savings">Save 15%</span>
</div>
<button class="complete-bundle">Add Bundle to Cart</button>
</div>
</div>
</div>
<script>
class BundleBuilder {
constructor(sectionId) {
this.section = document.querySelector(`[data-section-id="${sectionId}"]`);
this.selectedItems = new Map();
this.init();
}
init() {
this.attachEventListeners();
this.loadPersistedBundle();
}
attachEventListeners() {
this.section.querySelectorAll('.add-to-bundle').forEach(btn => {
btn.addEventListener('click', (e) => this.handleAddItem(e));
});
this.section.querySelector('.complete-bundle').addEventListener('click', () => {
this.addBundleToCart();
});
}
async addBundleToCart() {
const items = Array.from(this.selectedItems.values());
try {
const response = await fetch('/cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items })
});
if (response.ok) {
// Track conversion
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'bundle_purchase',
bundle_value: this.calculateTotal(),
items: items.length
});
window.location.href = '/cart';
}
} catch (error) {
console.error('Bundle add failed:', error);
}
}
calculateTotal() {
let total = 0;
this.selectedItems.forEach(item => {
total += item.price * item.quantity;
});
return total * 0.85; // 15% bundle discount
}
}
new BundleBuilder('{{ section.id }}');
</script>
{% schema %}
{
"name": "Bundle Builder",
"settings": [
{
"type": "text",
"id": "title",
"label": "Section Title"
}
],
"blocks": [
{
"type": "bundle_step",
"name": "Bundle Step",
"settings": [
{
"type": "text",
"id": "step_title",
"label": "Step Title"
},
{
"type": "product_list",
"id": "products",
"label": "Products"
}
]
}
]
}
{% endschema %}
Mega Menu System
{% comment %}
Intelligent Mega Menu with Category Previews
{% endcomment %}
<nav class="mega-menu">
<ul class="menu-level-1">
{% for link in section.settings.menu.links %}
<li class="menu-item {% if link.links.size > 0 %}has-dropdown{% endif %}">
<a href="{{ link.url }}">{{ link.title }}</a>
{% if link.links.size > 0 %}
<div class="mega-dropdown">
<div class="dropdown-container">
<div class="menu-categories">
{% for child_link in link.links %}
<div class="category-column">
<h4>{{ child_link.title }}</h4>
{% if child_link.links.size > 0 %}
<ul>
{% for sublink in child_link.links %}
<li><a href="{{ sublink.url }}">{{ sublink.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
</div>
<div class="menu-featured">
<div class="featured-product">
{% if section.settings.featured_product %}
{% assign product = section.settings.featured_product %}
<img
src="{{ product.featured_image | image_url: width: 400 }}"
alt="{{ product.title }}"
loading="lazy"
>
<h5>{{ product.title }}</h5>
<a href="{{ product.url }}" class="btn-primary">Shop Now</a>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
</li>
{% endfor %}
</ul>
</nav>
<style>
.mega-menu {
position: relative;
}
.mega-dropdown {
position: absolute;
top: 100%;
left: 0;
width: 100vw;
background: white;
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.menu-item:hover .mega-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.dropdown-container {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: 3fr 1fr;
gap: 2rem;
padding: 2rem;
}
.menu-categories {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
}
</style>
Phase 3: Checkout Extensibility (Weeks 7-8)
Implemented custom checkout experience using Shopify's new extensibility APIs:
- Upsell Blocks: Contextual product recommendations
- Trust Badges: Security and shipping guarantees
- Gift Options: Premium gift wrapping selection
- Order Tracking: Post-purchase integration
Phase 4: Performance Optimization (Weeks 9-10)
Critical Path Optimization
// Lazy load non-critical sections
const observerOptions = {
rootMargin: '50px 0px',
threshold: 0.01
};
const sectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const section = entry.target;
// Load section content
if (section.dataset.lazyLoad === 'true') {
loadSectionContent(section);
sectionObserver.unobserve(section);
}
}
});
}, observerOptions);
// Observe all lazy sections
document.querySelectorAll('[data-lazy-load="true"]').forEach(section => {
sectionObserver.observe(section);
});
Image Optimization
- Implemented native lazy loading
- WebP with PNG/JPG fallbacks
- Responsive images with srcset
- Optimized above-the-fold images
Phase 5: Testing & Launch (Weeks 11-12)
Comprehensive Testing
- Cross-browser compatibility testing
- Mobile device testing (iOS/Android)
- A/B testing on key pages
- Load testing with realistic traffic patterns
Staged Rollout
- Soft launch to 10% of traffic
- Monitor performance and conversions
- Gradual increase to 100%
- Post-launch optimization
The Results
The migration exceeded all performance and business targets:
Performance Achievements
- Page Load Time: Consistently under 2.5s (avg 1.8s)
- Lighthouse Score: 95+ on mobile, 98+ on desktop
- Core Web Vitals: All metrics in "Good" range
- Bundle Size: Reduced by 60% vs old theme
Business Impact
- Conversion Rate: +18% increase post-migration
- Average Order Value: +25% with bundle builder
- Mobile Conversions: +32% improvement
- Cart Abandonment: -15% reduction
- Page Views per Session: +40%
Feature Adoption
- Bundle Builder: Used by 35% of customers
- Mega Menu: 60% reduction in header search usage
- Checkout Upsells: $45k additional monthly revenue
- Mobile Experience: 50% increase in mobile purchases
Technical Innovations
1. Progressive Bundle Loading
Implemented intelligent loading system that:
- Loads initial products immediately
- Lazy loads additional options as user scrolls
- Prefetches likely selections based on behavior
- Caches bundle configurations in localStorage
2. Mega Menu Performance
Optimized complex navigation:
- CSS-only dropdowns (no JavaScript until interaction)
- Image preloading on hover intent
- Cached menu structure in service worker
- Sub-300ms interaction time
3. Checkout Extensibility
Custom checkout enhancements:
- Dynamic upsell based on cart contents
- Real-time shipping calculations
- Gift message customization
- One-click reorder functionality
Key Takeaways
-
Dawn 2.0 is Powerful: The new section architecture enables incredible flexibility while maintaining performance
-
Bundle Builder Drives AOV: Custom bundle experience significantly increased average order value
-
Performance Budget Works: Strict performance budgets ensured speed wasn't sacrificed for features
-
Checkout Extensibility ROI: Custom checkout features paid for themselves in first month
-
Mobile-First Approach: Starting with mobile design led to better overall experience
Client Testimonial
"The migration to Dawn 2.0 was seamless and the results speak for themselves. Our customers love the bundle builder, and our conversion rates have never been higher. Bechara's attention to performance detail while adding complex features is exactly what we needed."
— E-commerce Director, Sunday Golf
Technical Stack
Frontend
- Shopify Dawn 2.0 theme architecture
- Vanilla JavaScript (no frameworks for performance)
- CSS Grid and Flexbox for layouts
- Intersection Observer API for lazy loading
Shopify Features
- Theme App Extensions
- Checkout Extensibility
- Metafields for custom data
- Storefront API for dynamic content
Performance
- Critical CSS extraction
- JavaScript code splitting
- Image optimization pipeline
- Service Worker caching strategy
Tools & Testing
- Shopify CLI for development
- GitHub Actions for deployment
- Lighthouse CI for performance monitoring
- Google Analytics 4 for tracking