Skip to content

Instantly share code, notes, and snippets.

@gursuj
Created June 14, 2026 23:52
Show Gist options
  • Select an option

  • Save gursuj/8869cfbd0b857893feac941e07f55623 to your computer and use it in GitHub Desktop.

Select an option

Save gursuj/8869cfbd0b857893feac941e07f55623 to your computer and use it in GitHub Desktop.
Adding icons to WooCommerce global product attributes

adding icons to woocommerce global attributes (without acf)

wanted to let an admin attach an icon (dashicon or uploaded img) to each global product attribute (e.g. pa_length, pa_paper-type), then show them as icon cards on the single product page.

what didn't work

wasted a lot of time trying to do this w/ acf/scf field groups on the attribute term edit screen. everything failed for the same root cause:

  • a synced scf field group lands in the db w/ location: []. that empty array short-circuits acf_get_field_group_visibility() before any location filter runs. so no filter ever saves it.
  • acf_add_local_field_group() in php fired too early. the file is required during theme setup, before init, so the group isn't in scf's registry yet when it checks visibility.
  • acf/load_field_group injections got wiped by _acf_apply_get_local_internal_posts (priority 20) merging the empty-location json back over them.
  • acf/location/rule_match/taxonomy filters never fired, again because of the location: [] short-circuit above.

basically two layers of empty-location state (db record + json file) fighting each other.

the diagnostic that finally cut through it: temporarily set the field group location to Taxonomy == product_cat & edit a category. it showed up. so scf does hook taxonomy screens fine, the problem was specifically the dynamic pa_* wildcard, not scf itself.

lesson: if you need a field on all pa_* taxonomies dynamically, acf/scf fights you the whole way. also looked at native term meta ({$taxonomy}_edit_form_fields), would've worked but it's the wrong granularity. the icon belongs to the attribute, not each term value under it.

what shipped — woo's own attribute hooks + options api

dropped acf entirely. woo already renders an add/edit form for each global attribute & fires hooks around it. so store the icon as a plain option keyed by taxonomy. no field groups, no sync step, no location rules, no json.

// render the picker on woo's attribute add/edit screens
add_action( 'woocommerce_after_edit_attribute_fields', /* render field from option */ );
add_action( 'woocommerce_after_add_attribute_fields',  /* render empty field */ );

// persist on save
add_action( 'woocommerce_attribute_updated', function ( $id, $data, $old_slug ) {
    $taxonomy = wc_attribute_taxonomy_name_by_id( $id );
    // type in {'', 'dashicons', 'media'}, value = dashicon class or attachment id
    update_option( 'wc_attr_icon_' . $taxonomy, $icon, false ); // delete_option if 'none'
}, 10, 3 );
add_action( 'woocommerce_attribute_added', /* same, via wc_attribute_taxonomy_name() */ );

// wp_enqueue_media() on admin so the img picker works

storage shape:

wc_attr_icon_{taxonomy} => [ 'type' => 'dashicons'|'media', 'value' =>
'dashicons-info'|<attachment_id> ]

front end — pull the option per taxonomy attribute & build the card:

foreach ( $product->get_attributes() as $attribute ) {
    if ( $attribute->is_taxonomy() ) {
        $icon = get_option( 'wc_attr_icon_' . $attribute->get_name() ); // [] if none
    }
    // card: icon (dashicon span OR wp_get_attachment_image_url), label, value
}

takeaways

  • the icon is a property of the attribute, not the term. an option keyed by taxonomy is the right model & it sidesteps both acf and term meta.
  • woo's woocommerce_after_{edit,add}_attribute_fields + woocommerce_attribute_{updated,added} hooks are the clean, supported way to extend the attribute admin. no plugin layer needed.
  • don't reach for acf/scf for dynamic-location fields. an empty location: [] on a synced group short-circuits visibility before any filter runs, & you'll chase it for hours
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment