Case Study

Saving Core Web Vitals

How I reduced the performance impact of a third-party widget used across merchant websites.

seQura Web Performance Frontend Architecture 2023

Project at a glance

Context

At seQura, promotional payment widgets were embedded into merchants' product pages so shoppers could see installment options directly while browsing.

Problem

The widget appeared in Core Web Vitals and Lighthouse reports as one of the main third-party blockers, affecting merchant performance and trust.

My role

I led the investigation, experimentation, and implementation of the performance improvements across the widget integration assets.

A business-critical performance problem

In 2023 I worked on a project that became one of the most technically challenging — and meaningful — experiences of my engineering career.

At the time, I was working as a frontend developer at seQura, a fintech company that provides payment and financing solutions for e-commerce merchants. One of the core parts of the product was a set of promotional widgets embedded directly in merchants' product pages.

These widgets allowed customers to immediately see installment payment options while browsing products. However, they also came with a serious problem: several merchants started reporting that the widgets were negatively affecting the performance of their websites.

Performance reports based on Google's Core Web Vitals showed our script appearing as one of the largest third-party contributors to page slowdown. Some merchants were concerned enough to consider removing the widget entirely.

This situation triggered what internally became known as the widgets performance crisis.

Why merchants were worried

The first step was to understand why merchants were seeing our widget as a performance problem.

Modern website performance is often evaluated using Google's Core Web Vitals. Among these metrics, two were especially relevant in our case:

Metric

LCP

Largest Contentful Paint measures how quickly the main content of a page becomes visible.

Metric

TBT

Total Blocking Time measures how long the browser's main thread is blocked by JavaScript.

In many of the merchants' reports, our widget appeared as one of the largest contributors to Total Blocking Time. This meant that while the widget was loading or executing its logic, the browser could not respond to user interactions.

From the perspective of a merchant running Lighthouse or PageSpeed tests, the message was simple: the seQura widget was slowing down their page.

Key insight

The problem was not only what we loaded, but how much JavaScript the browser had to parse, execute, and keep on the main thread during a critical moment of page rendering.

Timeline

May 2023

Widgets performance crisis begins

Merchant concerns around performance, SEO, and Lighthouse reports make the issue urgent.

June 2023

Investigation and architecture analysis

I analyzed the existing architecture, dependency weight, loading strategy, and possible alternatives.

July 2023

Quick wins shipped

Library cleanup, refactors, and dependency reductions produced the first meaningful improvements.

September 2023

Deeper architectural improvements

I removed heavy iframe abstractions, simplified rendering, and dramatically reduced the widget's footprint.

What I tested first

Experiment 01

Async vs defer

I tested whether changing the loading strategy of the widget script could reduce blocking time.

Experiment 02

Banner fallback

I explored replacing the widget with a simpler banner to reduce JavaScript and preserve merchant trust.

Experiment 03

Mini widgets

I analyzed whether lighter mini-widgets could offer a stable alternative in production environments.

What was actually causing the problem

These experiments helped clarify something important: the root issue was not simply when the widget loaded, but the amount and structure of JavaScript executed by the widget itself.

The architecture had accumulated several layers of complexity over time:

  • Heavy JavaScript bundles
  • Legacy dependencies and partially used libraries
  • Iframes managed through Zoid
  • Duplicated resource loading when multiple widgets appeared on the page
  • Long tasks on the browser's main thread

Before and after

Before

  • Heavy dependency chain
  • Zoid-managed iframes
  • Larger integration script
  • Duplicated resource loading patterns
  • Widget appears high in performance reports

After

  • Unused libraries removed
  • Native HTML iframes managed with vanilla JS
  • Much smaller integration script
  • Simpler, more predictable rendering process
  • Widget no longer appears as a major blocker

Reducing bundle size first

Before attempting larger architectural changes, I focused on the quickest improvements that could reduce the amount of JavaScript shipped to merchant websites.

This included removing unused libraries such as axios, lodash, and date-fns, removing unnecessary polyfills, upgrading dependencies, and refactoring legacy code.

These changes alone reduced the widget bundle size by approximately 51%, proving that meaningful improvements were possible without rebuilding everything from scratch.

Removing Zoid and simplifying iframe management

The biggest improvement came from addressing how widgets were rendered.

The previous implementation relied on Zoid-managed iframes, which introduced unnecessary overhead. I replaced this approach with native HTML iframes managed with vanilla JavaScript, removing a major dependency layer.

This change eliminated a large vendor bundle, dramatically reduced the integration script, and simplified the widget rendering process.

I also explored the use of Shadow DOM as a future-friendly alternative for better encapsulation and improved performance in some scenarios.

Measured outcomes

Metric Before After Change
Main-thread blocking time 789ms 128ms 83% improvement
Total transfer size 242KB 147KB 48% reduction
Total bundle size 543KB 113KB 79% reduction
Integration script 54KB 8KB 85% reduction

Comparing against competitors

To understand whether the new implementation was truly competitive, I benchmarked seQura's widget against other embedded payment widgets in the market, including Klarna and Aplázame.

Klarna's solution was especially lightweight and used aggressive loading strategies, often producing almost no blocking time in the sampled reports. Before optimization, seQura tended to fall in the middle of the performance spectrum, but still appeared too prominently in merchant audits.

After the improvements, the widget no longer appeared as a major concern in those reports, which was an important signal that the work had not only improved internal metrics, but also made the solution much more competitive in practice.

Lessons learned

01

Third-party scripts must be extremely lightweight because they directly affect another company's performance and trust.

02

Architecture decisions accumulate technical debt over time, especially in embedded systems that live for years.

03

Measure before changing architecture. Several promising ideas turned out to have little real-world impact once tested.

04

Performance work is often invisible to users, but critical for SEO, conversion, and product trust.

A defining project for me

This project became one of the most meaningful technical challenges of my career.

It required combining performance analysis, architectural thinking, experimentation, and implementation to solve a problem affecting real businesses using our product.

Leading the investigation and implementation of these improvements reinforced my interest in web performance and system-level frontend engineering.