GraphQL + HubSpot: Query Your Heart Out!

This is a YouTube video titled "GraphQL + HubSpot: Query Your Heart Out!" recorded in July 2024. It features a developer-focused presentation hosted by Dennis and Carter Makai, discussing GraphQL and its application within HubSpot. The content includes announcements about upcoming developer events and a live coding session with no slides, emphasizing practical coding demonstrations.
Sam A.
Hello everybody. Welcome to another developer hug where we're going to talk about GraphQL today. And keeping with what I said on LinkedIn earlier, this is going to be no slides, all code thanks to our friend Carter Makai who's going to be teaching us all kinds of great things. But before we get to that, I want to do a real quick shout out to this. Hugs leaders Anton and Tune, who are now mentors in a HubSpot developer mentorship program. I'll add a link to that later on into the chat. Speaking of the chat, if you got questions, put them in there. We'll get to them at some point in time. If you. I know this is one of my things I always ask our speakers to do to make sure that the font size is large enough. So if it's not big enough, yell and I'll yell at Carter to make it bigger in the future. All right, so I do have some things I wanted to put up on the stage right now. And keeping true to no slides, I put it into my VS code editor tomorrow at 12:30pm is coding with John. He's working on a new developer homepage. Anton's actually already been on that once and donate some really amazing codes to do the Morse code background that is at 12:30 tomorrow on the YouTubes. The links I'll also add to the comments here. But you're on YouTube now, so you should be able to find it yourself. Next, I want to say is next month, August 29th at 2pm the road to Inbound. We are teaming up with another hug to present, you know, our thoughts, what's going to happen, what we're going to do at Inbound 2024. And with that I am going to put on my last slide this little image of Carter here that I think sums it all up. This is the man, you know him I'm going to bring on the stage right now to take over. Carter, get up here.
Thank you. Thank you, Dennis. I'm. I'm very impressed with that, the ASCII art. I've never seen someone take an image and, and make it ASCII art. That was beautiful. That. Yeah, Picasso. Thank you.
Many hours of work. Many hours of work right there.
Many hours of work. Many hours of work. Well, I'm really excited to be presenting today. About GraphQL. I was remembering back to the first time I got into GraphQL. My very first introduction with GraphQL was actually using HubSpot GraphQL and it was initially like a private beta that will Spiral was running and I had been building out a customer portal that was pulling in tickets for from HubSpot in the CMS. And he's like, okay, you're doing this in a crazy way right now. If you use GraphQL, which is our new product that we're launching, it would be 10 times better. And funny enough, I used GraphQL, it was 10 times better. And Will Spyro sat with me for a good three hours teaching me GraphQL and I'm forever grateful has made me such a brilliant developer.
All right, I'm gonna, I'm gonna get off this stage right now for you. And if you do a successful job here, Carter, I think we'll allow you to level up one more point. Just saying. I'm leaving level 15.
Maybe, maybe, maybe level 15. Yeah. So, GraphQL HubSpot, it's incredible. It used to be kind of the reason why HubSpot GraphQL was developed was initially just for the CMS as a different way to pull in data from the CRM, as opposed to using like Hubble objects or Hubble associations. Kind of a more flexible way to pull in GraphQL for the CMS. And GraphQL traditionally is used for mainly front ends, where you're, where you're pulling data from the back end straight into the front end and displaying it on the front end. HubSpot launched it as that initially and it was uber successful. So you could build out themes that pulled data from the CRM and put it straight into your CMS pages. And it felt like programming straight in Hubble from the Hubble perspective. But you still got all the benefits of GraphQL and you got to be able to query with associations and query with filters, whereas traditionally with the CRM objects, you could just say you could add a filter, which is great, but it was really hard to do orders and to do second level associations. And the limits were super intense where you can only have 10 CRM object functions per page. So if you were trying to do multi layer associations and multi layer objects like we're going to be talking about today a little bit, it was impossible. There was just no good way to do it. So GraphQL actually unlocked it. And kind of the massive benefit of GraphQL is you can say, I want all these objects, a particular object. You can say, I want all these deals and also give me all the associated contacts for every deal and filter out those contacts to a lower level of those contacts. And so you can filter and associate at all the different levels and oh, thank you so much for bringing up the screen. So let's walk through a quick example. I've built out three examples for today. One is one of the new REACT CRM cards that, that's using GraphQL to pull in some data. One is a library example built on the CMS and then one's a custom coded action. So they should each be about probably 15 minutes long here and we're just going to knock them out and go through all these examples. So first, for this CRM card, if you haven't seen the CRM cards yet, super useful, you can basically build out whatever interface you want to on the HubSpot CRM object pages. And so this particular CRM card looks like, if I go to this page, it looks like this. It's called GraphQL table and it shows a table with some paging and it shows some deals here. And you can click on these deals and it opens them up in the preview tab. Well, let's talk about how we actually got to that point now, because that is somewhat important. So the way you set up a CRM card in HubSpot now, it's actually super easy. They, they've just made it, they've just made it exceptionally easy here. The only thing you really need to do is you need to opt in to the REACT CRM update if you're not already, not already in there. And I think it's called Developer. I don't know where it is. Oh, I'm just in the new ones that would do it. CRM development tools to build UI extensions. You just need to opt into this beta and you can only opt into this beta right now if you're cms, sorry, sales or service enterprise. So that's, that's one limitation. But for everyone, that is opt into this beta because it unlocks so much new functionality for you. Once you're into that, you can just use your CLI to create a new developer extension and you can go HS project create and then you just provide your account. And for me, this is going to be DHUG demo just like that. And what you're going to do then is you can give your project, your developer project, a name. In my case, I've already created a new developer project right here. It's called the Dhug GraphQL example app. But that's honestly all you need to do. And then that's going to throw you in to a. Yeah, that's going to throw you in to a very simple example card to get you up and running with this code. So it's absolutely awesome. Once you're in that example card, there's a couple of main files you'll want to switch around before you start on actually writing your react code. And we're looking good on the zoom. Okay, beautiful. Thank you all for. Yeah, let us know if the zoom needs to be upped a little bit or down a little bit, and we'll make it happen. But there's a couple files you want to switch around. When you get loaded up into it, there will be a new file, new folder that's created, and inside of that folder there's a source, and then there's an app folder, and then inside of that app folder, there's an app JSON file. And what you can do in there is you can provide a name for your particular app and then you can provide a description if you want. Description's obviously not needed. We're programmers, some of us are not great at documenting code. And maybe I'm just speaking for myself here. You provide a UUID and then any scopes that you're going to need to use on this app. And the volume is very low for Carter. Hold momentarily while I see if I can swap that around. Okay, let's see if that does anything for here that might help it a little bit. But basically, you provide any scopes that you're going to be using in your REACT cards. And so in our case, the REACT card I just showed you, it searches the companies and it then searches the deals, and it also uses GraphQL. So those are the main scopes that were then used for this. And then you don't have to swap anything over down here. But that's some exciting stuff, possibly in the near future. And so then the next couple of files you'll swap around are just your main card JSON file. Now, this is the actual CRM developer card. So you can have multiple cards per developer project. So you don't have to develop multiple apps for every single card you want. If you have cards that are very similar to each other or they are part of the same project, I personally like to develop all the cards in the same project if they're very similar to each other. In our case, for this example, we're just using one card here. And so it's just sitting in one project and you just title your card as you see GraphQL table. And then if I go back here, we should get back to the GraphQL table. Yep. So that's. That's just kind of the Titling there and then you provide the object type this is going to be running on. So we're running this card on the Companies tab. But if you wanted to provide a couple of extra. If you wanted this card to run on like deals for example, or contacts like, like GitHub is trying to suggest I do, you can also add those in there. Okay, now that we have that all set up, the one last step is actually now creating that project in HubSpot because right now we've just created it locally. We just said, hey, create the project locally. And we've edited a couple of files. But now we actually got to upload that project and the code to HubSpot. So it's actually a super simple command, just like our Create command. But instead we're just going to say upload. And what this is going to do is it's going to take all of our configuration files and it's going to then upload them into HubSpot. And so that tells HubSpot how we want it done. In my case, this is the fifth time uploading to HubSpot, so that's a little bit of a caveat. If you're uploading it for the first time, you're probably going to see it's the first time uploading it. But once you've uploaded to HubSpot, then you can go in and and actually configure your company view to show that card. Just because you've created that card in the account doesn't mean you have the card on any of the tabs yet. So you can now use the Unified Record Editor, which shout out to all the HubSpot teams that worked on this. This Unified Record Editor is absolutely awesome. I love using it. But you can either create a new tab for your CRM card or you can go to the Overview tab and you can just add the card directly. In my case, I just created a new tab here and I added the card by clicking on. If I can get all these pop ups to hide yes, close Close Tour, you can click on it by add cards, extension cards, GraphQL table and now that's going to add the card that I created onto that new tab that we just created. And so it would show up here. Now that we have that out of the way, we actually need to start on writing the code. In my case, I had already written the code because I did not want to write code live for this stream. That's always a little sketchy. The only thing sketchier than demoing live is writing code Live. And so I did not want to bundle those two together, but I'm going to walk through the code step by step here. And for all of you that know React, or at least have a little bit of experience with React, is going to feel very, very similar to what you're used to. And in a lot of cases, it's actually going to be a lot easier than what you've been used to in the past. So HubSpot has built out a HubSpot has built out a couple of component toolkits for you to use, and all the components are up on the HubSpot docs, so one of Dennis or Anton could drop in a link to that. But HubSpot has built out all the component toolkits so you can use the HubSpot components that HubSpot uses to build out these CRM components. So your CRM extensions look and feel exactly like HubSpot, which is absolutely awesome. And so that's a significant benefit. In a lot of cases. You don't need to write your own HTML and CSS and JavaScript for these components. HubSpot just provides them and you just get to use them. In our case, we have a super simple card and we're just using a couple of components here. We're primarily just using the table and its couple of child components like the table, body, cell, head, row and header, which is awesome. And then we're also using. I actually can delete these because they're not used anymore. We're also using the CRM Action Link component. What the CRM Action Link component does is actually tap in the. To a couple of the HubSpot like really particular HubSpot functionalities like previewing records, opening up the engagement sidebar, sending emails, booking meetings. They kind of handle all of the different HubSpot interactions. So while you can have a lot of interactions on your card, if you ever want an interaction outside of your card, you have to use the CRM Actions components. And you can use a link or a button or you can also configure out these different like action sidebars up here, which is really awesome that HubSpot allows you to do that. Then down here we're just kind of defining how this, what, what different functionality this extension is going to be using. And we're, we're kind of passing a couple of functions to it. So we're saying we're passing in a context for how the what where this card is running. Like is it running on a CRM tab? Is it running on what object is it running on all that fun stuff? Who's the user of the current HubSpot that it's running on? We're also passing in a run serverless functions and then we're also passing in these actions. And so all of these kind of do their own thing actions are used to send alerts and run serverless functions. Kind of do exactly like what they say they do. They run serverless functions. And so right here is actually where we define our extension and this is all the code that runs. It's actually a pretty short script, but I think it's a great little demo purpose here. Again, if you have used react before, this statement up here will feel very similar to what you're all used to. It's a use state, which basically means whenever we update this component, it's actually then a reaction trigger a render of the CRM card and any new context that's been passed to it will show up live on the page. So what this allows us to do is right as the card loads up, we can run a serverless function called GetSalesData and we're going to pass it in our HubSpot object ID and we're then pass it the object ID that we're currently running on where the page is currently running. And then we'll send an alert to HubSpot saying, hey, we just got the deals, which is great. We're also going to console log the response just for troubleshooting purposes. If you have live CRM cards, you probably don't need to console log the response. But also remember, like we're not developing on a live page that's out into the world. This card is running for your team. And so if you have, if you want to console log it while you're in development a little bit, honestly, throw in a console log. It's not going to hurt anyone. You can also use the logger that HubSpot built, which is great. You can find that on the docs as well. HubSpot built a great logger function and that's another great way to use it. But then right here we actually set the deals. We actually go and update this state with the deals that were just fetched from the serverless function. And I'm going to walk you through now what the serverless function serverless function does and how it runs here. And so if I go over here in our App functions folder, you'll see there's a serverless file, serverless JSON file, and it just says, here's our app Functions, we have one called GetSalesData and the file it needs to point to is this GetSalesData JS file. And so if we go over to this GetSalesData JS file, it's uber simple. It's literally just a GraphQL query by default. In the HubSpot example, you always get this export main and then it's always an async function. And then HubSpot will pass through the context, which is what was passing through here. This is all different context that HubSpot's giving us to tell us what's happening and why they just triggered this function run. And so we use that context to pull out the object ID that was just passed through, and then we insert that object ID into our GraphQL query. And now I actually want to show you this GraphQL query in GraphQL, which, if you have not already heard about GraphQL, it's an absolutely awesome tool for. It's the easiest tool for querying with HubSpot. Unlike the HubSpot APIs, where you kind of have to guess and, and you can read through the docs and you can use some of the live examples on the docs. A lot of the times it is tough to figure out how you want to use it and which parameters you need to send for all that things. With GraphQL, it makes it 10 times easier. You literally just click open these dropboxes and these different functions to build out your query. So if we start from scratch here, we basically say what we want to query. And in our case we're going to be querying the CRM because we're trying to pull the company's associated deals and activities related to those deals. If we look at this one, you can see the deals and their related tasks and activities. So all that makes sense there. If we go to this one, we say, okay, we're going to want to ping the CRM and we're going to pass in a particular company. And you can then say, okay, our unique identifier for this query. So we're kind of filtering on this company's. In some cases you can use the domain. In our case we're just going to be using ID because that's going to be the best one for us because we're being passed the context, so we don't really have to deal with looking up a domain or anything. We already have the object ID in the context, so we can pass in that unique identifier. And I'm just going to hard code it here just for the time being. And then we could grab different company fields straight from here. So we could totally just grab like a company name if we wanted to here. So if I clicked on name, you see it just added it and then if I run this query, you'll see it just pulled in the data CRM company name and we obviously got HubSpot because that's what we just told GraphQL what we wanted to query. And so that's really awesome. It's, it's a super cool, super cool functionality there. But this is kind of useless because we're already on the companies tab. We actually need to be in the associations table. So we're going to say, okay, I actually want to fetch some associations and I actually want to get deals that are associated to this company. So we can click on to the deals collection here. And in our case we can add items, which basically means how many deals we want to pull or the deals that we want to pull. You could say there are a couple of options down here. You can add different filters and functions to the query. So you could add a limit and offset and order by. But in our case we're just going to grab items because we want the individual deals themselves and then let's throw in the amount for the individual deals and let's throw in a deal name and then for good measure we always want to throw in our HS Object Object id. So just like that, we've now grabbed the associated deals to for this particular company. If we go up to HubSpot here, you can see, okay, those deals are the exact same. So that's awesome. Well, now what we need to do is that we actually want to query one step deeper. We actually want to find the associated activities and those tasks for those deals. So if we click on associations one more time, we can then go into task collection. Now we're saying we want to pull the associated tasks for each one of these deals and we want to pull in some particular items here. And then let me just grab like our HS Owner id. We'll do HS Create Date and HS Object id. Always a good one. And then let's grab Task subject. And you can also like just type in here if you know what you're searching for and you don't want to like look through all the options. You can just type in like subject and it's going to pull up our task subject. And so if I run that, you can now see, oh wow, it just pulled in all the deals that are associated to HubSpot and then all the tasks that are associated to each of those deals. And so that's pretty killer. If you were doing this with the traditional APIs, you would have to do one search API call for pulling in HubSpot one, you would have to run one API call for pulling in the associated deals, then a batch lookup for each of those deals and then you'd have to run another batch association for each of those deals and then another batch lookup for each of those tasks. And so like you see how this like infinitely shrinks those API calls that you need. Now the one caveat to this is HubSpot does keep track of the points. So like, while you can go really deep and really technical on this, HubSpot does grade you on the complexity of your query. And now it's a little bit different than like normal, like 429 rate limiting where it's oh, I sent too many requests, you sent too large of a request or you asked for too much information or too deep of information. And Dennis, oh, thank you so much for dropping in those docs. Dennis just dropped in the docs in the chat and you can actually see that where the points are laid out. But as long as you keep your queries pretty nice and tidy and you make sure you add filters and paging, which we're going to touch on in just a minute, you should be pretty good. And so now that we have this, this one built out here in GraphQL, we could actually just grab it and throw it in here. Now I will just drop this in right here. Awesome. And I think, yeah, I named it DealData and now perfect, it's in there. I have a couple of those different company. Yeah, there's a couple of deal properties. So I'm not just in a paste and recopy those. I think you're all following along with me. The one extra special thing you can do here is if you're a little annoyed with how the HubSpot fields are named, you can rename them Graphic. GraphQL is actually really cool because you can literally just name it whatever you want and HubSpot will then configure the response to whatever you just named it. So for example, if I was trying to access this data, which we'll do in just a second in the CRM cards, I would have to go DealData CRM company name associations DealCollectionCompanyToDeal. Well, that's kind of a lot. Why don't we just name it deals? And now if we go like that. You can see HubSpot has renamed that field to. Instead of that whole long thing right there, it's just renamed it to Deals for us. And we can just use it just like that on our CRM card. Cool. Now that we got all that, we're just sending that request to HubSpot using the collector endpoint and we're passing in our private app token, which currently is stored in my env file. But when you upload this project to HubSpot, when you upload this to HubSpot, HubSpot will automatically pull in this private app access token. So you don't actually need to hard code your secrets here. Please, please don't hard code your secrets. If you're doing local development, open up an env file, drop in a private app access token into that env file, and then when this is uploaded to production, HubSpot will automatically pull that secret and it'll handle it for you. And again, you can upload it to GitHub. It's going to work the exact same way. Please, please, please use env files for all this. Okay, cool. Now that that's all finished here, we'll hop back into the REACT card. And again, like I was saying, it's a super simple, super simple component here. We're just passing in a table. We're saying, okay, here's the table head. It's going to contain one row and it's going to contain a couple of columns here. Deal, amount, owner and next task. Cool. Now that we have that, we're going to actually pop in a body, which is our table body. And then we're going to map over each of the deals and then we're going to create a row for every single deal here. This should all make somewhat sense. And this map function is a little bit, is a little special because unlike in Hubble, for example, where you just do like a for loop, because we're running in React, you actually have to use pretty much all JavaScript functions. And map is a function that will iterate over an array. And we also close that map down here after we end this table row. So that's one thing to keep in mind. Then for each, for this row, we have our couple of cells here and we're using that CRM action link to open a preview object. And we're previewing the deal type and we're passing in our deal object id. And then we have our cell for amount, our cell for owner, and then we also have our cell for the upcoming task, and we're passing in this task subject line right here. And again we're passing in this preview object which will allow us to click on the particular task subject line and it will open up in the sidebar of React for us. Sorry, the sidebar of the CRM object for us. So if we go over here, click on it, we can see. Oh wow, that's kind of nice. It opened it up in the preview bar. You can also use the different CRM action components to do like a lot of other things like create a note, create a task, send a one off email, schedule a meeting, create an associated record, which is a great one. Created an associated record will open up that association panel if you haven't used this already. Definitely check out this page. I'm going to drop it in the chat right now. But yeah, check out that CRM Actions components page because it's super useful for building in native HubSpot functionality into your custom cards. But as you see here, yeah, we're now pulling in these tasks and it's absolutely amazing. And yeah, you can preview the task, you can complete the tasks, all that straight from here. So yeah, that is that page. We've spent almost 25 minutes on this one react card. So now we're going to have to kind of speed run the other two GraphQL examples. The next one is actually using GraphQL in the CMS. And so what I was thinking here, I was like, well, how would be a great way to use GraphQL in the CMS? Well, you can query not only just CRM data, you can actually query HubDB data and blog data with GraphQL which makes it uber useful for querying the, for using in the cms. So I was like, well let's build out a couple of HubDB tables and we'll arc browser. I got you guys. I created a couple of HubDB tables to blow up the books and to connect books, ratings and authors together because and I'll click into each of one of these tables here, you can see Books just has a ton of demo data here which, which was just built with ChatGPT. Thank you Justin Givens for the ChatGPT prompt to create all this demo data. But the one special part about this is you see, we are actually connecting our author via a foreign id which is a little bit of a new functionality to HubDBs. If you haven't checked it out already. It allows for a lot of cool functionality like connecting, connecting separate hubdbs with foreign IDs. Very similar how you would with SQL and all that fun stuff. So now that we have these tables built out also I should mention that all of this code and all of this data and all these tables will be put on up on GitHub after this and I'll build a nice readme and that'll be messaged out. And so don't worry about memorizing all this stuff because it's going to be up and out on it. We also have the authors table, just first name, last name, all that fun stuff. And then we also have a ratings table where people could rate their books. And rating has an id, it has an actual rating and then it's connected to a book here. Well now how would we actually use this in GraphQL? It's a little bit of a, it's a pretty cool process here. But as you see, we also, we have the HubDB. So instead of clicking on CRM, we're going to click on HubDB and we're going to ask for a books. Can we use GraphQL and custom coded actions in workflows? Yes, that is the next example here. I think you're going to be blown away. It's going to be awesome. But getting back to it, we have hubdb here and we're going to click on book collections. And now I'm going to say I'm going to limit this to, let's say I'll just limit it to 10. I don't want to have an entire page full of 100 different books. I'm just going to limit it to 10. Here you can add filters so you can, you can filter on any of these things. You can say, hey, is the language equal to English or is the format equal to hardback? And all that fun stuff. So you can add a ton of fun filters. In our case, we're just going to add a limit really quick and then we're going to pull in the items. So we're going to say hsid, which will give us the row id. And then we're also going to pass through on the title and then let's grab price and ISBN. So if I run this now, you can see we just got the top 10 results for our HubDB table, which is, which is really cool because this would usually be a CRM objects call and there would be no way to test it. And you would kind of have to deal with the filters and be like, is this working? Is this not working? Now you just build it out in here and you don't even have to worry if it's working. You're like, I can test it live and see if it works with this. We also probably want to pull in the authors for these particular books because just knowing the books themselves is cool, but like it'd be cool to know the authors of those books and the exact same query. And so we can pass through again on that associations and we can pass the author collection, author id And I've just, I don't know that by my by memory, I've just been clicking on these associations. If you haven't figured that out already, Click on that, pull up the items, and then pass through the different, the different fields you want. In our case, let's just pass through first name and last name. So if I rerun this now, you can see each of these books now has a first name and a last name. Now with the fact that we're not using the CRM objects query, we're actually using GraphQL. Building the sincere m objects and the associations would be pretty use. It would be pretty cool, but it would be pretty impossible because of the CRM objects and association limits. The fact that you can only run 10 of those functions on every page with this, you can run as many as you want. You just have to be a little cautious of your points usage. So GraphQL gives you 30,000 points. Right now I'm using 4,000 points. Great. That doesn't really bother us too much there. So if I go into my design manager, we're actually going to be building out this module. We can check what we're actually going to be looking at today. I just created a very simple module here just by click right clicking New module next. Fill it out. And then I also created a GraphQL file. If you haven't created a GraphQL file yet, super easy new file, scroll down very, very bottom graphql and just drop it in right like that. Now what you have to do, this is the one semi important part to this. You actually have to link your GraphQL file just like you would be linking a style sheet or your JavaScript file. You have to link your GraphQL file. Bump up that font size again. I got you guys, that's too big. That's it. That was okay. There we go. Yeah, link that GraphQL file just like that right there. Now let's hop into that actual GraphQL file that we were just looking at. And here's as with the GraphQL that we just looked at over here, this one's a little bit unique with the CMS pages, usually you actually don't want to pass in a information into. You're actually going to want to pass in information into your query. And that's what is happening up here. We're actually setting up different variables for GraphQL query to use. They do look like comments. They do look like comments, but trust me, they actually will set up a variable that can be passed into graphql. And actually I'm passing in these two variables right now. I'm passing in offset as an int and include ratings as a boolean. And as you see, we're actually pulling these from the query dict in the request. And so you can just like anything that's after the question mark in the URL, that's what's being passed in here. And so it's a pretty nice system that they built. So that means you can filter and you can query directly from your page and it will Dynamically reload the GraphQL and it'll update all of the returned data for you. Let me grab this query because I just wrote it and I was thinking we were going to have time to build it together, which we just did actually in GraphQL, but let me just paste it in here. Awesome. Now, running through, you might notice that there is one extra thing that we did not touch on just a minute ago. We now have this rating collection. What rating collection does is you can actually instead of just querying one object at a time in HubSpot, you can query many objects or tables or whatever you want just inside of one single GraphQL query. So while we could just grab the books, we could also now just grab books and then we could also under ratings we can grab rating collection. And then boom, just like that, let's grab our rating. And then I think we have book ID here. Cool. If I run this code and then I slide this over, you can see we did still get. I think I'm going to have to bump down screens sites just momentarily. I'll be back up at 125 in just a second. But we do have our book collection here. But we now also have our second HubDB table which is right down here. And as you see, it's getting passed in right there. And we can use that directly to our advantage. And in this case, sometimes we will want to show rating on the page, like what these books are rated or what these books aren't rated. And so we can dynamically include or exclude ratings by having it or not having it in the URL there, which is Pretty cool. And so we can actually include this only if we actually have include ratings in the URL. If we don't have include ratings in the URL, it's actually going to skip it. So it's not going to over query. So you can limit or increase whatever you want to. You can actually limit some of these different GraphQL queries if you're not going to use the data on that particular page. So in some cases we'll want to include the ratings. In other cases we don't need to include the ratings. Now if I go to my actual page, let's go to the actual module. Now you can see we're now pulling in this module data straight from our data query, which is our GraphQL query, and we're passing in data and then HubDB. Actually, I'm going to blow this full screen up. Awesome. Just like that. Now if we wanted to look at what this looks like currently, we could just type in library data and this will give us the raw output of that GraphQL query. And if I preview, it's just going to give us a ton of JSON data. That is not the greatest, but now that we have that data, you can really quickly. And I'm going to paste in code and we're running out of time a slight bit here, so we're not going to be able to go through every single bit of this. But it's a really simple table, just like the other card was. And in this table we basically just pass through our book titles and then we also pass through the book associations and we pull up the author and we pull through first name and last name there. And then this one, this is a little bit hacky, but we're just pulling in the book ratings and then we're matching it to each of the books. Right on, right in Hubble. So not exactly the way you want to do it, but it's a, it's a pretty cool example of how you can kind of merge two separate Hubble tables, Hub DB tables in one in one module, straight like that. Now if I go and publish this one more time, we can go check out the actual page and if we restart it and I'm actually just going to clear out any of our page parameters here. Right now we're on page nine of this. So if I close that and run that, we have a random false up there. I'm not entirely sure what the random false is, but we can now see. Okay, we're pulling in the first 10 results for a hub DB and we can actually literally go and match that against our hub DB and say, oh yeah, that is the first 10 result. But because we're also using paging now, you can click next and then what that next button does is it drops in a little page parameter and it says I want to be on page two. And GraphQL interprets that and says, okay, now we're going to pull up the second page of results with an offset for you and that include rating goes in and drops in a rating column here and it will include the ratings right here. Now some of you might be thinking, oh, would this be slow on an actual live page? Actually, HubSpot does a fantastic job of caching these query results if you don't have anything super dynamic about them. So as long as you're not pulling in like contact ID or like a time zone or stuff like that, you can totally have these results be cached on HubSpot CDN and page loads are great. Super snappy. I've seen a couple of really massive websites using GraphQL to pull in different CRM objects or HubDB tables, and they're just as quick as if you were running your Hubble code. So that's something to definitely keep in mind. You actually don't need to worry about it too much now that we've touched on kind of two different like interface slash. What like just viewing data. Like, let's actually take action on data now. And so we're going to be building, we're going to be looking at a custom coded action that I built that's, that's pretty nice. And that I use in production all the time. I don't know if any of you have ever run across this problem, but after someone gets enrolled in a sequence and a ton of tasks get clicked created, sometimes the salesperson will be like, well, actually I don't, I had a bad call with that person. He said, I'm not the guy. And they're going to unenroll them from a sequence. Unenrolling them from a sequence is fine, but your tasks are still going to be open. And so the next person that's going to pick up that account, they're going to have open tasks on that account. They're probably not going to be able to close those tasks because those tasks are owned by another person. So I built out a little system here where it's whenever someone gets unenrolled from a workflow, we can actually close all the open tasks for the that were in that person's workflow here that were generated by that particular sequence. So super simple workflow. If I click into this, you can see I'm using the kind of new trigger system here. Whenever a property value is changed and the now in sequence is set to false, we're going to run it and we're also going to double check that they actually have open activity. So don't enroll if there is, if all these tasks are already closed. So that's one little caveat there. It kind of, it stops us from overrunning this workflow. If I go to my particular contact here, you can see I have one task here titled call Dennis and talk about his chickens. If you haven't already talked to Dennis about his chickens, definitely find him at inbound and make sure to ask about his chickens. But let's enroll myself in a sequence here really quick. I have the sequence called dummy task creator. It literally just creates three tasks for us to have here. So if I create this and now I'm going to get a couple of tasks that are flowing in on this record in just a minute. And so I'm going to hit a reload here. Okay, we have one task, another reload. Still one task. We should see three tasks pop up here momentarily. Two tasks. HubSpot's HubSpot system is. Is a little iffy. HubSpot sequence system is not like super real time, unlike workflows. Okay, beautiful. Now we have all three tasks here, but we also have like this task for call Dennis about his chickens. So like say, an owner, the particular sales owner for this account was like, I need to close out these tasks that were created by this massive sales sequence. And I just can't deal with them right now. But I still want context about all the personal of all the personal tasks that I created myself. And so that's kind of where this workflow action comes in play. I'm going to open it up here and I'll go full screen here. What I'm doing here is I'm passing in the object ID of the particular contact. And then I'm also passing in the last sequence this contact was enrolled in. And then what we're doing here is we're running a query and we're saying, hey, get all the sequence tasks for a particular contact. And we're passing in our contact variable right here. And we're also passing in our sequence ID as another variable. And then we're using the CRM function and we're saying, grab a particular contact by ID and then pull its associations and particularly pull the task collections to contact associations, but filter it on that engagement coming from this particular sequence, which is a really special one. Even with the Search API, it's pretty tough to be able to pull in tasks by particular sequences and especially those tasks which are related to a particular contact. And so with GraphQL, it makes it super easy to find all of those different tasks and actually make sure that you're pulling in the right data and you're filtering on the right data. Then we're also saying, hey, filter and make sure the task is not completed yet, because we don't need to pull up any tasks that are already completed. And then we just threw in a massive limit of 500. If any of you have created a sequence that has 500 tasks in it, honestly, yeah, I don't even know what to say. Please don't create sequences with 500 tasks in it. But if you had this code would still handle it. So we're saying, hey, limit it to 500 of these tasks and then pull up the total. And then for every single one of these tasks, pull the object ID and task status here. Task status is not needed, but we have it there. Then we run that really quick and, and we're again hitting that collector endpoint and we're passing in one of our tokens here. And I defined that token up there and the secrets value. And then we're running a batch archive on every single one of these tasks that just pulled up in these results. And so, for example, I'll show you real quick. If I unenroll myself here from that sequence that I'm in, I'll just click on enroll and we're going to give it about just a second here and we're going to hit reload several times and boom, all of those, all of those open tasks that were related to that last sequence have now been cleared out and you don't need to worry about having a ton of incomplete activity on there. And so it's honestly a, it's a use. It's a really useful action that I deploy on, on most HubSpot accounts that I'm. That I'm dropped in because it just, it cleans up a lot of sales activities and a lot of tasks. So yeah, that is, that is that one. And I think that's pretty much it here. As I said earlier, I'm going to be dropping all of these into the HubSpot D Hog GitHub with a README for each of these files. And so if you want to deploy any of these, if you want to just play around with it, use it as a, as a getting started template. Please do that. And definitely reach out if you have any questions. I'm on LinkedIn. I'm on Slack. Honestly, drop your questions in the chat right now if you have questions as well. Yeah, Dennis, Love it all.
Carter, you deserve to take a drink. So everyone stop and allow Carter to breathe and consume liquids. Well done. Perfect. Wonderful. Perfect. Let's get some questions out there. And I think one that came up earlier and I know you discussed it. Can you just go over the point system a little bit more thoroughly? Because I know, I know it's, it's different from rate limits that. Yeah. In all the APIs.
So can you go. So HubSpot scores on a couple of different things. HubSpot scores it on the number of properties that you're requesting for each object and then also the number of objects that you're requesting. And so. And then it, it also has like, it also has like, whether you're pulling in associated objects or not. So. So there are a couple of different tweaks there. So if you can limit the amount of data that you're requesting from HubSpot, you, you use less points. And then if you also limit the amount of objects you're querying by using those filters and those paging and that offset, you can really reduce your amount of limits there. Actually, I wrote a blog post on the dev blog about talking about how we're taking something that's like 2700 requests and then bringing it down to one GraphQL request because of how efficient their point system is. And so that was a really fun example of something where I was like, I need this to run in a custom coded action, but custom coded actions have a 20 second limit and I cannot run 2700 requests in 20 seconds. And so I needed to make it efficient. And GraphQL, if you need to make something efficient in HubSpot, there's usually a good argument for using GraphQL for it. Yeah.
Yeah. Do you step to GraphQL first when you're thinking about now?
I do. Now I do. Yeah. So now when I'm thinking of fetching data or pulling up associated data for a particular object, I'm like, why wouldn't I use. Why wouldn't I use GraphQL? Because honestly, GraphQL's explorer is such a great way to like, quickly build out your requests, even if they're very complicated. And like, okay, I don't necessarily know the fields I'm requesting. You Just build it out in graphic, throw it in postman, test the code, test the code in GraphQL and just, yeah, toss it in. And yeah, Honestly I'm using GraphQL for most of my data fetching and HubSpot obviously.
Beautiful.
The one limitation of GraphQL is you can't update or delete any of those things. And so create, update, delete, it's just a get so right for getting data. Use graphql.
We got a question from Estron. Hey friend, thoughts on, let's bring that up here. Thoughts on letting users use front end filters or search books on that Library example. Any GraphQL limits there?
No. So there's no limits there. You can throw up as many filters as you want. Actually, the more that you filter the data, the less points you use. And so that's actually a big benefit. So you could say, hey, I want 500 books max. That's the limit parameter. But then you can also pass in the filter parameters and you have to say, okay, the filter matches the title is contained in this particular string or this particular string is contained in the title. And so you can really quickly build out those queries. And just by passing it in the URL, just by passing it in the query parameters. It's super easy to allow users to front end filter. And you can, like I showed on the paging example, you can just pull them in to the GraphQL query just like that.
Love it. Next question. Navaz says, so then we can use GraphQL and serverless. Also, I think you've censored GraphQL forever.
Yeah, GraphQL now has an endpoint, so you can use it in serverless. The one benefit, the really nice thing about HubSpot building GraphQL for CMS first is you don't actually need to set up a serverless function. You don't need to handle the fetching code. You just say, hey, HubSpot, here's the query I want to run. You guys run the query, you handle all the execution. Just give me the data when you have it. And so that's a big benefit of using GraphQL with modules and themes. But if you need to run GraphQL in a lambda function, heck yeah, use the collector endpoint.
Next up, Steven says, is it read only because the GraphQL only exposes queries or they're mutations, but they can't be used for some reason, unfortunately.
HubSpot. So HubSpot built a very, very nice query system for GraphQL. They spent a good Year and a half building out the query system and I have been requesting a mutations system for a long time. We have not gotten there. I don't know if the team's even like. The team has definitely considered it. I don't think they're working on it, but it would be really cool. But honestly, for a lot of things you need just use the create endpoints or the update endpoints. And now we have the batch upsert endpoints, which are awesome. So you can batch, upsert and update at the same. You can batch, create and update at the same time. And so the mutations endpoint would be uber cool, but at this point it's not like super, super needed.
Chris Paul asks Working at the example code that we reviewed today, Carter is going to be uploading that to the GitHub repository that I linked before and I will see if we can find that again.
Go follow the Dhug GitHub on GitHub and you'll have access to the code right in a couple of hours. I just need to clean up a couple of things.
I'm going to throw that in the chat.
Get around the 10 calls to the HubDB table rows function we have. Oh yeah, Aaron, GraphQL is meant for that. You can query. By default, you can query as many tables as you want to and pull up as many rows as you want to in GraphQL just as long as you're not hitting the points limit, which, especially with HubDB tables, it's actually pretty tough to hit the points limit because HubSpot is really, really nice about allowing you to query as many tables as you want, as long as you're being efficient with how you're pulling the data. So you can't just say, hey, just give me every single thing all the time. That'll quickly make you hit the points limit. But if you say, hey, I'm running a page where I need to show a listing of books and then if they click on a particular book, I want to show the ratings for that book, stuff like that is totally where you want to use GraphQL. But yeah, Aaron totally can get around that 10 function limit with GraphQL.
And let's see, is there anything else out there that we need to address? I don't see anything. With that being said, as I said earlier, John McLaren will be doing property history with GraphQL.
Zach.
Oops.
Thanks for. Thanks for popping that one. Unfortunately, no, not yet. I don't. Yeah, I don't. I have not. Yeah, I. That's. That's not Something that works currently, yeah, just the properties with history APIs is the best way to do it. So yeah, not yet. Hopefully in the future. That would be cool.
In your example, the ratings loaded. But if you only wanted the ratings.
For the books you loaded, that's great question, Jonathan. The one thing about that and actually, Dennis, I don't know if we have a little time to show more code. Can we go a couple of seconds over?
Friends, are you ready for a little more code? Say yes in the comments because I'm excited. Let's just jump right into it. Yeah, let's add that back to stage.
Boom.
I'll leave you to it.
Awesome. Thank you so much. So the one thing here is while we are requesting these books here and we're saying, hey, we only want 10 books here, we're saying we only want a limit of 10 books. We don't actually know what 10 books we're going to receive back. Like we kind of do know because we know what's in the table. Like we know in our heads what it's going to be pulled back. But GraphQL doesn't know yet and we can't actually use the results of this query in this other query. So you can't really say, hey, only give me the results of this particular book, only give me the ratings of this particular list of books that is pulled here. You can totally throw in a filter here though, and if you knew which book you wanted to filter on, you can totally throw it in right here and say book IDs equal and then throw in the book ID. So if we grab throw in one of these books and threw that in and scrolled down here, you can now see the rating for that particular book. So it's, you can filter if you know what you want to filter on. Unfortunately, in this situation, we did not know what we wanted to filter on yet. But in the situation of, hey, we had a book example and they can click on a book and it's going to load it up in a dynamic page, which is what a lot of people do, you can totally pass through that book collection filter and just filter on the particular book page that you're currently on. So you can definitely do it if you know what you want to filter on.
Yeah, so you just replace that ID with something dynamic, like a variable that can put in there on the front end.
Yeah, yeah. Or even the page slug, right?
Yeah, yeah, yeah, yeah, exactly. Let's see. We got another question. As an integration developer, can we use GraphQL to get data from HubSpot and sync with other CRM.
I do that all the time. Yes. Yeah. Heck yeah. What can I do with GraphQL?
Yeah, right. You can't create. I think that will just about do it. As I said earlier, John McLaren is going to be coding live on the cms tomorrow at 12:30pm Eastern time. And next month on the 29th, we'll be doing a collaborative experience for Road to Inbound, where we talking about all the inbound stuff for the next developer hug. Stay tuned. Emails be sent out. Carter's gonna be pushing some code up so you can go play around with it. Feel free to add any comments like issues to that code and we can look at that and have a nice community. It'll be fun.
Heck yeah.
Carter again, thank you so much everyone. Have yourselves a great day.










