求助:如何在WordPress中点击发布按钮后触发JavaScript Fetch POST请求
Hey there! As someone who's navigated WordPress's unique quirks, I totally get why this feels trickier than a vanilla JS project. Let's walk through two solid ways to make this happen—one using frontend JavaScript (like you asked) and a more reliable backend approach that avoids common pitfalls.
WordPress admin uses specific selectors for its publish buttons, so we'll need to support both the Gutenberg (block) editor and the classic editor. Here's how to set it up:
Step 1: Load Your Custom JS in the Admin
First, add this code to your theme's functions.php file to register and load your script only on post edit pages:
function enqueue_custom_publish_script() { // Target only post edit screens $screen = get_current_screen(); if ( $screen->base === 'post' && $screen->post_type === 'post' ) { wp_enqueue_script( 'custom-publish-fetch', get_template_directory_uri() . '/js/custom-publish-fetch.js', array( 'wp-api' ), // Leverage WordPress's built-in API scripts for Fetch support wp_get_theme()->get('Version'), true // Load in the footer for better performance ); // Pass critical data to your JS (securely) wp_localize_script( 'custom-publish-fetch', 'publishFetchData', array( 'thirdPartyUrl' => 'https://your-third-party-url.com/endpoint', // Replace with your URL 'postId' => get_the_ID(), 'nonce' => wp_create_nonce( 'wp_rest' ) // Security token to prevent CSRF attacks ) ); } } add_action( 'admin_enqueue_scripts', 'enqueue_custom_publish_script' );
Step 2: Write the Fetch Logic
Create a new file js/custom-publish-fetch.js in your theme folder with this code:
document.addEventListener('DOMContentLoaded', function() { // Grab publish buttons for both Gutenberg and classic editors const publishButtons = [ document.querySelector('.editor-post-publish-button'), document.querySelector('#publish') ].filter(btn => btn !== null); publishButtons.forEach(button => { button.addEventListener('click', async function() { // Add a small delay to let WordPress save the post first setTimeout(async () => { try { // Fetch the latest post data via WordPress REST API const postResponse = await fetch(`/wp-json/wp/v2/posts/${publishFetchData.postId}`, { headers: { 'X-WP-Nonce': publishFetchData.nonce } }); const postData = await postResponse.json(); // Build your payload with the data the third party needs const payload = { id: postData.id, title: postData.title.rendered, content: postData.content.rendered, status: postData.status, published_at: postData.date_gmt // Add any other fields you need here }; // Send the POST request to the third party const thirdPartyResponse = await fetch(publishFetchData.thirdPartyUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!thirdPartyResponse.ok) { throw new Error(`Request failed: ${thirdPartyResponse.status}`); } console.log('Successfully sent post data to third party!'); } catch (error) { console.error('Error sending data:', error); // Optional: Add a user-facing alert here, like a WP admin notice } }, 1000); // 1-second delay ensures WordPress finishes saving before we fetch data }); }); });
While the frontend approach works, it has flaws (like users disabling JS or network delays). For a robust solution, use WordPress's built-in hooks to trigger the request after the post is successfully published:
Add this code to your theme's functions.php file:
function send_post_to_third_party_on_publish( $post_id ) { // Skip autosaves and revisions to avoid duplicate requests if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) { return; } // Get the full post object $post = get_post( $post_id ); // Build your payload with the required data $payload = array( 'id' => $post->ID, 'title' => get_the_title( $post_id ), 'content' => apply_filters( 'the_content', $post->post_content ), 'status' => $post->post_status, 'published_at' => $post->post_date_gmt // Add other fields as needed ); // Configure the POST request $args = array( 'body' => json_encode( $payload ), 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ), 'timeout' => 15, 'blocking' => false, // Don't slow down WordPress by waiting for a response 'sslverify' => true, // Set to false only if the third party uses an invalid SSL cert ); // Send the request using WordPress's secure built-in function $response = wp_remote_post( 'https://your-third-party-url.com/endpoint', $args ); // Log results for debugging (check wp-content/debug.log if WP_DEBUG is enabled) if ( is_wp_error( $response ) ) { error_log( 'Third party request failed: ' . $response->get_error_message() ); } else { error_log( 'Third party request succeeded. Response code: ' . wp_remote_retrieve_response_code( $response ) ); } } // Trigger when a post is published add_action( 'publish_post', 'send_post_to_third_party_on_publish', 10, 1 );
- Security: Always use nonces (like in the frontend code) to prevent cross-site request forgery. Never hardcode sensitive data in JS.
- Reliability: The backend approach is preferred because it runs regardless of frontend issues (JS disabled, network drops).
- Testing: Enable
WP_DEBUGin yourwp-config.phpto see error logs, and test with a staging site first. - Payload Format: Double-check that your payload matches exactly what the third party expects (data types, field names, etc.).
内容的提问来源于stack exchange,提问作者Andrei Pirvu

