Introduction
In today's digital real estate and construction landscape, immersive 3D home models have become essential tools for showcasing properties. This guide will walk you through creating a custom WordPress REST API that integrates Matterport 3D home models into your website, complete with a search wizard, cost estimation features, and property matching capabilities.
Why Build a Custom WordPress REST API for Matterport Integration?
- Seamless Integration: Connect Matterport's 3D tours directly with your WordPress site
- Custom Search Functionality: Allow users to find homes based on style, size, features, and budget
- Cost Estimation: Provide instant construction cost estimates based on user selections
- Data Management: Maintain a database of available property models with detailed specifications
- Enhanced User Experience: Offer interactive property exploration without leaving your site
Step-by-Step Implementation Guide
1. Database Setup
First, we create a custom database table to store Matterport model information:
function fox_create_matterport_listings_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'matterport_model_listings11';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
model_id varchar(255) NOT NULL,
title varchar(255) NOT NULL,
description text NOT NULL,
style varchar(100) NOT NULL,
size int NOT NULL,
features text NOT NULL,
cost decimal(12,2) NOT NULL,
img varchar(255) NOT NULL,
floor_img_link varchar(255) NOT NULL,
bedrooms int DEFAULT 3,
bathrooms decimal(3,1) DEFAULT 2.0,
stories int DEFAULT 1,
garage_spaces int DEFAULT 2,
kitchen_type varchar(50) DEFAULT 'standard',
additional_rooms text DEFAULT '',
flooring_type varchar(50) DEFAULT 'engineered',
countertops_type varchar(50) DEFAULT 'quartz',
cabinets_type varchar(50) DEFAULT 'standard',
appliances_type varchar(50) DEFAULT 'standard',
bath_fixtures_type varchar(50) DEFAULT 'standard',
is_renovation tinyint(1) DEFAULT 0,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY model_id (model_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// Insert default data if table is empty
$count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
if ($count == 0) {
// Insert sample data (see full code for complete dataset)
$default_data = [
[
'model_id' => 'zyDSyRXxMH8',
'title' => 'Modern Suburban Home',
'description' => 'A sleek, open-concept home...',
// ... other fields
],
// ... more models
];
foreach ($default_data as $data) {
$wpdb->insert($table_name, $data);
}
}
}
register_activation_hook(__FILE__, 'fox_create_matterport_listings_table');
2. REST API Endpoint Creation
Create endpoints to fetch featured listings and handle search submissions:
add_action('rest_api_init', function () {
// Get featured listings
register_rest_route('fox-api/v1', '/get-featured-listings', [
'methods' => 'GET',
'callback' => 'get_featured_listings',
'permission_callback' => function($request) {
$nonce = $request->get_header('X-WP-Nonce');
return wp_verify_nonce($nonce, 'wp_rest');
}
]);
// Handle search submissions
register_rest_route('fox-api/v1', '/send-search-data', [
'methods' => 'POST',
'callback' => 'handle_search_data',
'permission_callback' => '__return_true'
]);
});
function get_featured_listings() {
global $wpdb;
$table_name = $wpdb->prefix . 'matterport_model_listings11';
$results = $wpdb->get_results("SELECT * FROM $table_name", ARRAY_A);
if (empty($results)) {
return new WP_Error('no_listings', 'No listings found', ['status' => 404]);
}
$active_models = [];
foreach ($results as $result) {
if (check_matterport_model_active($result['model_id'])) {
$result['features'] = json_decode($result['features']);
$result['id'] = $result['model_id'];
$active_models[] = $result;
}
}
return new WP_REST_Response([
'status' => 'success',
'data' => $active_models
], 200);
}
3. Matterport Model Validation
Implement a function to verify if Matterport models are still active:
function check_matterport_model_active($model_id) {
$embed_url = "https://my.matterport.com/show/?m=$model_id";
$response = wp_remote_head($embed_url, [
'timeout' => 5,
'redirection' => 0
]);
if (is_wp_error($response)) {
error_log("Matterport check error for model $model_id: " . $response->get_error_message());
return false;
}
$response_code = wp_remote_retrieve_response_code($response);
return $response_code === 200;
}
4. Frontend JavaScript Implementation
The frontend JavaScript handles the interactive wizard, property display, and API communication:
document.addEventListener('DOMContentLoaded', function() {
// Global state
let currentStepWizard = 1;
const totalWizardQuestions = 8;
const galleryStep = 9;
const viewerStep = 10;
let MATTERPORT_MODELS = [];
// Fetch listings from API
function fetchFeaturedListings() {
fetch('http://localhost:10014/wp-json/fox-api/v1/get-featured-listings', {
headers: {
'X-WP-Nonce': foxApiSettings.nonce
},
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
MATTERPORT_MODELS = data.data;
renderPropertyCards(MATTERPORT_MODELS);
}
});
}
// Render property cards
function renderPropertyCards(models) {
// Implementation for displaying property cards
}
// Wizard modal functions
function openWizardModal(initialStep = 1, modelId = null) {
// Show wizard modal
}
function closeWizardModal() {
// Close wizard modal
}
// Form submission handling
function submitWizardData() {
const formData = new FormData();
// Collect form data
fetch('http://localhost:10014/wp-json/fox-api/v1/send-search-data', {
method: 'POST',
headers: {
'X-WP-Nonce': foxApiSettings.nonce
},
body: formData,
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
showWizardStep(galleryStep);
}
});
}
// Initialize
fetchFeaturedListings();
});
5. Cost Calculation System
Implement a comprehensive cost estimation system:
const pricingData = {
baseCostPerSqFt: 150,
styleMultipliers: {
modern: 1.1,
traditional: 1.0,
// ... other styles
},
// ... other cost factors
};
function calculateCosts(formData) {
const costs = {};
let totalSquareFootage = formData.size || formData.sizeMax || 0;
// Base construction cost
costs.baseConstruction = totalSquareFootage * pricingData.baseCostPerSqFt *
(pricingData.styleMultipliers[style] || 1.0);
// Add costs for garage, bedrooms, bathrooms, etc.
costs.garage = pricingData.garageCost[formData.garage] || 0;
costs.bedrooms = pricingData.bedroomCost[formData.bedrooms] || 0;
// ... other cost calculations
// Calculate total
costs.total = costs.baseConstruction + costs.garage + costs.bedrooms + /* ... */;
return costs;
}
6. Email Notification System
Set up email notifications for form submissions:
function send_data_to_email($submission_data) {
$to = "rob@foxcertifiedcontractors.com";
$subject = 'New Home Style Search Submission';
$body = "<h2>New Home Style Search Submission</h2>";
// Build email content from submission data
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: Fox Certified Contractors <noreply@' . $_SERVER['HTTP_HOST'] . '>'
);
return wp_mail($to, $subject, $body, $headers);
}
SEO Considerations
- Structured Data: Implement schema.org markup for properties
- Performance Optimization:
- Lazy load Matterport iframes
- Optimize images and assets
- Mobile Responsiveness: Ensure the wizard works perfectly on all devices
- Content Strategy:
- Create detailed pages for each property model
- Generate unique meta descriptions
- URL Structure: Use clean, descriptive URLs for property pages
Advanced Features
Property Matching Algorithm:
function renderMatterportGalleryWizard() {
let selections = getUserSelections();
// Score all models based on user selections
let scoredModels = MATTERPORT_MODELS.map(model => {
let score = 0;
let isExactMatch = true;
// Style match
if (selections.styles.length > 0 && !selections.styles.includes(model.style)) {
isExactMatch = false;
score += 30;
} else {
score += 100;
}
// Size match
if (model.size >= selections.sizeMin && model.size <= selections.sizeMax) {
score += 50;
} else {
isExactMatch = false;
let sizeDiff = Math.min(
Math.abs(model.size - selections.sizeMin),
Math.abs(model.size - selections.sizeMax)
);
score += Math.max(10, 50 - sizeDiff/100);
}
return { model, score, isExactMatch };
});
// Sort by exact match first, then by score
scoredModels.sort((a, b) => {
if (a.isExactMatch !== b.isExactMatch) {
return b.isExactMatch - a.isExactMatch;
}
return b.score - a.score;
});
// Display top matches
let topModels = scoredModels.slice(0, 10);
// ... render results
}
Interactive Floor Plans:
// Floor plan download functionality
downloadFloorPlanBtn.addEventListener('click', function(event) {
event.preventDefault();
const modelId = matterportViewerWizard?.src?.split('m=')[1]?.split('&')[0];
const selectedModel = MATTERPORT_MODELS.find(model => model.id === modelId);
if (selectedModel?.floor_img_link) {
const a = document.createElement('a');
a.href = selectedModel.floor_img_link;
a.download = `${selectedModel.title.replace(/\s+/g, '_')}_Floor_Plan.jpg`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
});
Printable Estimates:
function generatePrintableEstimate() {
// Get model data and user selections
const model = MATTERPORT_MODELS.find(m => m.id === currentModelId);
const selections = getUserSelections();
// Calculate costs
const calculatedCosts = calculateCosts({
...selections,
styles: [model.style.toLowerCase()],
size: model.size
});
// Generate printable HTML content
const printContent = `<!DOCTYPE html>
<html>
<head>
<title>Construction Estimate - ${model.title}</title>
<style>/* ... */</style>
</head>
<body>
<!-- Detailed estimate content -->
</body>
</html>`;
// Open print window
const printWindow = window.open('', '_blank');
printWindow.document.write(printContent);
printWindow.document.close();
printWindow.print();
}
Maintenance and Optimization
Scheduled Cleanup:
// Define cron hook
define('MATTERPORT_CLEANUP_CRON_HOOK', 'matterport_cleanup_inactive_models_cron');
// Schedule cleanup
function schedule_matterport_cleanup_cron() {
if (!wp_next_scheduled(MATTERPORT_CLEANUP_CRON_HOOK)) {
wp_schedule_event(time(), 'daily', MATTERPORT_CLEANUP_CRON_HOOK);
}
}
add_action('wp', 'schedule_matterport_cleanup_cron');
// Cleanup function
function delete_inactive_matterport_models() {
global $wpdb;
$table_name = $wpdb->prefix . 'matterport_model_listings11';
$model_ids_to_check = $wpdb->get_col("SELECT model_id FROM $table_name");
$inactive_model_ids = [];
foreach ($model_ids_to_check as $model_id) {
if (!check_matterport_model_active($model_id)) {
$inactive_model_ids[] = $model_id;
}
}
if (!empty($inactive_model_ids)) {
$placeholders = implode(', ', array_fill(0, count($inactive_model_ids), '%s'));
$sql = $wpdb->prepare(
"DELETE FROM $table_name WHERE model_id IN ($placeholders)",
$inactive_model_ids
);
$wpdb->query($sql);
}
}
add_action(MATTERPORT_CLEANUP_CRON_HOOK, 'delete_inactive_matterport_models');
Performance Monitoring:
- Track API response times
- Monitor Matterport embed loading performance
- Optimize database queries
Security Considerations
Nonce Verification:
register_rest_route('fox-api/v1', '/get-featured-listings', [
'methods' => 'GET',
'callback' => 'get_featured_listings',
'permission_callback' => function($request) {
$nonce = $request->get_header('X-WP-Nonce');
return wp_verify_nonce($nonce, 'wp_rest');
}
]);
Data Sanitization:
function handle_search_data(WP_REST_Request $request) {
$data = $request->get_params();
$sanitized_data = array_map('sanitize_text_field', $data);
// ... process data
}
File Upload Security:
$upload = wp_handle_upload($files['survey_file'], [
'test_form' => false,
'mimes' => [
'pdf' => 'application/pdf',
'dwg' => 'application/acad',
'dxf' => 'application/dxf',
'jpg|jpeg' => 'image/jpeg',
'png' => 'image/png'
]
]);
Conclusion
This comprehensive WordPress REST API solution for Matterport integration provides:
- A complete database of 3D home models with detailed specifications
- An interactive search wizard with step-by-step filtering
- Accurate cost estimation based on user selections
- Automated email notifications for leads
- Regular maintenance to ensure only active models are shown
- Robust security measures to protect your site and user data
By implementing this system, you can significantly enhance your website's real estate presentation capabilities, improve user engagement, and generate more qualified leads.
For developers looking to implement this solution, remember to:
- Carefully review all security considerations
- Test thoroughly with your specific Matterport models
- Customize the cost calculation parameters to match your pricing
- Monitor performance and optimize as needed
- Regularly update your model database as your portfolio changes
This implementation represents a powerful tool for any construction company, real estate agency, or property developer looking to leverage Matterport's 3D technology within a WordPress environment.
Top comments (0)