diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
index 5ea7aff..d9d7e28 100644
--- src/wp-admin/js/customize-controls.js
+++ src/wp-admin/js/customize-controls.js
@@ -1017,12 +1017,12 @@
 						}
 
 						// Check for cheaters.
-						if ( '-1' === response ) {
+						if ( '-1' === response || 'cheatin' === response.data ) {
 							self.cheatin();
 							return;
 						}
 
-						api.trigger( 'saved' );
+						api.trigger( 'saved', response.data );
 					} );
 				};
 
diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
index 5e2ba5d..c40933e 100644
--- src/wp-includes/class-wp-customize-manager.php
+++ src/wp-includes/class-wp-customize-manager.php
@@ -596,10 +596,14 @@ final class WP_Customize_Manager {
 	 * @since 3.4.0
 	 */
 	public function save() {
-		if ( ! $this->is_preview() )
-			die;
+		if ( ! $this->is_preview() ) {
+			wp_send_json_error( 'not_preview' );
+		}
 
-		check_ajax_referer( 'save-customize_' . $this->get_stylesheet(), 'nonce' );
+		$action = 'save-customize_' . $this->get_stylesheet();
+		if ( ! check_ajax_referer( $action, 'nonce', false ) ) {
+			wp_send_json_error( 'cheatin' );
+		}
 
 		// Do we have to switch themes?
 		if ( ! $this->is_theme_active() ) {
@@ -634,7 +638,16 @@ final class WP_Customize_Manager {
 		 */
 		do_action( 'customize_save_after', $this );
 
-		die;
+		/**
+		 * Filter response data for customize_save Ajax request.
+		 *
+		 * @since 4.1.0
+		 *
+		 * @param array $data
+		 * @param WP_Customize_Manager $this WP_Customize_Manager instance.
+		 */
+		$response = apply_filters( 'wp_customize_save_response', array(), $this );
+		wp_send_json_success( $response );
 	}
 
 	/**
