{"id":20856460,"url":"https://github.com/cityofnewyork/nyco-wp-assets","last_synced_at":"2025-07-21T12:39:21.515Z","repository":{"id":29244312,"uuid":"114800785","full_name":"CityOfNewYork/nyco-wp-assets","owner":"CityOfNewYork","description":"A developer plugin with helpers for managing assets in WordPress. Maintained by @NYCOpportunity","archived":false,"fork":false,"pushed_at":"2023-03-01T00:56:26.000Z","size":516,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-12T21:45:58.665Z","etag":null,"topics":["civic-tech","composer","css","enqueue","inline","inline-scripts","javascript","nyc-opportunity","nycopportunity","plugin","scripts","styles","stylesheets","theme","theme-development","wordpress"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/nyco/wp-assets","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CityOfNewYork.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-12-19T18:58:29.000Z","updated_at":"2021-11-04T17:22:30.000Z","dependencies_parsed_at":"2022-08-08T04:15:12.746Z","dependency_job_id":null,"html_url":"https://github.com/CityOfNewYork/nyco-wp-assets","commit_stats":{"total_commits":39,"total_committers":4,"mean_commits":9.75,"dds":"0.15384615384615385","last_synced_commit":"96d5867d3f44e76228617ee8011885fa0dc84816"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/CityOfNewYork/nyco-wp-assets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CityOfNewYork%2Fnyco-wp-assets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CityOfNewYork%2Fnyco-wp-assets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CityOfNewYork%2Fnyco-wp-assets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CityOfNewYork%2Fnyco-wp-assets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CityOfNewYork","download_url":"https://codeload.github.com/CityOfNewYork/nyco-wp-assets/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CityOfNewYork%2Fnyco-wp-assets/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266303622,"owners_count":23908373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["civic-tech","composer","css","enqueue","inline","inline-scripts","javascript","nyc-opportunity","nycopportunity","plugin","scripts","styles","stylesheets","theme","theme-development","wordpress"],"created_at":"2024-11-18T04:31:52.806Z","updated_at":"2025-07-21T12:39:21.493Z","avatar_url":"https://github.com/CityOfNewYork.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NYCO WordPress Assets\n\nA developer plugin with helpers for managing assets in WordPress. It can be used to register and enqueue stylesheets with general defaults and hashed names as well as configure inline integrations such as Google Analytics, Rollbar, etc by using WordPress' native `wp_enqueue/register_style/script()` and `wp_add_inline_script()` methods. This properly loads them into the site, avoids conflicts, and exposes them to asset hooks for deeper configuration.\n\n* [Installation](#installation-using-composer)\n* [Usage](#usage)\n* [Documentation](#documentation)\n* [Enqueue Inline Helper Function](#enqueue-inline-helper-function)\n* [Integration ACF Options Page Add-on](#integration-acf-options-page-add-on)\n* [Query Monitor Add-on](#query-monitor-add-on)\n\n## Installation using [Composer](https://getcomposer.org/)\n\n**$1** This package uses [Composer Installers](https://github.com/composer/installers) to install the package in the **Must Use** plugins directory (*/wp-content/mu-plugins*):\n\n```shell\n$ composer require nyco/wp-assets\n```\n\n*Not using Composer?* Download an archive of the code and drop it into the mu-plugins directory.\n\n**$2** [Create a proxy PHP loader file](https://wordpress.org/support/article/must-use-plugins/#caveats) inside the mu-plugins directory, or [use the one included with the plugin](https://github.com/CityOfNewYork/nyco-wp-assets/blob/master/autoloader-sample.php):\n\n```shell\n$ mv wp-content/mu-plugins/wp-assets/autoloader-sample.php wp-content/mu-plugins/wp-assets.php\n```\n\n## Usage\n\n**Quickstart**. Declare namespace in **functions.php** (or any php file) and instantiate.\n\n```php\nuse NYCO\\WpAssets as WpAssets;\n\n$WpAssets = new WpAssets();\n\n// The general pattern for all methods is $WpAssets-\u003e{{ method }}()\n$WpAssets-\u003eaddScript();\n```\n\n**Migrating** a block such as this...\n\n```php\nwp_register_script('main', '/wp-content/themes/theme/assets/js/main.831f1593.js', [], null, true);\nwp_enqueue_script('main');\n```\n\n... can be done with...\n\n```php\n$WpAssets-\u003eaddScript('main');\n```\n\nAssuming `main.831f1593.js` is a compiled script file and `831f1593` is a hash based on the contents of the script, the filename will change if the contents of the file change. This is useful for cache busting without forcing a browser to load the script on every load using a query variable `?ver=831f1593`. However, WordPress won't be able to locate scripts without a hard-coded source. `-\u003eaddScript('main')` will register and enqueue the first script file it finds with any hash contents between `main.` and `.js`.\n\n**Note**. The autoloader sample sets an instance of `WpAssets` to the global scope which can be used as well;\n\n```php\n$GLOBALS['wp_assets']-\u003eaddScript();\n```\n\n## Documentation\n\nThe core of the plugin is a single class with several methods that are available upon instantiation. For a full description of methods refer to the [source](https://github.com/CityOfNewYork/nyco-wp-assets/blob/master/WpAssets.php).\n\n### Class (including namespace)\n\n```php\nNYCO\\WpAssets\n```\n\n### Methods\n\n* [Add Script](#add-script)\n* [Add Style](#add-style)\n* [Add Attribute](#add-attr)\n* [Load Integrations](#load-integrations)\n* [Add Inline](#add-inline)\n* [Register Rest Routes](#register-rest-routes)\n\n### Add Script\n\n```php\n-\u003eaddScript( ...args )\n```\n\nRegister and/or enqueue a hashed script based on it's name. File name should match the pattern `script.{{ hash }}.js` by default. The separator between the filename and the hash can be configured.\n\n**...args**\n\n- `String   $handle`    The name of the file without a hashname. Default: `'scripts'`\n- `Boolean  $enqueue`   Wether to enqueue the file or not. Default: `true`\n- `Array    $deps`      Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_script/)|[`enqueue_script`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) `$deps` argument. Default: `array()`\n- `String   $ver`       Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_script/)|[`enqueue_script`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) `$ver` argument. Default: `null`\n- `Boolean  $in_footer` Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_script/)|[`enqueue_script`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) `$in_footer` argument. Default: `true`\n- `String   $sep`       The separator between the base name and the hash. Default: `'.'`\n\n**Returns** Key/value pair including [wp_register_script](https://developer.wordpress.org/reference/functions/wp_register_script/) response, [wp_enqueue_script](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) response, and the source uri of the file.\n\n#### Examples\n\n```php\n$WpAssets-\u003eaddScript();\n```\n\nThis will scan the default scripts assets directory *assets/scripts/* of the current theme using the default pattern *script.{{ hash }}.js*, register the script with the handle `script` and enqueue it. To pick a different script named *main.{{ hash }}.js* do the following;\n\n```php\n$WpAssets-\u003eaddScript('main');\n```\n\nThis script will be loaded into the footer of the document and be available to the [script_loader_tag filter](https://developer.wordpress.org/reference/hooks/script_loader_tag/);\n\n```php\nadd_filter('script_loader_tag', function($tag, $handle) {\n  if ($handle === 'main') {\n    // do something to $tag like add attributes, disable for certain views, etc.\n  }\n\n  return $tag;\n});\n```\n\n[Back to top](#documentation)\n\n---\n\n### Add Style\n\n```php\n-\u003eaddStyle( ...args )\n```\n\nRegister and/or enqueue a hashed style based on it's name. File name should match the pattern `styles.{{ hash }}.css`. The separator between the filename and the hash can be configured.\n\n**...args**\n\n- `String   $handle`   The name of the file without a hashname. Default: `'styles'`\n- `Boolean  $enqueue`  Wether to enqueue the file or not. Default: `true`\n- `Array    $deps`     Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_style/)|[`enqueue_style`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) `$deps` args. Default: `array()`\n- `String   $ver`      Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_style/)|[`enqueue_style`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) `$ver` args. Default: `null`\n- `String   $media`    Maps to [`wp_register`](https://developer.wordpress.org/reference/functions/wp_register_style/)|[`enqueue_style`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) `$media` args. Default: `'all'`\n- `String   $sep`      The separator between the base name and the hash. Default: `'.'`\n\n**Returns** Key/value pair including [wp_register_style](https://developer.wordpress.org/reference/functions/wp_register_style/) response, [wp_enqueue_style](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) response, and the source uri of the file.\n\n#### Examples\n\n```php\n$WpAssets-\u003eaddStyle();\n```\n\nThis will scan the default style assets directory *assets/styles/* of the current theme using the default pattern *style.{{ hash }}.css*, register the style with the handle `style` and enqueue it. To pick a different style named *site.{{ hash }}.css* do the following;\n\n```php\n$WpAssets-\u003eaddStyle('site');\n```\n\n[Back to top](#documentation)\n\n---\n\n### Add Attr\n\n```php\n-\u003eaddAttr( ...args )\n```\n\nUses the [`script_loader_tag`](https://developer.wordpress.org/reference/hooks/script_loader_tag/) filter to add an attribute and a value to a specific script. For example; crossorigin=\"anonymous\".\nAttribute values may be strings. To add a boolean attribute such as `async` or `defer` pass `true`.\"\n\n**...args**\n\n- `String  $name`  The name of the script.\n- `String  $attr`  The name of the attribute.\n- `String|Boolean $value` The value set for the attribute.\n\n#### Examples\n\n```php\n$WpAssets-\u003eaddAttr('script', 'async', true);\n```\n\n[Back to top](#documentation)\n\n---\n\n### Load Integrations\n\n```php\n-\u003eloadIntegrations( ...args )\n```\n\nThis retrieves an integration configuration file from the MU Plugins directory. By default it will look for a YAML file at *config/integrations.yml* that contains an array of individual configuration objects then it converts the YAML file to a PHP Array and returns it. This is meant to be used with the `-\u003eenqueueInline( ...args )` method.\n\n**...args**\n\n- `String  $path` Accepts a custom to the integrations file within the Must Use Plugins directory. Default `'config/integrations.yml'`\n\n**Returns** an array of individual configuration objects.\n\n```php\n$integrations = $WpAssets-\u003eloadIntegrations();\n```\n\nA configuration file may include multiple objects with the following parameters.\n\n```yml\n- handle: rollbar\n  path: https://remote/url/to/integration/source.js\n  dep: CONSTANT_THIS_SCRIPT_IS_DEPENDENT_ON\n  localize:\n    - ARRAY_OF_CONSTANTS_TO_LOCALIZE_IN_SCRIPT\n    - CONSTANT_MY_SCRIPT_IS_DEPENDENT_ON\n  in_footer: true/false\n  inline:\n    path: config/integrations/scripts/a-config-script-for-the-source.js\n    position: before\n  body_open:\n    path: config/integrations/body/a-html-tag-to-include-in-the-body.html\n  attrs:\n    crossorigin: 'anonymous'\n    async: true\n\n- handle: google-analytics\n  path: https://www.googletagmanager.com/gtag/js?id={{ GOOGLE_ANALYTICS }}\n  dep: GOOGLE_ANALYTICS\n  localize:\n    - GOOGLE_ANALYTICS\n  in_footer: false\n  inline:\n    path: config/integrations/scripts/google-analytics.js\n    position: after\n```\n\n[Back to top](#documentation)\n\n---\n\n### Add Inline\n\n```php\n-\u003eaddInline( ...args )\n```\n\nRegister and enqueue inline scripts and their source using `wp_register/enqueue_script()` and [`wp_add_inline_script()`](https://developer.wordpress.org/reference/functions/wp_add_inline_script/)\n\nUseful for cloud service integrations that are configured on the client-side (Google Analytics, Webtrends, Rollbar.js, etc.) what require loading a remote source but are configured with an inline script code block.\n\nAlso enqueues inline styles if required by the configuration. This is not possible by default and uses a technique described in [this article](https://www.cssigniter.com/late-enqueue-inline-css-wordpress/).\n\n**...args**\n\n- `Array  $script` Accepts a single key/value array of a configuration. Refer to the `-\u003eloadIntegrations( ...args )` method.\n\n**Returns** the same array with additional inline script contents.\n\n#### Examples\n\n```php\n$integrations = $WpAssets-\u003eloadIntegrations();\n\nif ($integrations) {\n  $index = array_search('google-analytics', array_column($integrations, 'handle'));\n\n  $WpAssets-\u003eaddInline($integrations[$index]);\n}\n```\n\nThis will load the `'google-analytics'` integration. Below is the Google Analytics configuration in *config/integrations.yml*...\n\n```yml\n- handle: google-analytics\n  path: https://www.googletagmanager.com/gtag/js?id={{ GOOGLE_ANALYTICS }}\n  dep: GOOGLE_ANALYTICS\n  localize:\n    - GOOGLE_ANALYTICS\n  in_footer: false\n  inline:\n    path: config/integrations/scripts/google-analytics.js\n    position: after\n  attrs:\n    async: true\n```\n\nThe *config/integrations/scripts/google-analytics.js* script should contain something like the following;\n\n```javascript\nfunction gtag() { dataLayer.push(arguments); }\n\ngtag('js', new Date());\n\ngtag('config', '{{ GOOGLE_ANALYTICS }}');\n```\n\nThe constant `GOOGLE_ANALYTICS` should be defined somewhere in another part of your configuration (*wp-config.php*, *functions.php*, *or* this plugin works nicely with the [nyco-wp-config](https://github.com/CityOfNewYork/nyco-wp-config) plugin);\n\n```php\ndefine('GOOGLE_ANALYTICS', 'GTM-9A9A9A9');\n```\n\nThe following will be printed in the head of the document;\n\n```html\n\u003cscript async type=\"text/javascript\" src=\"https://www.googletagmanager.com/gtag/js?id=GTM-9A9A9A9\"\u003e\n\u003cscript\u003e\n  function gtag() { dataLayer.push(arguments); }\n  gtag('js', new Date());\n  gtag('config', 'GTM-9A9A9A9');\n\u003c/script\u003e\n```\n\n[Back to top](#documentation)\n\n---\n\n### Register Rest Routes\n\n```php\n-\u003eregisterRestRoutes( ...args )\n```\n\nUses an array of configuration objects to register WP Rest Routes that act as JavaScript files instead of inline scripts.\n\n**...args**\n\n- `Array  $scripts` Array of integration objects (use -\u003eloadIntegrations() to retrieve them).\n- `Function  $auth` The authentication function to use for routes (passed to register_rest_route() as the `'permission_callback'` argument).\n\n**Returns** the Array of integrations objects with all rest route details.\n\n[Back to top](#documentation)\n\n## Enqueue Inline Helper Function\n\nUse the included `enqueue_inline( ...handle... )` helper function to quickly add integrations. It wraps around the example described above to make it easier to call integrations based on their handle in the *config/integrations.yml* file. The sample autoloader includes the helper function automatically.\n\n```php\nadd_action('wp_enqueue_scripts', function() {\n  enqueue_inline('google-analytics');\n});\n```\n\n## Integration ACF Options Page Add-on\n\nThis plugin ships with an Integrations Options page add-on to allow WordPress admins to toggle integrations on or off. It **requires [Advanced Custom Fields](https://www.advancedcustomfields.com/)** to display the options page. Create a copy of the add-on in your mu-plugins directory.\n\n```shell\n$ mv wp-content/mu-plugins/wp-assets/integrations-options.php wp-content/mu-plugins/wp-assets-integrations.php\n```\n\nThe page will then appear under the **Integrations** menu item.\n\n![Integration ACF Options Page preview](integrations-options.png)\n\n## Query Monitor Add-on\n\nThis plugin ships with an add-on for [Query Monitor](https://querymonitor.com/) that displays the *available* integrations to the [Load Integrations method](#load-integrations) and compares them to integrations that are registered. It uses the same method to display the details of the **config/integrations.yml** file. The sample autoloader includes the add-on automatically.\n\n![Query Monitor Add-on preview](query-monitor.png)\n\n---\n\n![The Mayor's Office for Economic Opportunity](NYCMOEO_SecondaryBlue256px.png)\n\n[The Mayor's Office for Economic Opportunity](http://nyc.gov/opportunity) (NYC Opportunity) is committed to sharing open source software that we use in our products. Feel free to ask questions and share feedback. **Interested in contributing?** See our open positions on [buildwithnyc.github.io](http://buildwithnyc.github.io/). Follow our team on [Github](https://github.com/orgs/CityOfNewYork/teams/nycopportunity) (if you are part of the [@cityofnewyork](https://github.com/CityOfNewYork/) organization) or [browse our work on Github](https://github.com/search?q=nycopportunity).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcityofnewyork%2Fnyco-wp-assets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcityofnewyork%2Fnyco-wp-assets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcityofnewyork%2Fnyco-wp-assets/lists"}