The Complete Ring Builder: Architecture, Psychology, and Conversion Engineering for Jewellery’s Highest-Intent Feature
Author: Erwee Coetzee | Diamond Stack / SEO Gurus
Supporting Page: Custom Ring Builder & Diamond API Integrations
Reading Time: ~24 minutes
There is a moment in the jewellery buying journey where everything converges. The research is done. The category decision has been made — natural diamond, lab-grown, moissanite. The budget is set, at least loosely. The style direction has been established through hours of Instagram saves and Pinterest boards and late-night browsing sessions. The buyer arrives at a jewellery website ready, in principle, to commit.
And then they encounter a ring builder.
In most cases, what follows is one of two experiences. The first: a simplified three-step selector — choose a setting, choose a stone, see a price — that moves so fast and offers so little information that the buyer does not feel they have actually made a decision. They feel they have filled in a form. They do not complete the enquiry. The second: a technically ambitious configurator that takes twelve seconds to load on mobile, renders a blurry 3D preview that does not represent the finished piece accurately, requires six interactions before showing a price, and times out when the diamond filter returns 47,000 results without pagination. They do not complete the enquiry either.
The ring builder is the most commercially consequential feature in jewellery e-commerce. It sits at the apex of the buyer journey, at the highest point of purchase intent, at the moment when a customer is most ready to spend a significant sum of money. And the majority of implementations fail them at exactly that moment.
This article is the complete blueprint for building a ring builder that converts. It covers the buyer psychology that determines what the feature needs to do, the UX architecture that structures the decision sequence correctly, the full technical implementation from database schema to REST endpoint to front-end state management, the performance constraints that most developers underestimate, and the conversion mechanics that close the gap between diamond selection and completed enquiry.
Every section of this article is connected. The psychological model determines the UX sequence. The UX sequence determines the technical requirements. The technical requirements determine the architecture. The architecture determines the performance characteristics. And performance, in a feature this commercially important, is not a separate concern — it is conversion.
Part One: Why Ring Builders Fail
Before building the right ring builder, it is worth understanding precisely why the wrong ones fail. The failure modes are consistent enough across implementations to constitute a taxonomy.
Failure Mode 1: The Premature Commitment Problem
The most common structural failure in ring builder design is asking the buyer to commit to a setting before they understand the economics of the stone they will put in it.
A ring builder that opens with “choose your setting” puts the buyer in an impossible position. They are selecting a frame without knowing the cost or size of the picture that will go inside it. A 1.5ct cushion cut moissanite sits in a very different setting than a 0.5ct round brilliant diamond — different prong configuration, different proportions, different centre stone dimensions. A buyer who selects a solitaire setting because it looks elegant in the product image, then selects a 2ct oval stone, may find that the setting they loved does not offer an oval centre option. They have to go back. The decision sequence has broken.
The psychological consequence of forced reversal in a multi-step decision flow is not just inconvenience — it is trust erosion. The buyer who has to backtrack feels they did not understand the system, which is the system’s fault. They are now less confident, not more. Confidence is the variable that drives the enquiry submission at the end of the flow.
Failure Mode 2: The Information Deficit at the Decision Point
The engineer buyer — the highest-value customer discussed in the previous article in this series — arrives at a ring builder with a specific set of questions they need answered before they can make a decision. What is the table percentage on that stone? What is the depth? Does it have fluorescence? Is the cut grade Excellent or Very Good? What are the millimetre dimensions?
A ring builder that displays diamond results as a list of prices with thumbnail images and nothing else is not a ring builder. It is a price list. The engineer buyer leaves to find a retailer who will show them the specification.
The information architecture of the diamond selection interface needs to match the information requirements of the buyer who is most likely to complete a high-value purchase. That buyer needs: full grading detail, measurements in millimetres, a size reference (what does 8.5mm look like on a finger?), the certificate number and a link to verify it, a clear breakdown of what the price includes, and confirmation of the availability status. Every missing field is a question the buyer has to answer elsewhere, and the buyer who goes elsewhere to answer a question does not always come back.
Failure Mode 3: The Performance Collapse Under Real Load
Diamond filters that query a live feed of 50,000 stones without a proper caching and indexing architecture produce one of two outcomes: a response time that makes the interface feel broken, or a server-side timeout that returns an error to the buyer at the moment of highest engagement.
The performance requirements of a ring builder are not the same as the performance requirements of a content page. A content page that takes 1.5 seconds to load is acceptable. A ring builder filter interaction that takes 1.5 seconds to return results is not. The buyer’s mental model for an interactive filtering interface is built on the sub-200ms response time of Google search and Amazon product filtering. When a jewellery ring builder takes three times as long, the experience registers as broken even if it technically functions.
The architecture section of this article covers the technical solution in detail. The point to establish here is that performance in a ring builder is a UX requirement, not a technical afterthought.
Failure Mode 4: The Mobile Abandonment Gap
A ring builder designed primarily on desktop and adapted for mobile is not a mobile ring builder. It is a desktop ring builder with a viewport problem.
The buying journey for jewellery, particularly in the consideration phase, is predominantly mobile. Buyers browse on their phones at lunch, in the evening, while shopping. But the conversion decision — the moment of completing an enquiry — shifts to desktop for many buyers, particularly engineer types who want to compare specifications side by side and verify certificate details.
A ring builder that is unusable on mobile loses buyers during the consideration phase who will not return on desktop. A ring builder that is usable on mobile but does not complete the conversion triggers a device switch that many buyers never complete. The correct design philosophy is mobile-first for browsing and filtering, and optimised for desktop conversion without abandoning mobile conversion capability.
Failure Mode 5: The Commitment Threshold Mismatch
The ring builder that ends with a “Complete Purchase” button is misaligned with how jewellery purchases of R 20,000 and above actually convert. A buyer who has spent twenty minutes selecting a stone and a setting and arrives at a “Buy Now” button experiences a sharp discontinuity — the decision they thought they were building toward turns out to be a purchase commitment they were not psychologically prepared for.
The correct commitment threshold for a ring builder at this price point is an enquiry, not a transaction. “Reserve this stone and discuss with a designer” or “Submit your selection for a consultation” asks for a smaller commitment while capturing the same commercial intent. The financial transaction follows the human conversation — and the human conversation closes the sale at a dramatically higher rate than an unattended checkout flow.
The ring builder that does not understand this distinction will have an abandoned cart rate that looks inexplicably high. The stone was selected. The setting was chosen. The price was seen. And then nothing. Because the buyer needed a conversation, not a payment form.
Part Two: The Buyer’s Decision Architecture
Understanding why ring builders fail leads directly to the question of how the buying decision actually works — because the ring builder’s UX sequence must mirror the buyer’s psychological sequence, not the retailer’s operational preference.
The ring builder buyer moves through five distinct psychological states, each with different information needs and different friction tolerances.
State 1: Orientation (What am I looking at?)
The buyer arrives at the ring builder either from a product page, a marketing link, or a site navigation element. In the first five seconds they need to understand: what can I do here, what are the steps, and how much effort is this going to require?
A ring builder that does not explain itself — that simply presents a search interface with fifteen filter sliders — loses orientation-phase buyers immediately. They are not confused because they lack intelligence. They are confused because the interface has not told them what it is, what it does, or what a successful outcome looks like.
The orientation phase requires: a headline that explains the feature (“Design your ring: choose a stone, select a setting, request your quote”), a visible step indicator (Step 1 of 3), and an entry point that is low-friction (a primary shape selector with images, not a text dropdown).
State 2: Exploration (What exists at my budget?)
Once oriented, the buyer enters an exploration phase. They are calibrating the market — understanding what their budget achieves in terms of stone quality and size, and whether the options available match the brief they arrived with.
The exploration phase is filter-intensive and non-linear. The buyer adjusts carat range, changes clarity grade, switches shape. They are building a mental model of the option space, not converging on a specific stone. They will visit fifteen to thirty stone records in this phase before any particular stone becomes a candidate.
The UX requirement for exploration is: fast filter response (sub-200ms), broad result sets with clear sorting options, and enough information per result card to support rapid candidate identification without requiring a click into each individual stone page.
State 3: Evaluation (Is this the right stone?)
When the buyer identifies a candidate stone, they shift from exploration to evaluation. They need: the complete specification, the certificate verification link, the millimetre measurements with a visual size reference, and enough comparative context to confirm that this stone represents good value for its grade.
This is the state where the engineer buyer’s information requirements are fully activated. The evaluation phase UI needs to surface every field in the diamond specification, present it in a format that enables comparison against other candidates, and provide external verification pathways for the claims being made.
A stone detail view that omits depth percentage, table percentage, or crown and pavilion angles is failing the evaluation-phase buyer. These fields are not edge-case technical curiosities — they are the difference between an Excellent cut that faces up brilliantly and an Excellent cut that is cut deep and faces up small for its carat weight.
State 4: Combination (Does this stone work with this setting?)
Once a stone is selected, the buyer needs to evaluate it in combination with a setting. This is where the setting-first vs stone-first debate in ring builder design becomes structurally important.
The setting selection phase, post-stone-selection, is constrained by the stone’s shape and approximate size. A buyer who selected a 7.5 x 5.5mm oval stone should only see settings with oval centre options of appropriate size. A buyer who selected a 6.5mm round brilliant should see round solitaire, halo, and three-stone options for a centre stone of that diameter.
The UX architecture that serves this state presents a filtered setting catalogue where ineligible options are either hidden or clearly marked as incompatible — not a full setting catalogue that the buyer has to manually cross-reference against their stone selection. Showing a buyer a setting that will not accommodate their chosen stone wastes their time and erodes confidence in the interface’s intelligence.
The combination phase also introduces the pricing synthesis moment: stone price + setting price + manufacturing = total cost. This calculation needs to be visible, persistent, and real-time. A buyer who reaches the end of the flow and discovers the combined price is 40 percent above their mental budget has experienced a deception — even if no individual component was misrepresented. The total cost should be visible throughout, updating live as selections change.
State 5: Commitment (Am I ready to move forward?)
The final psychological state is the commitment decision. The buyer has selected a stone, chosen a setting, seen the total price, and needs to decide whether to proceed.
At this state, three things determine whether the enquiry is submitted or the session is abandoned:
Confidence in the product. Does the buyer believe the stone is as described, the setting is as shown, and the price is fair? Every information deficit from earlier in the flow reappears here as doubt. The buyer who is not certain about the stone’s cut quality, or who could not verify the certificate number, or who saw a setting thumbnail that did not look like the ring they want — that buyer does not submit the enquiry.
Confidence in the retailer. Does the buyer believe this specific jeweller will deliver on the promise? The ring builder does not exist in isolation. The retailer’s reviews, their about page credentials, their portfolio of completed work — these are the trust signals the buyer is drawing on at the commitment state. The ring builder should surface them contextually: a link to the about page, a count of completed commissions, a testimonial from a previous customer with a similar selection.
Clarity about what happens next. The buyer who submits an enquiry through a ring builder needs to know: who will contact them, how quickly, what information they will need to bring to that conversation, and what commitment they are making by submitting. A submission form with no explanation of the next step creates a commitment anxiety that prevents submission.
Part Three: The UX Architecture
With the psychological model established, the UX architecture follows from it. Every structural decision below is a direct translation of a psychological requirement.
Stone First, Setting Second — The Correct Sequence
The evidence from the failure mode analysis and the buyer decision architecture points to a clear conclusion: the ring builder should begin with stone selection, not setting selection.
The reasons are both psychological and practical:
Psychologically, stone selection establishes the price anchor. The buyer who selects a 1.2ct E/VS1 round brilliant at R 42,000 has committed to a budget context. The setting selection that follows is evaluated against that context — a R 8,500 solitaire setting feels reasonable against a R 42,000 stone. The same ring builder sequence in reverse — setting first, stone second — presents a R 8,500 setting purchase followed by a R 42,000 stone that may feel like an escalation the buyer was not prepared for.
Practically, the stone’s shape and size constrain the setting options. Starting with the stone means the setting catalogue can be intelligently filtered. Starting with the setting means the buyer may select a setting with a 6.5mm round centre, then browse stones and fall in love with a 9 x 7mm oval — requiring a complete restart.
The one legitimate exception is the buyer who arrives with a very specific setting design in mind — perhaps a vintage Art Deco setting they saw in your portfolio — and wants to find a stone to suit it. For this buyer, a “start with a setting” entry point is valid, and the ring builder should offer it as an alternative path from the orientation screen. But the default flow, serving the majority of buyers, starts with the stone.
The Three-Panel Layout: Filter, Results, Preview
The ring builder interface that handles the exploration phase most effectively uses a three-panel layout:
Left panel — Filters. Shape selector (image-based, not a dropdown), price range (dual-handle slider in ZAR), carat range (dual-handle slider with 0.01 precision), colour range (D through Z with a visual colour scale), clarity range (FL through I3 with a grade description tooltip), cut grade (Excellent / Very Good / Good — rounds only), certification lab (GIA / IGI / HRD / other — checkboxes), and fluorescence (None / Faint / Medium / Strong — checkboxes). Advanced filters collapsed behind a toggle: table percentage range, depth percentage range, measurements, polish, symmetry.
Centre panel — Results grid. Diamond cards showing: stone image (if available, with a fallback illustration for the shape), carat weight prominently displayed, shape, colour and clarity grade pairing (e.g., “E / VS1”), cut grade badge (Excellent shown in gold), certification lab logo or abbreviation, and retail price in ZAR. Sort options: price ascending, price descending, carat descending, best cut. Pagination: 24 results per page with infinite scroll as a UX option on mobile.
Right panel — Stone detail and preview. When a stone is selected from the centre panel, the right panel surfaces the full specification, the certificate number with a verification link, the millimetre measurements alongside a hand diagram showing approximate finger coverage, and a “Select This Stone” button that progresses to the setting selection phase.
On mobile, this three-panel layout collapses to a bottom-sheet filter drawer, a full-width results grid, and a full-screen stone detail view. The layout is sequential rather than simultaneous on mobile — one panel visible at a time.
The Setting Selection Interface
Post-stone-selection, the setting catalogue interface shows:
Filtered by compatibility. Only settings that accommodate the selected stone’s shape and approximate dimensions are shown. The filter is applied silently — the buyer sees a curated catalogue, not a “12 of 47 results” message that implies something has been hidden.
Metal options within each setting. A setting card shows the primary metal option with colour swatches for alternatives (yellow gold, white gold, rose gold, platinum). Selecting a different metal updates the setting image and the price in real time.
Total price always visible. A persistent price bar at the bottom of the screen shows: Stone (R X) + Setting (R Y) = Total (R Z). This updates live when metal options change. VAT note: “Prices include 15% VAT.”
Setting detail view. When a setting is selected, the detail view shows: the setting with the selected stone type approximately rendered (not necessarily photorealistic — a stylised illustration is acceptable and more honest than a CGI render that may not represent the actual piece accurately), the metal specifications (purity, approximate weight), the prong configuration, the compatibility note (“Accommodates round stones 6.2mm–7.0mm”), and a description written by the jeweller — not manufacturer boilerplate.
The Summary and Enquiry Screen
The final screen shows a complete summary of the selection:
- Stone: Shape, carat, colour, clarity, cut, certificate number, source
- Setting: Name, metal, purity
- Total price breakdown (stone, setting, manufacturing, VAT)
- Estimated lead time (“Completed in 6–8 weeks from order confirmation”)
Below the summary, the enquiry form:
- Name (required)
- Email (required)
- Phone (required)
- Ring size (optional — with a link to the ring size guide)
- Message (optional — “Is there anything you’d like us to know about your brief?”)
- Preferred contact time (dropdown: morning / afternoon / evening)
Below the form, the trust layer:
- “Your selection will be held for 48 hours pending consultation confirmation”
- A single testimonial from a previous customer with a matching stone type
- A link to the about page with the jeweller’s name and credentials
- The response time commitment (“We respond within one business day”)
The submit button: “Submit My Selection — Reserve This Stone” — not “Buy Now,” not “Add to Cart,” not “Complete Purchase.”
Part Four: The Technical Implementation
The UX architecture above describes what the ring builder needs to do. This section describes how to build it.
The Database Foundation
The ring builder’s performance is determined primarily by the database layer. As established in the earlier architecture article in this series, diamond inventory should never be stored in WooCommerce’s native wp_postmeta EAV structure. The custom ds_diamond_inventory table — with composite indexes designed for the ring builder’s specific filter query patterns — is the foundation everything else depends on.
The indexes that serve the ring builder’s primary filter combinations:
-- Primary composite for the most common filter pattern
ALTER TABLE ds_diamond_inventory
ADD INDEX idx_ring_builder_primary
(shape, colour_sort, clarity_sort, cut, carat, price_zar, is_available);
-- Secondary for price-range queries without shape filter
ALTER TABLE ds_diamond_inventory
ADD INDEX idx_price_range
(is_available, price_zar, carat);
-- For the millimetre-based setting compatibility filter
ALTER TABLE ds_diamond_inventory
ADD INDEX idx_dimensions
(shape, length_mm, width_mm, is_available);
The composite index on (shape, colour_sort, clarity_sort, cut, carat, price_zar, is_available) covers the most common ring builder query: a buyer who has selected a shape and is filtering by colour range, clarity range, and price range simultaneously. MySQL’s query optimiser will use this index for any left-prefix combination of these fields, meaning it serves both the full filter set and the partial filter sets that occur during early exploration.
The REST API Layer
The ring builder communicates with the server via a custom WordPress REST API endpoint. This endpoint is the performance-critical path — every filter interaction triggers a request to it, and its response time is what the buyer experiences as the interface’s “speed.”
/**
* Ring builder diamond search endpoint.
* Route: GET /wp-json/diamond-stack/v1/ring-builder/diamonds
*
* Accepts filter parameters, returns paginated diamond results
* with facet counts for active filter options.
*/
add_action( 'rest_api_init', function() {
register_rest_route( 'diamond-stack/v1', '/ring-builder/diamonds', [
'methods' => 'GET',
'callback' => 'ds_rb_search_diamonds',
'permission_callback' => '__return_true',
'args' => [
'shape' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
'carat_min' => [ 'type' => 'number', 'default' => 0.30 ],
'carat_max' => [ 'type' => 'number', 'default' => 5.00 ],
'colour_min' => [ 'type' => 'integer', 'default' => 1 ],
'colour_max' => [ 'type' => 'integer', 'default' => 10 ],
'clarity_min' => [ 'type' => 'integer', 'default' => 1 ],
'clarity_max' => [ 'type' => 'integer', 'default' => 12 ],
'cut' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
'price_min' => [ 'type' => 'number', 'default' => 0 ],
'price_max' => [ 'type' => 'number', 'default' => 9999999 ],
'lab' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
'fluorescence'=> [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
'sort' => [ 'type' => 'string', 'default' => 'price_asc' ],
'page' => [ 'type' => 'integer', 'default' => 1 ],
'per_page' => [ 'type' => 'integer', 'default' => 24 ],
],
] );
} );
function ds_rb_search_diamonds( WP_REST_Request $request ): WP_REST_Response {
global $wpdb;
$table = $wpdb->prefix . 'diamond_inventory';
// Build cache key from normalised params
$params = $request->get_params();
$cache_key = ds_diamond_cache_key( $params );
$cached = wp_cache_get( $cache_key, 'ds_ring_builder' );
if ( $cached !== false ) {
return new WP_REST_Response( $cached, 200 );
}
// Build WHERE clause dynamically
$where = [ 'is_available = 1' ];
$values = [];
if ( ! empty( $params['shape'] ) ) {
$where[] = 'shape = %s';
$values[] = $params['shape'];
}
$where[] = 'carat BETWEEN %f AND %f';
$values[] = $params['carat_min'];
$values[] = $params['carat_max'];
$where[] = 'colour_sort BETWEEN %d AND %d';
$values[] = $params['colour_min'];
$values[] = $params['colour_max'];
$where[] = 'clarity_sort BETWEEN %d AND %d';
$values[] = $params['clarity_min'];
$values[] = $params['clarity_max'];
$where[] = 'price_zar BETWEEN %f AND %f';
$values[] = $params['price_min'];
$values[] = $params['price_max'];
if ( ! empty( $params['cut'] ) ) {
$cuts = array_map( 'sanitize_text_field', explode( ',', $params['cut'] ) );
$in = implode( ',', array_fill( 0, count( $cuts ), '%s' ) );
$where[] = "cut IN ({$in})";
$values = array_merge( $values, $cuts );
}
if ( ! empty( $params['lab'] ) ) {
$labs = array_map( 'sanitize_text_field', explode( ',', $params['lab'] ) );
$in = implode( ',', array_fill( 0, count( $labs ), '%s' ) );
$where[] = "lab IN ({$in})";
$values = array_merge( $values, $labs );
}
if ( ! empty( $params['fluorescence'] ) ) {
$fluors = array_map( 'sanitize_text_field', explode( ',', $params['fluorescence'] ) );
$in = implode( ',', array_fill( 0, count( $fluors ), '%s' ) );
$where[] = "fluorescence IN ({$in})";
$values = array_merge( $values, $fluors );
}
$where_sql = implode( ' AND ', $where );
// Sort
$sort_map = [
'price_asc' => 'price_zar ASC',
'price_desc' => 'price_zar DESC',
'carat_desc' => 'carat DESC, price_zar ASC',
'best_cut' => "FIELD(cut,'Excellent','Ideal','Very Good','Good','Fair'), price_zar ASC",
];
$order_by = $sort_map[ $params['sort'] ] ?? 'price_zar ASC';
// Pagination
$per_page = min( (int) $params['per_page'], 48 );
$offset = ( max( 1, (int) $params['page'] ) - 1 ) * $per_page;
// Count query (for pagination)
$count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM {$table} WHERE {$where_sql}",
...$values
)
);
// Results query
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT id, sku, shape, carat, colour, clarity, cut, polish, symmetry,
fluorescence, lab, certificate_no, measurements,
length_mm, width_mm, depth_mm, depth_pct, table_pct,
price_zar, image_url, video_url, certificate_url,
last_synced
FROM {$table}
WHERE {$where_sql}
ORDER BY {$order_by}
LIMIT %d OFFSET %d",
...array_merge( $values, [ $per_page, $offset ] )
)
);
// Facet counts for active filter UI
$facets = ds_rb_get_facets( $table, $where_sql, $values );
$response = [
'total' => $count,
'pages' => (int) ceil( $count / $per_page ),
'page' => (int) $params['page'],
'results' => $results,
'facets' => $facets,
'cache' => 'miss',
];
wp_cache_set( $cache_key, $response, 'ds_ring_builder', 15 * MINUTE_IN_SECONDS );
return new WP_REST_Response( $response, 200 );
}
/**
* Facet counts — how many results exist for each filter value
* within the current active filter set. Used to grey out
* unavailable filter options in the UI.
*/
function ds_rb_get_facets( string $table, string $where_sql, array $values ): array {
global $wpdb;
$shapes = $wpdb->get_results(
$wpdb->prepare(
"SELECT shape, COUNT(*) as count FROM {$table}
WHERE {$where_sql} GROUP BY shape ORDER BY count DESC",
...$values
)
);
$labs = $wpdb->get_results(
$wpdb->prepare(
"SELECT lab, COUNT(*) as count FROM {$table}
WHERE {$where_sql} GROUP BY lab ORDER BY count DESC",
...$values
)
);
return [
'shapes' => $shapes,
'labs' => $labs,
];
}
Setting Compatibility Query
When the buyer progresses to setting selection, the system needs to query the WooCommerce setting catalogue filtered by compatibility with the selected stone:
/**
* Return settings compatible with a selected diamond's shape and dimensions.
* Route: GET /wp-json/diamond-stack/v1/ring-builder/settings
*/
function ds_rb_get_compatible_settings( WP_REST_Request $request ): WP_REST_Response {
$shape = sanitize_text_field( $request->get_param('shape') );
$length_mm = (float) $request->get_param('length_mm');
$width_mm = (float) $request->get_param('width_mm');
$metal = sanitize_text_field( $request->get_param('metal') ?? 'white-gold' );
// Query WooCommerce products with ring builder compatibility meta
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => [
'relation' => 'AND',
[
'key' => '_ds_rb_enabled',
'value' => '1',
'compare' => '=',
],
[
'key' => '_ds_rb_compatible_shapes',
'value' => $shape,
'compare' => 'LIKE',
],
[
'key' => '_ds_rb_centre_min_mm',
'value' => $width_mm,
'compare' => '<=',
'type' => 'DECIMAL',
],
[
'key' => '_ds_rb_centre_max_mm',
'value' => $width_mm,
'compare' => '>=',
'type' => 'DECIMAL',
],
],
];
$query = new WP_Query( $args );
$settings = [];
foreach ( $query->posts as $post ) {
$base_price = (float) get_post_meta( $post->ID, '_price', true );
$metal_data = ds_rb_get_metal_pricing( $post->ID, $metal );
$settings[] = [
'id' => $post->ID,
'name' => $post->post_title,
'slug' => $post->post_name,
'description' => $post->post_excerpt,
'image' => get_the_post_thumbnail_url( $post->ID, 'large' ),
'metals' => ds_rb_get_available_metals( $post->ID ),
'price_zar' => $metal_data['price_zar'],
'metal_label' => $metal_data['label'],
'style_tags' => get_post_meta( $post->ID, '_ds_rb_style_tags', true ),
'centre_min' => (float) get_post_meta( $post->ID, '_ds_rb_centre_min_mm', true ),
'centre_max' => (float) get_post_meta( $post->ID, '_ds_rb_centre_max_mm', true ),
];
}
return new WP_REST_Response( [ 'settings' => $settings ], 200 );
}
Real-Time Price Synthesis
The persistent price bar that shows Stone + Setting = Total in real time requires a client-side calculation function that pulls the current stone price and the currently selected setting/metal combination price and sums them with the configured manufacturing cost:
// Ring builder state management (vanilla JS — no framework dependency)
const RingBuilder = {
state: {
selectedStone: null,
selectedSetting: null,
selectedMetal: 'white-gold',
manufacturingCost: 2500, // ZAR — fetched from wp_localize_script
},
updatePriceDisplay() {
const { selectedStone, selectedSetting, selectedMetal, manufacturingCost } = this.state;
const stonePrice = selectedStone ? parseFloat( selectedStone.price_zar ) : 0;
const settingPrice = selectedSetting
? parseFloat( selectedSetting.metals[ selectedMetal ]?.price_zar ?? selectedSetting.price_zar )
: 0;
const total = stonePrice + settingPrice + manufacturingCost;
document.getElementById('rb-price-stone').textContent
= selectedStone ? ds_format_zar( stonePrice ) : '—';
document.getElementById('rb-price-setting').textContent
= selectedSetting ? ds_format_zar( settingPrice ) : '—';
document.getElementById('rb-price-manufacturing').textContent
= ds_format_zar( manufacturingCost );
document.getElementById('rb-price-total').textContent
= ( stonePrice + settingPrice > 0 ) ? ds_format_zar( total ) : '—';
},
selectStone( stone ) {
this.state.selectedStone = stone;
this.updatePriceDisplay();
this.fetchCompatibleSettings();
this.renderStoneDetail( stone );
},
selectMetal( metal ) {
this.state.selectedMetal = metal;
this.updatePriceDisplay();
this.renderSettingDetail( this.state.selectedSetting );
},
};
function ds_format_zar( amount ) {
return 'R\u00a0' + Math.round( amount ).toLocaleString( 'en-ZA' );
}
Part Five: Mobile-First Performance Engineering
Mobile performance for a ring builder is not a standard page performance problem. The diamond filter interaction pattern — rapid successive filter changes as the buyer explores the option space — creates a specific performance challenge: debouncing.
Without debouncing, a buyer who moves the carat range slider from 1.0ct to 1.5ct triggers a new API request on every intermediate value: 1.01, 1.02, 1.03… 1.50. At 24 slider positions per second, this produces a flood of requests that overwhelms the server and produces a UI that is visually chaotic as results flash in and out.
The correct implementation debounces filter changes: a request is only fired when the buyer has stopped adjusting a filter for a defined interval (typically 300ms for sliders, 100ms for button selects):
let filterDebounceTimer = null;
function onFilterChange() {
clearTimeout( filterDebounceTimer );
filterDebounceTimer = setTimeout( () => {
ds_fetch_diamonds( RingBuilder.getFilterParams() );
}, 300 );
}
// Button-based filters (shape, cut, lab) use a shorter debounce
function onButtonFilterChange() {
clearTimeout( filterDebounceTimer );
filterDebounceTimer = setTimeout( () => {
ds_fetch_diamonds( RingBuilder.getFilterParams() );
}, 100 );
}
Image Loading Strategy
Diamond images from external feeds (RapNet, IDEX, Nivoda) are served from external CDN URLs. Loading 24 external images simultaneously on a results page creates a waterfall of parallel requests that degrades mobile performance.
The correct approach: lazy load all diamond images below the fold, use a low-resolution placeholder (a shape outline SVG) for stones without images rather than a broken image element, and preload the first six images in the initial result set:
<!-- First 6 results: preload with eager loading -->
<img src="[diamond-image-url]"
loading="eager"
width="240" height="240"
alt="1.24ct Round Brilliant Diamond — E / VS1">
<!-- Results 7+: lazy load -->
<img src="[diamond-image-url]"
loading="lazy"
width="240" height="240"
alt="1.31ct Round Brilliant Diamond — F / VS2">
<!-- No image available: shape SVG placeholder -->
<img src="/assets/ring-builder/shape-round.svg"
loading="lazy"
width="240" height="240"
alt="Round Brilliant Diamond silhouette">
Touch Interaction Optimisation
Range sliders for carat and price on mobile require larger touch targets than their desktop equivalents. The default HTML range input thumb is 16px — on a mobile device this produces a tap target that is below the WCAG minimum of 44x44px and results in interaction errors that frustrate buyers.
Implement custom range sliders with a minimum 44px thumb and 44px track height on mobile:
/* Mobile range slider — large touch target */
@media (max-width: 768px) {
.rb-range-input::-webkit-slider-thumb {
width: 44px;
height: 44px;
cursor: pointer;
background: var(--ds-gold);
border-radius: 50%;
border: 3px solid var(--ds-dark);
}
.rb-range-input::-webkit-slider-runnable-track {
height: 6px;
background: var(--ds-gold-dim);
border-radius: 3px;
}
}
Part Six: Conversion Mechanics — Closing the Gap Between Selection and Enquiry
The technical implementation and the UX architecture create the conditions for conversion. The conversion mechanics are the specific design decisions that close the gap between a buyer who has completed their selection and a buyer who submits the enquiry.
The 48-Hour Stone Hold
Communicate clearly that the selected stone will be held for 48 hours pending a consultation confirmation. This is not merely a logistical policy — it is a psychological commitment device. The buyer who is told their stone is being held has made a smaller commitment than a purchase, but a larger commitment than a browse. The 48-hour frame creates gentle urgency without the manipulative countdown timers that damage luxury brand positioning.
The implementation requires marking the stone as status = 'held' in ds_diamond_inventory and associating it with the enquiry record. The hold expires after 48 hours via a scheduled WP-CLI job that resets the status to available.
Social Proof Proximity to the Commitment Point
The summary and enquiry screen — the commitment point — should contain one piece of social proof from a buyer with a similar selection. Not a generic testimonial. A contextually matched one: if the buyer has selected a round brilliant, show a testimonial from a round brilliant customer. If they have selected a moissanite, show a moissanite customer testimonial.
This requires tagging testimonials with stone type attributes and retrieving the closest match at render time. The implementation effort is modest; the conversion impact is substantial because it reduces the specific doubt a buyer has at the commitment point — not “is this jeweller trustworthy?” but “has someone like me done this and been happy?”
The Abandonment Recovery Sequence
A buyer who progresses through stone selection and setting selection but does not submit the enquiry is the highest-intent unconverted visitor in your business. They deserve a recovery sequence — but one appropriate to the price point and the buying psychology.
If the buyer created an account or provided an email earlier in the session (ring size guide download, comparison save), a single follow-up email 24 hours later with the subject line “Your selection is still available” and the specific stone and setting details is appropriate. Not a generic abandoned cart reminder. A specific, personalised summary of exactly what they selected, with a direct link to resume the session and a low-friction re-entry point.
If the buyer did not provide an email, a persistent session storage of their selection allows the ring builder to present “Welcome back — your previous selection” on their next visit — without requiring a login and without the creepiness of tracking they did not consent to.
Part Seven: The SEO Architecture of the Ring Builder
A ring builder that converts brilliantly but contributes nothing to organic acquisition is a conversion asset without an acquisition channel. The ring builder needs to be discoverable through search.
The Ring Builder Landing Page
The ring builder itself — /ring-builder/ — should be a full landing page with editorial content above the interactive feature, not a blank tool. The page should:
- Target the primary commercial query cluster: “design your own engagement ring,” “custom ring builder,” “engagement ring configurator”
- Include an H1 that incorporates the primary target query
- Contain 300–400 words of editorial content explaining the process, the stone options, and what happens after the buyer submits their selection
- Carry
ProductandBreadcrumbListschema - Have a canonical tag pointing to itself (not to the homepage)
- Be included in the XML sitemap
The ring builder URL should not be in the exclusion list of the full-page cache. The page itself — the HTML shell above the interactive feature — is cacheable and should be cached. The diamond search results, loaded dynamically via JavaScript after page load, are not cached at the full-page level but are cached at the Redis object cache level as covered earlier in this series.
Deep-Link Architecture for Specific Selections
A buyer who selects a 1.5ct oval moissanite in the ring builder is performing an action that corresponds to a high-commercial-intent search query. If the ring builder updates the URL with the current filter state — /ring-builder/?shape=oval&stone=moissanite&carat_min=1.3&carat_max=1.7 — those URLs become deep-linkable and shareable. A buyer who shares their selection with a partner, or who saves it for later, returns to exactly the state they left.
These deep-link URLs are also indexable — with caution. The filter combinations that correspond to commercially significant query clusters (shape + stone type + carat range combinations with meaningful search volume) can be included in the sitemap and allowed to be indexed. The long-tail of low-volume filter combinations should carry noindex canonical tags pointing to the base ring builder URL.
This is a nuanced implementation that requires a judgment call per filter combination — it is not automated. But for a ring builder with an active SEO strategy, the five to ten deep-link pages that target high-volume commercial filter combinations are worth the implementation investment.
The Ring Builder as the Apex of the Diamond Stack Architecture
Every technical article in this series — the 50,000 SKU architecture, the RapNet field mapping, the dynamic metal pricing, the caching strategies, the multi-vendor feed blueprint — has been a component of this article. The ring builder is where all of those components assemble into a single user-facing experience.
The custom table schema handles 50,000 stones without touching wp_postmeta. The composite indexes return filter results in under 50ms. The Redis object cache serves repeat queries from memory. The REST endpoint handles mobile interaction patterns with debounced requests. The real-time pricing synthesises stone, setting, and metal costs live in the UI. The 48-hour hold creates commitment without requiring payment. The contextual testimonial reduces doubt at the submission point.
None of these elements works in isolation. A ring builder with a fast front end and a slow database is still a slow ring builder. A ring builder with excellent performance and a broken commitment threshold is a browsing tool, not a sales tool. A ring builder with a clean UX and a poor mobile implementation loses half the consideration-phase traffic before anyone reaches the commitment point.
The ring builder is the most complex feature in jewellery e-commerce and the one that rewards the most rigorous implementation. When every component is correctly built and correctly integrated, it produces a buying experience that the engineer buyer — the high-value, research-driven customer who will not be charmed into a purchase they have not verified — finds genuinely satisfying. And a satisfied engineer buyer, as the previous article in this series argued, becomes a precision-targeted referral engine.
That is the commercial case for building it right. Build it right once, and it works for every buyer who arrives with the intent to commit — for as long as the stones keep coming.
If you are building a ring builder for a jewellery business — whether integrating a live diamond feed, connecting a custom stone sourcing network, or building the configurator UI from scratch on WooCommerce — Diamond Stack’s Custom Ring Builder & Diamond API Integrations service is the complete implementation of the architecture described in this article. Every component covered here is part of the standard build. No shortcuts. No generic templates. No post-launch surprises.
Erwee Coetzee is the founder of SEO Gurus and the principal of Diamond Stack, a Cape Town–based WordPress development and technical SEO practice specialising in jewellery e-commerce architecture. He has been active in technical SEO since 2012 and published two SEO titles in 2026.
