Developer reference
Code lives under the BytCrush\ namespace in includes/. The prefix for options, meta keys and hooks is bytcrush_. The REST namespace is bytcrush/v1.
Filters
bytcrush_skip_auto_optimize
Skip automatic optimization for a specific upload. The image stays pending and can still be optimized by a bulk run or by hand.
add_filter( 'bytcrush_skip_auto_optimize', function ( $skip, $attachment_id ) {
// e.g. leave uploads to a "Print files" folder alone.
$file = get_attached_file( $attachment_id );
return $skip || false !== strpos( (string) $file, '/print/' );
}, 10, 2 );
bytcrush_mimes
The attachment mime types BytCrush works on. Default: image/jpeg, image/png, image/webp, image/gif. The engine can only process these four, so this is mainly useful for removing one.
add_filter( 'bytcrush_mimes', function ( $mimes ) {
return array_diff( $mimes, array( 'image/gif' ) ); // never touch GIFs.
} );
bytcrush_levels
The compression presets shown on the Settings screen, keyed by slug. Each preset is an array:
| Key | Type | Meaning |
|---|---|---|
label |
string | Card title |
hint |
string | Card description |
jpeg |
int | JPEG quality, 1–100 |
webp |
int | WebP quality, 1–100 |
avif |
int | AVIF quality (added by BytCrush at priority 10 when missing) |
subsample |
bool | 4:2:0 chroma subsampling for JPEG |
png_lossy |
bool | Palette PNGs (honoured by the Ultra module, Imagick only) |
lossless |
bool | Lossless WebP copies of PNGs |
pro |
bool | Locked without Pro |
add_filter( 'bytcrush_levels', function ( $levels ) {
$levels['balanced']['jpeg'] = 76;
return $levels;
} );
A saved level that no longer exists falls back to balanced.
bytcrush_sibling_formats
The next-gen copies created for one file. Only the webp and avif keys are used.
apply_filters( 'bytcrush_sibling_formats', $siblings, $settings, $level, $format );
// $siblings: array( 'webp' => array( 'quality' => 80, 'lossless' => false, 'sources' => array( 'jpeg', 'png', 'gif' ) ) )
// $format: format of the file being processed: jpeg | png | webp | gif
A copy is created only when the file's format is in that entry's sources. Removing an entry deletes that copy from the file the next time it's processed.
// No WebP copies for PNGs.
add_filter( 'bytcrush_sibling_formats', function ( $siblings, $settings, $level, $format ) {
if ( 'png' === $format ) {
unset( $siblings['webp'] );
}
return $siblings;
}, 10, 4 );
bytcrush_served_formats
The formats delivered to browsers, best first (array( 'avif', 'webp' ) when both are on). Used by picture tags and by the rewrite rules.
apply_filters( 'bytcrush_served_formats', $formats, $settings );
The rewrite rules are written when settings are saved, so save the Settings screen once after changing this filter.
bytcrush_driver
Force the image library: 'imagick' or 'gd'. Empty (the default) means Imagick when available, otherwise GD. Only 'gd' changes anything in practice, since Imagick is already preferred.
add_filter( 'bytcrush_driver', function () {
return 'gd';
} );
bytcrush_encoded
Post-process an encode. Pro's Smart target file size uses it to re-encode until the file fits. The callback must return the same shape.
apply_filters( 'bytcrush_encoded', $encoded, $driver, $format, $flags, $options );
// $encoded: array( 'blob' => string, 'quality' => int, 'resized' => bool )
// $driver: BytCrush\Engine\Driver\Driver (may be resized by the callback)
// $format: jpeg | png | webp | avif
// $flags: array( 'subsample' => bool, 'png_lossy' => bool, 'lossless' => bool )
// $options: the compress options, including 'target_bytes' and 'min_width'
bytcrush_img_tag
Filter each <img> tag of a front-end page. The page is buffered and processed once; <img> tags inside <picture>, <noscript>, <script>, <style>, <textarea> and HTML comments are skipped. Picture delivery hooks in at priority 20 (Pro's page fixes at 5). The page is only buffered when at least one callback is attached.
add_filter( 'bytcrush_img_tag', function ( $tag, $index ) {
// $index: 0-based position among the page's images.
return 0 === $index ? str_replace( '<img ', '<img fetchpriority="high" ', $tag ) : $tag;
}, 10, 2 );
bytcrush_picture_enabled
Return false to skip <picture> wrapping for the current request.
add_filter( 'bytcrush_picture_enabled', function ( $enabled ) {
return $enabled && ! is_page( 'gallery' );
} );
bytcrush_buffer_enabled
Return false to turn off all of BytCrush's HTML processing for the current request (picture tags and Pro page fixes).
bytcrush_bulk_time_budget
Seconds one bulk request keeps processing images before it returns. Default 20. Applies to the dashboard runner, background batches and Restore all. Lower it on hosts with a short PHP time limit.
add_filter( 'bytcrush_bulk_time_budget', function () {
return 10;
} );
bytcrush_bg_dispatch_url
The URL the server calls to start the next background batch. Default: admin_url( 'admin-ajax.php?action=bytcrush_bg' ). Change it when the site can't reach itself on its public address, for example behind a proxy. The request is a non-blocking POST carrying the run's random token; the handler answers 403 without a valid one.
apply_filters( 'bytcrush_bg_dispatch_url', $url );
The request is sent with WordPress's https_local_ssl_verify filter value for certificate checks.
Actions
| Action | Arguments | Fires when |
|---|---|---|
bytcrush_optimized |
$attachment_id, $result |
BytCrush has run its pipeline on an image. $result has status (optimized, error or skipped), message, and for successes before, after and served byte totals. |
bytcrush_restored |
$attachment_id, $restored (number of files put back) |
An image's originals were restored. |
bytcrush_settings_saved |
$new, $previous |
Settings were saved. BytCrush uses it to rewrite the .htaccess rules. |
bytcrush_imagick_png |
$image (Imagick), $flags |
Just before a PNG is encoded with Imagick. |
bytcrush_fs_loaded |
none | The Freemius SDK (or the built-in stub) is ready. |
add_action( 'bytcrush_optimized', function ( $id, $result ) {
if ( 'error' === $result['status'] ) {
error_log( "BytCrush could not optimize #{$id}: {$result['message']}" );
}
}, 10, 2 );
Functions
| Function | Returns |
|---|---|
bytcrush_settings() |
The effective settings array (stored values over defaults, with Pro-only options off when Pro isn't active). |
bytcrush_format_bytes( $bytes ) |
A human-readable size, such as 1.4 MB. |
bytcrush_percent( $before, $after ) |
The reduction as a percentage, 0–100, one decimal. |
Settings keys: level, auto_optimize, backup, strip_metadata, resize, max_width, max_height, webp, avif, delivery (picture, rewrite or off), target_size, target_kb, background, fix_srcset, fix_dimensions, fix_lazy, remove_data. Defaults are listed in the Settings reference.
REST API
All routes are under /wp-json/bytcrush/v1/ and need a logged-in user with a REST nonce, as the admin screens use them.
| Route | Method | Permission | Does |
|---|---|---|---|
/stats |
GET | manage_options |
Library totals and recent failures |
/settings |
GET, POST | manage_options |
Read or save settings (POST takes a JSON object of keys to change) |
/bulk/start |
POST | manage_options |
Checks folders and recovers interrupted images before a run |
/bulk/run |
POST | manage_options |
Processes pending images for one time budget |
/bulk/retry |
POST | manage_options |
Puts every failed image back in the queue |
/bulk/restore |
POST | manage_options |
Restores originals for one time budget |
/background, /background/start, /background/stop, /background/tick |
GET / POST | manage_options |
Status, start, stop and a browser-driven batch of the background run |
/image/{id}/optimize |
POST | upload_files and edit_post on that image |
Optimizes one image. force: true restores the original first. |
/image/{id}/restore |
POST | upload_files and edit_post on that image |
Restores one image |
Pro adds /audit/analyze, /audit/fix and /audit/fixes (manage_options).
Data the plugin stores
| What | Name |
|---|---|
| Settings | option bytcrush_settings |
| Version | option bytcrush_version |
| Backup folder name | option bytcrush_backup_dirname |
| Background run | options bytcrush_bg_run, bytcrush_bg_state; scheduled event bytcrush_bg_cron (every minute, only while a run is active) |
| Cached totals | transients bytcrush_stats, bytcrush_backup_size; option bytcrush_stats_flushed |
| Per-image locks | options _bytcrush_lock_{id} (removed when the image is done) |
| Per-image results | post meta _bytcrush, _bytcrush_status, _bytcrush_before, _bytcrush_after, _bytcrush_served |
| Dismissed notice | user meta bytcrush_notice_dismissed |
| Page audit (Pro) | options bytcrush_audit_history, bytcrush_lcp_pages, bytcrush_sized_pages, bytcrush_has_page_fixes |
_bytcrush_status is optimized, skipped, error or processing. An image without it is pending.
Deleting _bytcrush_status (and the other _bytcrush* meta) for an image puts it back in the queue without touching its files.
Code map
| Folder | Contents |
|---|---|
includes/Engine/ |
Optimizer (per-image pipeline and restore), Compressor (single-file encoder), Backup, Background, Stats, Avif, Driver/ (Imagick and GD) |
includes/Delivery/ |
Buffer (front-end HTML processing), Picture, Rewrite (.htaccess rules) |
includes/Core/ |
Plugin, Settings, Hooks (upload and delete hooks), Activator, Uninstaller, Lock |
includes/Admin/ |
Admin (screens), MediaColumn |
includes/Rest/ |
Controller |
includes/Freemius/ |
Gate (plan checks), Stub |
includes/Pro/ |
Premium-only modules: Audit, Fixer, Ultra, TargetSize, Media. Not included in the free build. |
views/ |
Admin screen templates |