 Thank you. Thank you. Welcome everybody. Yeah. So we're talking about hooks today. Before we even get started with that, I had a quick question for everybody. If I use the word WPQuery, who in this crowd has used the WPQuery before? Yes. Good. Okay. All right. It was a good preliminary question, because I gave not this talk, but I gave a talk in Pittsburgh about a similar topic to a community of developers and they had a slightly different answer. So yeah. But my name is Benji. I am a senior web developer at Top Hat. It's a company in Pittsburgh that does a lot of marketing and branding, including websites. With that, we do other kinds of websites. With that, we need to know a lot about development. We need to know a lot about WordPress. We really like to stretch WordPress and use it to its limits. So we have a lot of feats of strength that we like to put in our WordPress sites, including we'll do headless WordPress, plug-in development, we'll get Google Maps in there, and really, really integrate it into the site and do some fun stuff with that, and APIs, sync data, stuff like that. Then we've got a couple of clients that are, if you've known them, you know them, but that's good. Today, we're talking about hooks. I'll give you a little preliminary story before we get started. So I'm a contributor and a member of the Pittsburgh software community, at least a part of it. There are lots of different organizations out there. But I was attending an event for one with many developers, and I had the WP admin for this theme up, and there was a person sitting on my left, and I didn't know him at all, never met him before. He turned, he looked at my WP admin console, and he said, WordPress, that's WordPress. Oh, that sucks. So I was speechless. Besides being a very rude thing to say, he put into Word something that I occasionally experience when I'm talking to developers that don't really get outside of their zone. WordPress is so easy that sometimes ignorant folks think that it's simple, and sometimes even worse, they think that it's limited. So it's not capable of doing whatever they do in their fancy little corner. First off, WordPress doesn't suck. It's a sleek beast of a framework. It's used by two-thirds of all CMS-backed websites, and 43.2% of all the websites on the internet in 2022. So you're going to get haters. We're number one, so people are going to hate. But it's so easy that sometimes understanding the magic behind WordPress is not so easy. So we can do anything that they can do, but you have to tap into a lot of resources. One of the big resources that we use for plug-in development and for theme development is an action or a filter. It's called a hook. So besides working on the open-source framework core, I'd say that there are two ways that you can be a developer in WordPress. One is building themes and one is building plug-ins. Both of them use these. So today, we're going to look into that. So first, what is a hook? So let me explain this in a simpler term as possible. When something happens on your site, you can put some code in there that triggers a function whenever that happens. It can be on another function. It can be on a user experience. It can be on a variety of things. But when that thing is called, you can add an action to that point where you can make a callback function do anything you want there. You can also pass arguments through that callback function so that the data that's happening at that time is the data that you're using in those functions. So an example here of actually hooking into something, you'll hook in with add action. This is the action side of things. If you use add action, you want the name of the action you're hooking into. And then you can set a string as a callback or you can put an anonymous function here. But you can set a callback function name. And then you pass these two numbers as additional arguments. You don't need them all the time. There are defaults. I think the defaults are 10 and 1. The first one here is the priority of your action that's being fired. So if there are many things that are happening at that action name point, 10 is going to allow you to sort of, you can put that number at 1 if you want your function to fire first or you put it down at 99 if you want it to be really, really lowly prioritized. So that's the first number there. And the second number there is the arguments that you want to pull in from that action at that time. So here's our example. We've got add action with action name and our callback, which we're defining right here. Our callback is going to take two arguments. And we've just prioritized it at 10 because that's default. I like to think of it like 10 and 2, like you're driving a car. 2 is a good number of arguments to have. Sometimes, like I said, the default's 1. But still, thinking about that, you're never going to get it confused and put 2 and 10. And then your whole website blows up. It'll always be good. So in this case, I'm going to skip down to this one here first. So here we have the actual action that we're going to call on this page, which is do action. That's how WordPress core or the plug-ins or the themes that are in your site are going to tell WordPress that all your action functions need to be found and run. So while you're writing this code up here, you're hooking into whenever this function is called. As you can see, that's where the action name is. And then we have, wait a second, we have three. We have three arguments that are passed to any add actions of that action name. So there are three here, but I only wanted two. So I specified two. And that's what I output. So here we output that. The action's called right here, literally, in this theme, which you can get to on GitHub. It's Benji the Immortal. I'm not that pretentious, but Benji the Immortal slash WCUS hooks or get hooked or something like that. I can give it to you at the end of the talk. It's literally on this template for this page. There's a do action function there. And there are the outputs of argument one and argument two. So this is how we use actions. Really, really simple example of how we use actions. Why would I want to use actions? I got a real world example here. And last time that I was thinking about this, I thought about it in this order, but it's changed. The WP head action is called every single time WordPress templates out a page and builds a page in HTML. This is the header part of the HTML. And so you can hook into WP head, in this case, an anonymous function, and you can output some code. And it's going to appear in the header of your website on every page. Every time WP head action is fired, you've hooked in there and you've added your own code. So if this is not included in the core theme or the core plugins that you're using, you can add whatever you want there. Do anything that you need to do. So that's a pretty useful and simple real world example. Because what we're doing, really, is we're trying to make our clients life easy. I think that's the main way that I keep a job, is trying to do things for people and trying to be a nice guy about it. So one of the ways that we noticed that's really super helpful is, let's say your client only has access to the file structure on their site. And they're like, look, I haven't accessed the admin panel in 30 years. I don't know what's going on. This is terrible. The site's gone down. I need you to help right now. And so you're going into somebody else's theme, somebody else's structure and setup. And you need to access that, but you don't have anything. But the logins, like SFTP or FTP or SSH or something, you can still get anything you need out of that site. And you can even hack in and make your own account, because you can use actions. So in this case, we hook in with an init action. And the init action, we're going to use this function hack an account. And we're going to check and see if Benji doesn't exist as a user. And if my email address doesn't exist as an email in the system, then I can use all these. And even these two are very wonderful base WordPress core functions. I didn't define them. All of these wonderful WordPress core functions to set myself up as a user in the site and log in. And so running this action, running this add action, and then loading any page, really, because init runs everywhere, suddenly I'm in and I'm able to access the back end of the site. I've got my own credentials and everything there. So this should be incredibly useful for saving your clients some time. Say, I just need SFTP. I just need SSH. I can get you anything you need. That's all I need from you. So you might want to tell me what the problem is. But that's the other stuff that I need. So that's really great. You're going in and you're doing that on somebody else's website. But it's also really great. The init and some other of these back end hooks are really great for helping the clients to see what they need to see out of the site. As you probably know already, the WP Admin panel can get pretty confusing very fast. It's got a lot of things going on. And it's got just so many. You've got plug-in settings. You can change the theme. You can do things. I don't really necessarily want my clients to do that all the time. So you can hook into the Admin menu and simplify what the client can see. And so that's what we're doing here. We're removing a lot of the menu page icons from the left-hand side of the toolbar. And we can limit that to whoever we want. So for example, if I'm accessing the site as your super admin, I can see the plug-in settings. I can change the HTML form templating or do those complicated things that are my job as a developer. But we're not going to have easy access to the parts that are not useful for the client. So I'm going to see if I can do this in real time. I did this wrong last time. Let's see if I can do this. Oh, that's small. Here we are in the code base. This is the theme that I developed for the talk. So like I said, it's all right here. You'll be able to get this in the GitHub repo there. So I'm just going to uncomment that hook and then do this. And it's all gone. It's only gone because my user that I'm logged in as is not the one that's specified there. So if I was logged in as your super admin, I'd be able to see everything. But your client gets exactly what they need to do their job and not worry about the rest. So that's a pretty powerful thing. And it's pretty helpful. One of our default functions that we use in our themes. So that's one way that you can help your clients out is to limit the things that they don't need and make WordPress do anything that you want. Another way that you can help your clients is if you're developing something special for them, sometimes you need to require something. You need to maybe require is a bad word. Who here uses advanced custom fields? Great, OK, many people do. Advanced custom fields, it's one of the top plugin downloads. It's a really powerful tool. It's a paid plugin. So that's kind of annoying sometimes. But it is absolutely worth every penny because of some of the functionality it brings. And in advanced custom fields, you can require that a field gets filled out. But that only happens in certain ways. What if I want a date field to fill in, even if the posts are being created dynamically by an API call or at every possible time, any time that the post is saved, I absolutely need wrong page. Absolutely need a field to be saved. And so here we see on this side, I've set an ACF that's called sort of mandatory field. And it's empty. Now, if it's empty, and now I'm trusting you, you said you used WP queries, so I'm just going to go with this. If it's empty in IWP query and do a meta query and that field, I'm going to order by that field and I'm going to meta query for posts to have that field. This one's empty. It's not going to come through because I've said posts with a date after the date and the date range. So if it doesn't have a date range, it's not going to come through. So I need that to work every time. It needs to fill in every time. So I need something where I can save this page. And even if I was a client moving super fast and I missed it, it's still updated. So there's a great function. There's a great, great action that I use a lot called Save Post. It's a really good one. But if I use Save Post and I hook into the action when the post is saved, and then I try to edit the post inside that callback function and save it again, then it's going to call the hook and then it's going to try to save it. And then it's going to call the hook and then it's going to try to save it. And it's going to keep on doing that infinitely and my page is going to break. I need the right action to make this work. And so luckily, ACFs are extremely helpful and they have wonderful documentation and you can see that they have their own hook called Save Post. Well, that's great. That one does not fire every time the post is updated. That one only fires when the ACFs are about to be saved inside of the page. So I could actually modify the ACFs with Update Field and it will not call this post. It won't update. It won't infinitely loop. So if I use the right action for this and I save it, it's going to populate anyway, at which point that date field is going to be there every time. Even if I don't fill it in, it's always going to be there. If I want to fill it in, sure, I can modify it and save it and it doesn't matter. It's already there so we don't have to worry about it because we checked to see if it's empty or not. But at the end of the day, you get the right action for the job and you can do anything to make your client's life a little bit easier. I'm going to show you one more and this is a little bit of a personal preference. There are a lot of different, I mean, there are actions everywhere and at the very end of the talk, I'll also give you a list of a couple hundred different actions that fire during normal page load, normal processes on the back end of WordPress. So you'll have a lot to choose from. It's a little overwhelming but the next one I want to talk to you about is more about when your site's talking to other sites and why would you want to do this? Well, I like Jamstack a little bit and I couldn't refrain from mentioning that, Mike, so sorry. But sometimes you'll want your site to communicate with a custom API or be a custom API or maybe you'll want your site to go off and run an AWS Lambda function or maybe your site will be sending web hooks to build static pages on a static site and that would be a headless WordPress build. If you're going to do that, you can do that with a hook. In this case, we are going to use SavePost but I only want to save the post with a certain kind of post, I only want to save the post and I name that post type data type. So I have a special post type called data type, maybe the client goes and adds a whole bunch of special post meta fields on that post type and saves that, maybe it's not even going to be shown on the WordPress side but every time that data type is saved, I can use a simple curl function, default PHP curl functions to take that custom post meta which is passed through as one of the, the post object is passed through as one of the arguments in SavePost, I can take that and I can send it to whatever other site I need to and I do any validation and stuff at the end. So this is a web hook, yes, WordPress, we can just make web hooks whenever we want, whatever we want, anybody starts talking to you about web hooks, we can do it. So no personal bias or anything, no personal experience of people doing that. At this point, it's a great point to stop and ask questions, does everybody feel comfortable with actions, are there any questions about actions or about what I've talked about so far? Sure, I'll repeat it because we have to hear it for the live stream, so can we go over the second number? We've got two numbers going on with a hook, the first one is a 10 and the second one is a two, in this case, you can fill in whatever you need there. This number is gonna be the priority of your function, your add action function here. So you're calling add action to action name and you're doing it at this point in the functions.php or any page template or whatever that you're working with but maybe somebody else has another add action function over here and they're trying to do something or a WP head is a great example because when do you want your code to be put in WP head? Sometimes that's important. There was a talk recently at a conference that somebody said, this is the fastest way that WP head gets downloaded by browsers, you've gotta put it in this order. So if you're gonna follow that, maybe you need to know when your custom injection is going to come into that. So you're gonna use this argument here, 10, you could change that to one, to put it at the top of WP head but to put it at the top of the HTML header where you could change it to 99, put it all the way at the bottom, even under Yoast I think, it'll get all the way down there. So that's what that number is. Was that the number you were talking about? The second one, that's the number of arguments that you're going to give to your function. So you can see that this action action name has three arguments provided but that doesn't mean that you need three arguments. You can use one, you can just say I want one argument and then in your callback you're just gonna list one. In this case I chose two and I only listed two and I don't get all these wonderful sports teams and Pittsburgh accents that I'm not going to say. So that's an excellent question that that number is extremely important. If you write the wrong number there, you're gonna get an error. I think it's even, yeah, I think it's a pretty big error. Was there any other questions? Yeah. Hello, okay. It's more of a philosophical or personal opinion question. I was working once, I'm working at this site and I couldn't hook early enough. I had this problem, I couldn't hook early enough and I couldn't use another hook to hook into before that hook so I was like really, really stuck and all of a sudden at the moment of desperation I used minus one as the priority and it started to work and then within my dev team there was this fierce debate about using a negative number and apparently, yeah, there you go. So apparently some people are in favor of it and some are against it and I wanted to know what your opinion about that was. I've developed for like 12 years and I've never had the use of a negative number but the thing is I didn't wanna go over the other hooks and change the order of it and the code base was too deep to do that so yeah, there it is. Now there, okay. If it worked for you, I'd say if it works and it's got no errors, we always walk away from those things and try not to look at them, right? That's our job. No, no, no, no. So the first thing that I would look at is the order that your code is called and so for example, in your site, in your functions.php, if that other file was working there then perhaps you could put your function above their function in the functions.php because priority is also affected by the order that the function is not initialized but defined. So if your ad action has the same priority number as somebody else's but yours is defined first in functions.php, great, awesome. Or if that plug in, it's more complicated with plugins and so I do, I am sorry. That's, I sympathize, that's absolutely terrible. Honestly, I don't like to use the number one. So very important developer discussion here. Try to stick with the middle as much as you can so that the next time somebody comes they don't want to kick you. Yeah, no, that's really, totally. You don't even need a plug in. There are multiple things and we can, wow. Oh yes, I'm so sorry. Yes, there are plugins. No, holy shit, it's loud. It should show you all the plugins and all your hooks and how they load and if you need a negative one, that list of the order of the hooks at fire should help you solve that problem so you should figure out which hook is getting in the way of the hook you want to load. Yes, there are plugins out there for showing that. You can also, there are a couple of functions you can put in functions.php that can also do that. I'll put that on the page for you so you can see everything that's being called. It gets a little bit stressful because there are so many. There are so many actions and so many filters that are called on a page, but yes. So to that, and I work with front end as well, using negative one is kind of scary because somewhere, sometime. I would never use it. Yeah, but that's a feat of strength right there that you found a solution when. I was asking him a minute ago if he uses bang important in his CSS code too. Sometimes, sometimes. Any other questions? I'll try to talk really fast about, let's just make this harder, okay? But it's for a really good cause, okay? So there are actions and everybody's cool with that. Now there is this other thing that you can hook into that's called a filter. Filters are even better. Here's how filters are better. You can modify the data that's coming in. Now, our friend was talking about, I'm sorry, what was your name? Marco. Marco was talking about having an action fire in a certain sequence. This is even more important because you can modify the data that's coming through that filter because it's filtering that data. And so here's how you would do that. You would add a filter. In this case, I'm adding a filter to the filter that's applied that's called filter name. So I'm gonna make this call back. I'm gonna make it earlier. As you can see, I'm not using one. Don't use one. So I'm calling this filter and I'm giving it a priority of 10. And then I'm giving it two arguments. Now, the filter's gonna have as many arguments as it has. That's fine. It's going to have at least one argument because that's the editable value that the filter passes to every one of these that we can change. And so if the filter, for that one, if that filter, the first argument is WordPress like this, then I can take that argument and I can modify it. So once I modify it, I'm showing you here that it's still there, that it's output the way that I've saved it right here. And then I can return it back. So my callback function with a filter returns that first argument back to the filter and then it keeps on going. So that way, whenever your filter happens, you can modify that here and then pass it on to whatever's next. In this case, I've filtered it again. I've hooked it again with this one and it's got a priority of 11. So is this gonna fire before or after? After, yes. It's got 11. In this case, I'm gonna take all three arguments that are coming in. You notice that that can be any number, again, completely independent, any number of arguments that you have there just as long as you're matching them here. And when I output that editable value, because of our first filter, because of our first filter hook, that value is now WordPress capitalized like that. And I can still output anything else I want, even argument two, which we didn't see yet. There it is. That's great. Now, as I said before, you must absolutely return this every time. You must return this or else it's gonna disappear. So if you're using a filter, always return the filter, even if you're not modifying it. In which case, I would say to you, don't use a filter. But use an action on the filter. So first, yeah, it sounded like a gotcha, but no, for real, don't use a filter. Use an action on the filter. You can use an action on that filter just fine. And here, we're calling this after everything else is done, we're going to give three arguments. We're gonna output all three of those arguments here. Ah, yeah, so here's where the real filter is called right here. So now we see the first callback that we have here, the first, that first priority filter, then the second priority filter is here, and then the third priority filter is here. WordPress and Jamstack can live right next to each other. It's totally fine. So yes, so in this case, it's an action. I don't need to return anything, it's an action. It's not going to modify that editable value. Now, this is just like we had that add action, sorry, add action, and then thank you, thank you. You can finish the talk, I've just lost all privileges to talk about this anymore because I forgot that right here. Thank you very much. So yes, do action, just like do action, apply filters is what your plug-ins or WordPress core or you are going to do to start that filter to give it the data that you need here, here, here. There's editable value and then whatever other arguments you need to give it and then modify it and it outputs there. I can't believe this is on, somebody likes me. Okay, so why would we use a filter? Well, filters have a lot of really important things that they can do. One of the main ones is with any form plug-in that you use, filters can be extremely important. If you want to validate a field, if you have a field like on GitHub, you want to delete a repo and GitHub says, you have to type the name of this repo before you can delete it, how does it do that? Well, we can do that with WordPress. We can do it with a filter that calls in to that request as it returns. And if you add filters to validate that form, you can check the name of the repo versus the input value and if it doesn't match, you can send that filter along as invalid. So every single form plug-in that I've seen in WordPress, all the major ones have these form validation things. There are a lot of other ways to use filters, but I'm going to take a little bit of a different path because I'm supposed to finish talking in very few minutes. So I'm going to use Ajax load more. Has anybody used that? It's moderately interesting. A couple of people have used it. It's not like ACFs, but it is really powerful and it's a way that you can make these beautiful cards load. I haven't really done anything to the CSS to make these cards look special. This is just what Ajax load more does. And so we've got a whole bunch of posts and it loads a couple and it's just a short code. So I put it the short code on there and install the plug-in and it loads a couple posts and then it loads a couple more as you scroll down. So it does that Ajax that loads more and more and more and more. So if you have 3,000 posts, your page isn't going to break. So this is great, but what I'd really like is I'd really like the featured posts to be up on top. And the featured post is just a little ACF checkbox that I've made inside of that post. So it's post meta featured is one, featured equals one. So I know how to get to it and I know how to WP query, but I'm not doing that. Ajax load more is doing that. And Ajax load more uses short codes and they're very, very helpful, but they don't do this because I don't only want featured posts. They do have short code arguments that you can pass to give you a WP meta query, but I don't want that. I only want to order by that and I want to order by whatever else is currently being ordered. In this case, date. I want the most recent posts to always be first, but I want my featured posts to come above that. That's really super complicated. And so with our short code here, you can see that we've got a pretty basic short code that we are ordering by the default, which is the post published date in which way is that. Descending order. So the most recent first and that's all. That's all we have here, but Ajax load more, like tons of plugins and tons of resources out there has a lot of beautiful hooks that we can use. And in this case, they have this ALM query args where you can hook into the query and filter the query and return whatever you want the query to be. So we're going to add a filter for this ID right here, custom ALM. We're gonna filter only on that Ajax load more. So if you have other ones on the page, it's not gonna affect them. We're going to take two arguments, which is the arguments and then the ID. And you're going to give this callback here. We're gonna run this callback when that filter hook gets initialized. So here is that callback. Again, I'm trusting that you know WP query is usually accepting an array. And in this case, ALM sets a lot of defaults that we should not change in that array. For example, posts per page. If I change this value, the ALM is gonna break and it's gonna do something that's not expected. Same with offset. ALM is gonna modify this term. So if I tried to change that, then bad, bad things would happen. So there are some things I can't change. So instead, I'm gonna use this array key saving notation instead of creating a brand new array to pass to the WP query. This is another one that's a default, but it's an example of how we're telling the WP query array what to do. So in this case, we're gonna use the meta query first sort featured. We're gonna give a name to this meta query. And we're going to look for the key featured. That's our ACF checkbox that we have that says whether the post is a featured post or not. And we are not going to put a value there. If we put the value there, it's only gonna return featured posts. We don't want that. So we're only gonna do it this way. So this is great. And this gives us the meta query that we need to do what we need. But now we have to order the post. We can't change the order that we're already ordering by. We have to modify it. So this is where it gets super complicated. The first one is if there is no order by in your query, you can just make it sort by featured. Unfortunately, there will always be an order by in your query. Sometimes it's going to be an array of many things that you're ordering. In which case, you're going to need to use array on shift and put your featured at the top of that. So it starts by featuring by what you said and then it features by the rest of the things. Otherwise, ALM likes to use a shortcut for order by where instead of making that an array, it just puts a string of the name of the thing that we're ordering by, in this case, post date. So it would just say args order by equals post date, that string. So if we try to array on shift on that, it's gonna say that's not an array. I don't know what's going on. It's gonna throw an error and it's not gonna work. So if it is an array, or if it's not an array, we have to make an array. We have to take the existing args order by and we have to put it after our first sort featured and then return args so that it runs. So if we do that here, now our featured post comes up on top and the rest come after that. Cool? Okay. So we have two kinds of, ah, sorry folks. We have two kinds of hooks. We have actions and filters and if we use them effectively, they're really good. The last thing that I would say is that there are a lot of folks out there who have tried to consolidate and give this in useful format. So if you take this talk and then you go any further in your own development, you might wanna start with Rachel Vasquez. Her site is an older one, but this is an extremely useful, an extremely useful resource for something that's a little bit more simplified. Then you've got Adam R. Brown and the WordPress.org documents, which is gonna be where you're gonna see that, like every post that is fired in or every action and hook that's fired in order on every page type and you get everything that you possibly need. So from that, are there any questions or last minute things there? Is that a live site? Yes, yeah, I can expose this for you on our stuff. It's also, there's a GitHub repo that I said I put up at the very end here and that is, come on. Benjiva Immortal Slash Get Hooked. So this here is the full theme that's very, very small. This is the full theme that I used for this presentation. So all the slides are basically in here. It has instructions on how to do that. It's got the links from the end of this talk here for you and everything else. So hope you enjoyed it and learned a little bit more about actions and hooks. So I hope I got you hooked.