Integration Recipes
Practical examples for the most common addon and integration patterns.
Adding an integration with API key field
Three steps: register the field, register the option key, inject your runtime script.
// 1. Surface the field in Global Settings → Integrations
add_filter( 'tncfb3d_integration_fields', function( $groups, $options ) {
$groups['my_service'] = [
'label' => __( 'My Service', 'my-textdomain' ),
'fields' => [
'my_service_api_key' => [
'type' => 'password',
'label' => 'API Key',
],
],
];
return $groups;
}, 10, 2 );
// 2. Allow the option key to be saved
add_filter( 'tncfb3d_integration_keys', function( $keys ) {
$keys[] = 'my_service_api_key';
return $keys;
} );
// 3. Inject your script at viewer body end
add_action( 'tncfb3d_viewer_body_end', function( $post_id, $payload ) {
$key = tncfb3d_opt( get_option( TNC_FLIPBOOK_3D_OPTION, [] ), 'my_service_api_key' );
echo "<script>window.MyService.init( '" . esc_js( $key ) . "' );</script>";
}, 10, 2 );
Custom metabox tab
add_filter( 'tncfb3d_metabox_tabs', function( $tabs ) {
$tabs['my_tab'] = [ 'label' => 'My Tab', 'icon' => 'dashicons-admin-tools' ];
return $tabs;
} );
add_action( 'tncfb3d_metabox_tab_content_my_tab', function( $post, $meta, $schema ) {
$value = get_post_meta( $post->ID, '_tncfb3d_my_field', true );
?>
<input name="_tncfb3d_my_field" value="<?php echo esc_attr( $value ); ?>">
<?php
}, 10, 3 );
Custom settings tab
add_filter( 'tncfb3d_settings_tabs', function( $tabs ) {
$tabs['my_tab'] = 'My Tab';
return $tabs;
} );
add_action( 'tncfb3d_settings_tab_content_my_tab', function( $options ) {
// render fields here; submit handler is shared
} );
Force-disable a toolbar item
Useful for embedded-as-iframe variants where you want a specific button gone:
add_filter( 'tncfb3d_config_toolbar', function( $toolbar, $post_id ) {
$toolbar['download'] = false;
return $toolbar;
}, 10, 2 );
Gate access (paywall)
add_filter( 'tncfb3d_content_access', function( $gating, $post_id ) {
if ( ! my_user_has_paid( $post_id ) ) {
$gating['preview_pages'] = 5;
$gating['gating_message'] = __( 'Upgrade to read the full document.', 'my-td' );
$gating['purchase_button_text'] = __( 'Buy now', 'my-td' );
$gating['purchase_url'] = wc_get_checkout_url();
}
return $gating;
}, 10, 2 );
The viewer applies the gating overlay (.tncfb-gating-overlay) automatically.
Listen to viewer events from the host page
The viewer is in an iframe — bridge events via postMessage:
window.addEventListener('message', e => {
if (e.data?.type !== 'tncfb-event') return;
if (e.data.event === 'page-changed') {
myAnalytics.track('flipbook_page', {
id: e.data.id,
page: e.data.detail.page,
});
}
});
Viewer plugin (inside the iframe)
If you control the viewer template (e.g. through tncfb3d_viewer_body_end), use fb.use():
window.__tncfb.instance.use({
name: 'my-tracker',
init(fb) {
fb.on('page-changed', e => {
console.log('Page', e.detail.page);
});
},
});
Custom JSON-LD schema
add_filter( 'tncfb3d_seo_schema', function( $schema, $post_id ) {
$schema['@type'] = 'Book';
$schema['author'] = [ '@type' => 'Person', 'name' => 'Jane Doe' ];
return $schema;
}, 10, 2 );
Customize the iframe
add_filter( 'tncfb3d_iframe_attributes', function( $attrs, $post_id ) {
$attrs['allow'] = 'fullscreen';
$attrs['loading'] = 'eager';
$attrs['scrolling'] = 'no';
return $attrs;
}, 10, 2 );
React to flipbook lifecycle
add_action( 'tncfb3d_flipbook_created', function( $post_id ) {
// e.g. send a Slack notification, build a search index entry
} );
add_action( 'tncfb3d_flipbook_deleted', function( $post_id ) {
// cleanup external resources
} );
Override the download filename
add_filter( 'tncfb3d_config_download_filename', function( $name, $post_id ) {
return sanitize_file_name( get_the_title( $post_id ) ) . '.pdf';
}, 10, 2 );
For the full hook list see Actions & Filters. For the meta keys you can read/write see Post Meta Schema.