# Proper Way to Inject into Head using ACF / Sage 10

**URL:** https://discourse.roots.io/t/proper-way-to-inject-into-head-using-acf-sage-10/20723
**Category:** sage
**Tags:** blade, sage10
**Created:** 2021-05-04T20:50:10Z
**Posts:** 5

## Post 1 by @jesstucker — 2021-05-04T20:50:10Z

I need to add an ACF field, callable on any blade template, that will inject editable code into the document head. (In this case, [schema.org](http://schema.org) json LD schemas). I’m wondering if there’s a way I can call sage to do it at the index.php level like this:

`site/web/app/themes/mytheme/index.php`

```
<!doctype html>
<html <?php language_attributes(); ?>>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <?php wp_head(); ?>
    
  </head>

  <body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    <?php do_action('get_header'); ?>

    <div id="app">
      <?php echo \Roots\view(\Roots\app('sage.view'), \Roots\app('sage.data'))->render(); ?>
    </div>

    <?php do_action('get_footer'); ?>
    <?php wp_footer(); ?>
  </body>
</html>
```

I noticed it’s echoing Sage in the app div. Can I call a template to render in head, even though it’s outside sage?

Maybe I should refactor the whole html document to live inside sage? :thinking:

---

## Post 2 by @evankford — 2021-05-05T17:10:15Z

I dug into this for a bit. I think because the ThemeServiceProvider is (as you called) booted inside the Roots\app instance, you’re going to have a tough time loading your views/templates outside of that instance.

If you were going to refactor everything inside the roots\app instance, you could probably just do this:

`site/web/app/themes/mytheme/index.php`

```
<!doctype html>
<html <?php language_attributes(); ?>>
<?php echo \Roots\view(\Roots\app('sage.view'), \Roots\app('sage.data'))->render(); ?>
</html>
```

Then in `site/web/app/themes/mytheme/resources/views/layouts/app.php`

```
<head>
    <meta charset="utf-8">
	<meta http-equiv="x-ua-compatible" content="ie=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    @yeild('head'); //This is, I think, the best way to add in blade template content to the <head>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?> //Default WP Stuff
    <?php do_action('get_header'); ?> //Default WP Stuff
    <div id="app"> //Now we're back to the app
	    <main class="main">//This is normally in views.layouts.app
		    @yeild('content');
	    </main>
    <?php do_action('get_footer'); ?>
    @yield('footer') //Add in footer scripts, because why not!
    <?php wp_footer(); ?>
</body>
```

Lastly, in one of your templates, like `template.product-schema.blade.php`

```
@extends('layouts.app')

@section('head')
    //Your <head> content here
@endsection

@section ('content')
    //Your <main> content here
@endsection

@section ('footer')
    //Your pre-</body> content here
@endsection
```

I haven’t tested this, so your milage may vary. Still, I think this is the best way to make this work for you, if if you **need it.** ( Note: I don’t think you need it for schemas. My work with Shopify, et. al, makes me think it’s perfectly acceptable to include these outside of the `<head>`, specifically at the end of the `<body>`).

---

## Post 3 by @alwaysblank — 2021-05-05T17:40:20Z

> [@jesstucker](#):
>
> I need to add an ACF field, callable on any blade template,

I’m a little confused by this. Are you referring to a [template in the WordPress sense](https://developer.wordpress.org/themes/basics/template-hierarchy/), or to _any_ blade partial?

My guess is you have a situation that’s something like this:

- Some pages/posts/cpts/etc have an ACF field available on them
- When this field has certain content, you want to use that content to generate a JSON-LD schema chunk in the `<head>`

If that’s the case, imo the best way to approach it would just be to hook into the `wp_head` action, i.e.:

```
add_action('wp_head', function() {
  $value = get_field('the_acf_field');
  if ($value) {
    echo convert_to_json_ld_string($value);
  }
});
```

If for some reason you want to use a blade template to generate that string, you could do:

```
- echo convert_to_json_ld_string($value);
+ echo \Roots\view('your-blade-file', ['json_string' => convert_to_json_ld_string($value)])
```

…or something similar, depending on your needs.

> [@jesstucker](#):
>
> Can I call a template to render in head, even though it’s outside sage?

Not in the way you’re probably thinking of it, no. You can use the above technique to do stuff in the head, but it’s not “inside” of the Sage template renderer.

> [@jesstucker](#):
>
> Maybe I should refactor the whole html document to live inside sage?

I would not recommend this. It is the way it is to allow various WordPress plugins that need to do things with the header and footer hooks to do those things…appropriately. If you put it all inside Sage you may run into issues with plugins not working in the way you expect, or not working at all.

---

## Post 4 by @jesstucker — 2021-05-05T22:52:13Z

Hey @alwaysblank,

Incidentally I did try a method that @evankford detailed, as it was along the same lines as my originally proposed solution. It did work, but now you’ve got me scared per your comment!:

> [@alwaysblank](#):
>
> I would not recommend this. It is the way it is to allow various WordPress plugins that need to do things with the header and footer hooks to do those things…appropriately. If you put it all inside Sage you may run into issues with plugins not working in the way you expect, or not working at all.

So I refactored per your suggestion using the `wp_head` hook. It’s working perfectly well, thank you!

@evankford Thank you so much for looking into a solution, it seems we were thinking similarly. And thank you for the note about the schema being able to exist outside the head, that may make the `<head>` business unnecessary.

:pray::pray: :pray:

---

## Post 5 by @system — 2021-06-15T20:50:11Z

This topic was automatically closed after 42 days. New replies are no longer allowed.
