The below transcript has been auto-generated for your convenience. Please reference the source video/audio for direct quotes or to clarify any errors.
Speaker 1: (00:04)
Hey everyone. Um, I'm gonna see about get a, can we get the, the deck shown, whoever is sharing the deck.
Speaker 2: (00:13)
Ah, there we go.
Speaker 1: (00:16)
Alrighty. Welcome everyone to our second masterclass. Uh, this one is basically around building an app. Uh, if you were around the last time around, it was really about the considerations that you need to be thinking about when it comes to making a HubSpot app, what a HubSpot app actually is. Um, and some of the considerations, whether it's a large app or small app, and team considerations or things of that nature, uh, today is much more hands on, uh, where it's gonna be, just build. Um, I am Ty Fallston. I am the CTO of Aptitude eight, where we pretty much stake our lives on the HubSpot cuz we absolutely love the platform. And, uh, I pretty much lead our, um, product development and a lot of our kind of just IT engineering as well.
Speaker 2: (01:03)
I have that I run the a labs portion of our business, so we create apps for sp hub by ecosystem strictly. So apps integrations are what we do all day. We like to, uh, fill the holes that HubSpot hands, but there's not that many of 'em, so we're always looking, uh, yes, there is only alone. So, uh, but this is gonna be a gray. We're really excited to present today the actual nitty gritty in the weeds of developing ops by applications. Not a lot of council out there for, it's gonna be one of the first, so we're so excited to be able to win some.
Speaker 1: (01:35)
All right, so today we're gonna be discussing, as you see right here on screen, we're gonna be creating an app in HubSpot. And by creating an app, we basically means, Hey, HubSpot, we're creating an app. Um, give me an app by, essentially we're registering our app with HubSpot. Uh, we'll talk about the install flow with, with Ooff, and if you watched our last video, you would know that there are three different ways you can basically access, uh, HubSpot. But we're gonna talk about the Ooff method because that is the method you are going to be using if you are making, uh, apps for the public. Uh, the the other ways we're using API keys, which is a depreciated way, and private apps. And private apps work great if you're making an app for yourself, I mean for your company. But we're really kind of talking about more public consumption here.
Speaker 1: (02:20)
Uh, next we're going to be, I, I've already developed a very small app, um, that is going to be the middleware that is ultimately going to connect to HubSpot. And then number four is creating the CRM card. This is basically how you would take your little wear and how you would integrate it into HubSpot, into the HubSpot ui. And then after that, we will take a few questions. Side note, we definitely wanna hear from you as we're kind of progressing through this presentation. Please feel free to add questions to the, uh, to the common section here. So we're going to ultimately come to a point where we're just doing q and a and it'd be really great if we had a bunch of questions kind of lined up and I think we kind of knock 'em on down, uh, when we get to that particular part Del, and be shy to ask any questions whatsoever.
Speaker 1: (03:05)
Please fire away. Okay, kind of getting back to the slide here, primary goal here is we really are going to build, we're gonna go through the subs of building a really simple app. So that starts with having a account. And to recap, uh, a HubSpot account is you, you need it like, period. You cannot get away with it. Even if you're not gonna be tracking contacts and deals and things of that nature, you simply still need a HubSpot app. Uh, really easy to set up, takes you all of two minutes and then boom, you're ready to go. Uh, once you have your HubSpot app, then you can create a developer account. And a developer account is essentially you tell the HubSpot, Hey, I'm a developer, and it is where all of your apps will be registered at. It is where your apps will be registered.
Speaker 1: (03:52)
And it is also the starting point of when you go to put your app into the eco place, it'll pretty much start with your developer account. Uh, your developer account is also where you will get your developer API key when you need it. Uh, so everything HubSpot dev related starts there. Uh, what you will need if you are attempting to follow and or mimic, um, a HubSpot app is you will need a web server and an application server. And in our case also need a database server, uh, web. The, the technology here that you use is totally up to you. Uh, the middleware, if you remember from the last session, it exists wherever you host it. So it is not a traditional app in the sense of, Hey, I'm going to put a bunch of files together and then it's gonna run on hardware like a phone or something. Uh, it is much more like it's a website that I built somewhere on the internet and it's publicly accessible to HubSpot, and we're going to use that accessibility to bring things from my middleware into HubSpot. Um, in this case, we are using, um, a Windows box, which is using internet information system. So I s 10, we're also using a open source form of ColdFusion called Lucy, and we're using MySQL for the data store. Next slide. All right, connecting your app to HubSpot.
Speaker 1: (05:14)
So as I kind of said beforehand, just kind of beat this with the dead horse or like a dead horse. Apologies. Uh, there are multiple waves, and I just wanna touch on this real quick. The a every HubSpot instance has an API key, and if you are building apps for the public, you ultimately can get an API key, but you do not want to get an API key because it doesn't give you God access to the person's HubSpot. And if something goes wrong, it's gonna be really easy to point a finger in your direction. So to make sure you, you eliminate that risk, you either want to go down the private app or the oau route. We are going to go down the oau route because in this example, we are making an app for the public, uh, private app makes a lot more sense if you're making an app, maybe for yourself and or maybe for your company.
Speaker 1: (06:00)
Uh, but we are going down the OAuth route because we are gonna make the assumption that anyone can sign up for an app and it needs to be pretty general. And, uh, we wanna be able to protect ourselves with some of the things that come with ooff, uh, like setting permissions and the token expire. So those two things will help prevent you from accessing things you don't want. And more importantly, your customer, uh, yielding access to things that they don't want you to have. And in addition to only doing it for a limited set of times, so those O off tokens expire after 30 minutes, and after 30 minutes, you then have to refresh the token. So you could easily say, Hey guys, I need to tell your customers guys, listen, you know, after 30 minutes, if you don't want us to have any access to your app, you don't have to do anything.
Speaker 1: (06:44)
You don't even have to uninstall. We just simply will now refresh the tokens. Uh, or you can where they can uninstall your app will be the, the exact same thing. Uh, the developer API key, uh, just to kinda hammer home on that, um, is a very niche like credentials as far as I can tell, is only used when it comes to, uh, managing parts of your app that have to, that directly use workflows and the HubSpot workflow ui, uh, outside of that, not a whole lot of users for, but just wanna drive that point home. Next slide. All right, so, um, I am going to start sharing my screen here, and we are going to do step one, which is registering the app. So let me get my screen going here.
Speaker 1: (07:34)
Okay, so this is the, the, uh, the s we're before we were, um, acquired by eight. This is our developer account. So just kind of real quickly, I'll show you this. We have a long list of apps. I've created an app down here for the mass, just for the sake of this demo. It's called Masterclass Demo. Uh, when you come in here, you're basically going to add your, the name of your app, you wanna give it something descriptive. Uh, you always want to add the description because a lot of times you may have apps that operate in different environments. Maybe you have one for production and staging and development. So you wanna make sure that your description is very descriptive of what's kind of going on. Uh, and then you're gonna come over here to the off part. The off part is what essentially, uh, really helps delineate your app from other people's.
Speaker 1: (08:25)
So when you submit your app and by submitting it, I mean you're basically just going to fill out this app ID form. If you were to come over here, yep, you'll get the save option. And then once you get the save option, um, this off part is going to then populate. So you'll get an app id, you'll get a client id, you'll get a client secret. And then what you will have to do as part of the authorization as far as the OAU process is you need to specify somewhere on the internet, um, somewhere that, uh, you, you're familiar up where you can basically take the OAU code that's given to you and swap that out for access and refresh tokens. And we'll come, uh, we'll come across again that come across that in just a little bit. Once you've added in your redirect url, you wanna come down here and you want to basically set the permissions for your app.
Speaker 1: (09:18)
And what this means is these are the objects or the object structures that you are saying you want to be able to manipulate. So if it's, for example, companies or contacts for, for this example, I'm, I want read and write access to contacts. Um, see the schema means your ability to alter context. So maybe add a new field, drop a field, change the name of a field. Uh, it's the schema, it's, it's the structure of the object. So read and write. You will definitely, definitely want to only pick the ones that you really need, uh, as you go, as you're, if your ad becomes really popular and you go to, to get your app certified. HubSpot certification team will definitely look at your permissions and look at the app's usage and determine if the scopes, if the permission scope that you've chosen really are in usage or not, and will suggest maybe you, uh, remove some.
Speaker 1: (10:14)
So you wanna make sure that, again, to reduce your risk and other long term things, you wanna make sure that you only use the scopes that you really need. You also notice that crm and then there's legacy. Uh, this is essentially new to HubSpot. So before maybe, maybe three or four months ago, they used to only be this, uh, all the way down. And it's definitely a longer list and it's a little confusing. But HubSpot has really been trying hard to kinda reap, uh, their permissions to make it a lot more granular and to also just make it make more sense. Um, more than likely you are going to be picking some combination of these, the CRM scopes, again, this section is new and probably something from Legacy. Again, um, only pick the one that you need for the sake of this demo. We're only going for contacts.
Speaker 1: (11:05)
So as you pick your, uh, the scope that you need, you'll see that the install preview changes on the right hand side. This area here is what your customers are going to see as they are about to start signing up for their app. It basically says, Hey, you're gonna sign, you're gonna let, you're gonna sign up for these people's app and here's what they're gonna be manipulating inside of your, uh, inside of your HubSpot instance. And they need to be okay with that. Uh, again, we're only going for contacts. So as you pick these, you can actually see up here that these bed boards are changing. This is pretty much your list. And once you have selected the ones that you want, we'll just pause here. This area right here, your install ooff is going to be populated. So if we kind of look at this, it is basically the, uh, redirect URL in addition to its scopes that you specify.
Speaker 1: (12:06)
Now, I want to add this in here. The scopes that you specify here, these are the required scopes. These are the, these are the scopes that you are saying, Hey, my app will simply not work without it. There are other scopes that you can use and to, and you will actually have to add them manually. And to do that, you'll have to add the ampersand. You'll have to say optional, and then you'll have to, to add the scopes that you want. For example, if you say he wanted, um, I dunno, custom schema dot, then whatever the name of some custom object is you have, you'd have to actually add that in manually yourself. Uh, so that, that's a caveat that a lot of people don't necessarily know about. Uh, now, you know, definitely take that, that back to work with you. Uh, for the, again, for the sake of this demo, we're only doing ti. This oau URL is ultimately what you are going to hand to your customers so that they can begin installing your app. Okay? Now that we have that established and now that we have actually specified a location of where HubSpot is going to, and actually, lemme back this up here. When you give someone this a, this oAuthing leak, they're gonna take this bad oric, they're gonna put it in their browser, and it's going to, oh, hold on, set live demos always painful.
Speaker 1: (13:26)
All right? And it's gonna bring them here. So this is what installing an app Ashton looks like. And then you would want to pretty much cycle through whichever HubSpot is, and if you want it on, and you gotta choose account. Now, once I hit the choose account button, it is going to then redirect me to this location right here and append it to this location is going to be something like this code equal blah, blah, blah, blah, blah. It's going to be the, the, the authorization code. So if we kind of go back here, we choose account, it's basically gonna say, Hey, are you absolutely sure that you want to do that by default? I actually had already installed this app for the sake, the demo. And so now it is redirecting me here to my redirect url. So let's take a look at this. This is the, uh, and masterclass.app.io. This is publicly available. If you guys wanna go to it, feel free. Uh, but you can see that this is the re direct URL that I specified. And then HubSpot themselves automatically appended the authorization code. Great. So now that we see that HubSpot has already appended the authorization code, let's take a look at this, installed that CFN script to see what's going on there.
Speaker 1: (14:42)
Okay, so in the script, if you're not familiar with ColdFusion, I'll kind of quickly walk you through it. Uh, but we're looking for a query strain key URL dot code. In code fusion URL is the, the, the global scope for everything that's in the query string as part of a page request. And we're taking that code and then we're specifying the client id, the client secret, and the app redirect url. These three variables are something that is stored in our, in our database that we pull out just for the sake of making this request to actually swap out the, the code for, uh, for access and refresh tokens. I also have a rapper class here called HubSpot api. If we, uh, take a look here, let's see. And again, uh, this entire application is actually, uh, on GitHub. In fact, lemme go ahead and throw the GitHub link in the, in the chat there.
Speaker 1: (15:39)
Speaker 1: (16:29)
We are passing in as form fields, the client id, the client's secret, and the redirect uri. These values right here directly come from our app by our client id, our client secret, and then our redirect url. So that's what those values are. Um, and then you wanna make sure that you have the, the header here involved. This header's actually optional, but this application forming code, this is mandatory. This is what you need to, to make the call. And then lastly, we're actually passing in the code that came from the URL as another floor field. That's part of our request. The result of that request is an object. This is gonna be a J S O object. And I pretty much just dumped it out here to this screen for the, for the sake of the demo. But you can see, uh, it, it, it was successful and HubSpot returned to us, the token type.
Speaker 1: (17:24)
It returns to us a refresh token. We'll need this later when we go to refresh our access tokens. Cuz remember they only last for 30 minutes. Here's the actual access token itself, and they give you another, uh, property that says expires in. So basically, how long do I have until I have to refresh this be, when does this access token inspire? When am I gonna have to refresh? That's what this value is. Uh, and this value is in seconds. Okay? So if we go back and we look at our install script, we're making our, or making our API call to get the token, we put the value or we put the response in this token response object, and then we're basically saving it to the database. We have a table called config and we're basically saying to this, to config to the config tape. Uh, just a heads up the database that we're using here, if you're in the repo, that is actually here in the masterclass underscore demo that SQL file. So the entire database definition, everything you need is actually here.
Speaker 1: (18:26)
And if we want to take a quick look at what that table looks like, here it is. So here's our, here's our masterclass, here's our, uh, our table call config, uh, here's the access token and stuff like that. Uh, everything that we need that we'll be using later on. Okay? So now that we have a flow to install, um, to, to go through the install, we need another one that will simply refresh our tokens because they do expire every 30 minutes. Just wanna beat that with a dead horse. And I do have a script already in place for that. It is refreshed cfm. And let's take a quick spin through that real fast.
Speaker 1: (19:07)
This script basically does a few things. One, it grabs the access token in the refresh token for our database. Um, and then calls, we're gonna make another instance of our h uh, HubSpot API rapper, and then we're going to call the refresh token. So if we take a quick look at the refresh token method, very, very similar to our initial, um, token API call, we're gonna pass the grad type again except this, instead of being authorization code this time it's a refresh token. Again, we're gonna pass our client id, our client's secret, our redirect url and the actual refresh token. So when you go to refresh the token, you don't pass the access token, you pass the refresh token. And the refresh token was something that we initially got here, okay? We're looking back at our original, uh, request for, uh, for token data. Okay?
Speaker 1: (20:00)
So now what we would really want is you would want to be able to call your refresh that CFM page every 30 minutes to make sure that you were indeed getting new fresh token data at all times. Cuz you'd never know when your client ultimately is going to be needing to make API calls. Uh, if we go back and we look at our refresh page, our script, again, once we get that refresh token ba uh, data back, we're just saving it back to the database. Really simple, really straightforward. Okay, so now that we actually have access to someone's HubSpot, now this is essentially where the meat of the app really begins. And the, in this particular app, the only thing we've done is we have a login script. So what we wanna do here is we wanna say, Hey, here's a login page, and when someone puts info into this page, they're gonna put in an email address.
Speaker 1: (20:53)
I need to be able to reach out to someone's HubSpot and I need to see if the person with this email address actually exists. And if they do, then I need to check on their password. Okay? So this page, aps, uh, masterclass dot aps do io slash login goes directly to this page, right? Oh gosh, where is it? Here's right here, login. And if we scroll to the bottom, um, we'll see that there's a form. This chunk of the, of, of the script lines, 84 to 129 directly correlate to this form that you're seeing here.
Speaker 1: (21:32)
Um, and then the rest of the script here is actually going to handle the flow of when someone actually submits the form. So let's, let's walk through this. You can see what's going on. I think everyone knows how form works. Um, but let's see what happens first, our logic says that if form.email, that is when you submit a form of codefusion, just like there was a URL scope, there's the form scope. And the form scope basically is a structure that contains everything about the form that was just submitted. So in this case, there's a, there's a form field called email. If you look down here in this form, we'll see we got, uh, we'll see you have an input name is email. That's where that kind of comes from. So we're looking to see if it's empty. If it's not empty, we're like, Hey, I think we got something.
Speaker 1: (22:18)
First thing we need to do, let's go grab the access token from the database. Next thing we need to do, let's create an in, uh, let's create an instance of our rapper class and let's pass the access token to that rapper class. Our rapper class actually has a little bit of logic in it that will take the access token and then send it as a, as a header for all of our API calls. So if we were to simply look, um, at, let's take a, let's take a sample right here quick. Um, I'm trying to look for a simple one. Here we go. If we're looking to get someone's custom objects, um, here's the authorization header for example. So you would part of your HTP call as part of your API call, you wanna have a header called authorization and you wanna pass in the word bearer and then the value of the access token that we just got and refreshed earlier.
Speaker 1: (23:09)
So that is this, this header part is like dead necessary for any API calls that you're going to make that using access to. You absolutely gotta have it. Uh, other, and then next is the content type application dot json. You absolutely need these two. If you do not pass in these two headers in, you will get two very irritating messages. One is going to say no authorization data found. The second one is going to say media unsupported. And the media unsupported one I kid you not will send you howling to the nuthouse. So make sure that you have application json and the content type header specified as part of your API calls. Okay, now that we got that right, going back to our login flow, uh, , yeah, I did this. We're creating an instance of our API class. Next thing we do is we're actually going to make an API request to find a contact by email address.
Speaker 1: (24:10)
So part of that, part of this form that we're looking at, I'm gonna put in here, uh, yeah, email domain.com. I'm gonna submit the form. We're going to do an API call, and if we look at the API call request, kind of go back to our wrap class here, uh, instead of doing a post and, and, um, we're doing, uh, a gi So here's the URL that's being generated. We're basically making a call to the contact api. We're passing in the email address as part of the URL because that's what's specified in the, um, API documentation. We're asking for a few other fields to be returned to us, like first name, last name, email, phone, and then we're basically making our API call, okay? So once we make our API call, we're gonna dump this out to the screen and let's see what happens. I'm gonna put in some, uh, Woody Glo and I'm gonna hit login.
Speaker 1: (25:03)
Okay, great. So what's our response here? This is the direct response that HubSpot gave us. Basically, contact is not at exist ultimate. And what we did was we took the error message here and we threw it right here just in case something bads happened. We wanna let the user know, but this is what it is. We, we stored the results of the API con contact of the API call to the contact results object. We basically said, Hey, if there's a property on this object, on this response object that says status, something has gone wrong, right? Something is, is not, it's just not right. Uh, and then we wanna dump it out to the screen. So that's what we're looking at.
Speaker 1: (25:46)
But what if someone is, is there, right? What if the person is there? And so let's see, aptitude.com gotta give Ty blo for a password. I'm gonna hit the login button. Okay. Ah, so this time is very different. The response we got this time is because HubSpot actually found a person with that email address. And you can see part of the response is we get the, the id. Um, we will actually, this, this response will actually tell you if this contact's ever been merged with another contact, the portal that it belongs to, and then the meet, okay, GLI gl is a real word. Uh, the meat of the response here, which is first name, last name, email address, and last name not modified. When you're looking at this data, uh, for example, under the property's first name, you'll see that the value is tyrant. That's me.
Speaker 1: (26:38)
And then you can see the, the, the field history. So tyran was only added its contact once. If I had changed it from Tyran to Steve to Jacob to Dax, you, the, the versions here would be a very deeply populated array. And uh, HubSpot will actually give you the history of any field, 20 iterations back and 20 max. Uh, so just a heads up on that it, for the example here you can see that we actually found a contact named Tyron. Um, and then returned us some data. And so if we look back through our code this time we don't see a property name status. So let's go to our LS lodge. Now that we found a contact, now we actually need to see if the email address and that password actually matches someone who's in our database. This is how we know we have a legit user.
Speaker 1: (27:30)
And in most cases, if you are building a login, you do not wanna store that password on HubSpot and you wanna store that password yourself, you have no idea who has access to that password HubSpot. So to limit any damage and to reduce any risk, you would always wanna keep that password, uh, in your own data store. As you can see here, I've got a query and if you're familiar with Cold Fusion, um, and in my style, I generally like to do multiple queries and one query block just to hit the database, hit it hard, give that I need get out. Um, I'm doing a search for that person based on email and password. I'm putting the row count into a variable called found users. And then I'm saving the results of this login attempt to a table called login history. And then I'm also saving, um, the IP address of the person who just tried it, as well as how many rows I found from my initial query up here.
Speaker 1: (28:23)
After that, I am returning the results of my found user and then I'm using that Incode Fusion to set a message that appears in my form. So if the number of users found was, which in theory should be one, if it is a one, congrats your credentials were filed successfully, check the log table for details. If it was not, we're saying no user could be filed those credentials cause really we're only looking for one person and this form do message will optionally appear here down in our form based on if there's actually something to show. So we've kinda looked beforehand. Um, right now we, we, we found a user in HubSpot, but we didn't really couldn't really determine if the credentials matched because the password was pretty much garbage. I just wanted to show what happens when a for a negative outcome. Uh, if I look in here in my credential history, I do have a Tyron at APT 2.8 user and then I am going to now add in a legit password and let's see what happens.
Speaker 1: (29:24)
Okay, so hubs five, return the user and whoa, congrats your credentials were successfully found. Okay? So part of this demo is that we are always saving, um, these attempts to our database. We have to have a database table called login history. And you can see right here we had an unsuccessful attempt. We tried again with the right password, we got a successful attempt. Okay, great. So now that we have a baby app, now the question is how do we get this into HubSpot? This is, this is the, the, the the million dollar question. I got this app, how do I get it in there? Okay, we're gonna go back to our app. We are then going to go to CRM card. Now discarding changes cuz we're just kind of fiddling around and I've created a CRM call, CRM card called login history. Now, where do we want the CRM card to appear?
Speaker 1: (30:20)
We want it to appear on the contacts record. So what this means is that every single time a HubSpot contact page is opened, HubSpot says, please give me, I wanna create the CRM card for you, but give me some direction. I need some data to know what to show on the CRM card. Point me to someplace public on the internet where I can go to that. I can think about, Hey, I want to, he wants me to show this about the user, he wants me to show that about the contact. Where should I go? That is what this data fetch URL is ultimately. And when you, when you specify this in, you could actually say, Hey, as part of your request to this url, I want to add a bunch of crap in here. The object id, the first name, the last name, the email, all these things will become query string attributes to this location.
Speaker 1: (31:13)
Okay? And if you are curious what is coming out of this, you can always go to monitor, we'll discard real quick CRM extensions and you can actually actually's see what HubSpot is requesting. This is, this will help you debug and find out what the heck is going on, right? Okay, so if we go back to my ty aptitude that a, um, user, I have a contact in here already. I tried to log in with, with him two times as we saw previously, one time unsuccessful second type successfully. I have a CRM card that I have generated and this is what's being generated. Now your question might be, Hey, where in the world did all that crap just come from? Fantastic question. I see. Let's find out. Okay, so this is ultimately, uh, if you look here, the url we have CRM card json that directly goes to this CRM card that I just made.
Speaker 1: (32:12)
So what happens is the TY fall, I'm just gonna load this page up again, part of what takes the, the, the the contact part so long to load up and you see all this stuff here on the right hand side, all loaded up is that HubSpot is making like a crap ton of a, uh, a CTP calls in the background specifically to wherever you specify. And if we look right here, you can see that we have our CRM card that is loaded. It has masterclass contact summary. It's got a little bit of data that I specified. It's got a, it's got a, a little button here and there's login history. Great, great. Grace, show me where this got generated at. Again, if we go to our monitoring, we go under CRM extensions. This is it right here. And in fact, as you, as you look at the details, this is the exactly URL that was actually being called.
Speaker 1: (33:02)
So if we copy this, we put it in the browser. This is the J s O that was generated that built this CRM card. So if we, let's, let's look at this JSON and let's purify it pretty upfit, if that is the word. Let's throw it here, um, in our bit and we can kind of take a look at it. Okay, so this CRM card came from this JSON code. Um, you'll see the title is masterclass Contact login summary, which directly correlates to this title here, uh, login success. Um, and then you'll see a few other lines, successful login percentage and total ips. And if you look at these, these are properties of the CRM card for each property that you want to show. You actually do have to specify the data type and whatever data it is that you wanna show, and then the label.
Speaker 1: (33:56)
Okay? Also part of that, if you notice there's a actions dropdown button at a login history. That login history comes from right here. Here you see the actions and then the actions is an array. And just like you saw login history, you'll see login history here. So this directly correlates that. And then this is going to, ultimately, when I click on this login history is gonna pop up as a I freight. And the dimension though that I frame is specified here and here. Now, if you look at this crm, if you look at this, the page that generates the CRM card, it's CRM card dash json, that directly correlates to this script right here in the repo. Uh, so here I'm Ashley going to the URL scope. I'm looking for the HS object id, which we know got passed over. I'm looking right here in our login history.
Speaker 1: (34:52)
So I'm basically just doing a database search and then I'm dumping that out to make my J side response. So I've got a, I've got a, uh, a very generic object. I'm populating it with the, the title like we saw beforehand, the description, like we saw beforehand. I'm populating my properties array like we just saw beforehand. Uh, I'm populating my actions array like we just saw beforehand. All this is a direct correlation. Uh, and then I'm dumping all that j s o to the screen. And the result of that is this content right here. Okay? So now that we have the ability, we have an app, we are able to output, uh, we are able to create a CRM card, we're able to generate content for that CRM card. We can actually see that CRM card on the contact. Let's go ahead and hit our login history button.
Speaker 1: (35:42)
And it's a I frame in of a page that we are in control with. So the what just got I framed in is this Bad Boy right here. So Ashley, for, for for Better Visuals is this Bad boy right here. We just, I framed in this page. And remember we are in control of this page. This page here is CRM, car dot cfm, which directly correlates to this page right here. Only thing I'm doing here, looking at the url, contact id, going to the database and then looping over the database roles and dumping it to a table. That's what this page is right here. So it looks, it's in the HubSpot ui. Looks like it's coming from HubSpot, but actually this comes from the middleware that we built. This is how you get your data, your content, your middleware, your app ultimately into HubSpot so that users have one place so they can go and do everything normally.
Speaker 1: (36:41)
Um, what you would want to do is you would maybe wanna do some additional contact management here. You can have a form here. You can have everything you are in complete control of this page because it's, I framed in from some location that you specified. Uh, the only true caveat with having your I frame in is that it has to use https s there's no way around that. HubSpot will simply not load it. Um, but which really should not be a deal, honestly. Uh, we should be worried about security from every standpoint possible. So, um, I'm trying to think. I think that may cover most of everything that we want to do. So from end to end, we've pretty much built an app. Uh, we've got it into HubSpot. We created our CRM card, we're showing that CRM card inside of HubSpot. Uh, we've talked about assets, tokens, we've talked about refresh tokens. Um, again, the, the get repo is publicly accessible. It also has, um, the rapper class in here, which I would definitely tell you guys to leverage. It also has the database definition in here as well. Um, and so with that, I would like to take a quick pause and let's go about answering any questions you guys might have.
Speaker 3: (37:55)
First of all, I wanna say, uh, that's, uh, some great content. Also, I'm allowing you to, uh, turn on your video. I apologize, that was my fault. And, um, go ahead. Nah. Hey, there you are friend.
Speaker 1: (38:06)
There I am. I was just a talking a talk. You hit all this time.
Speaker 3: (38:11)
Yes, yes. Um, of information here guys. So, um, I can understand it if this is a little overwhelming. Um, but yeah, we're here for any, uh, q and a. If you can't think of it right now, which I totally understand, you probably wanna go rewatch that content about 3000 times. There is the issues in that GitHub repository
Speaker 1: (38:34)
That, uh, go ahead and spit 'em there and we'll make sure we get to 'em from there as well. Yeah, for sure. Uh, I, I would add 'em there if anyone wants to talk about just application development and generally very welcome to, to reach out or grab some time on a calendar. I definitely will give you a few minutes and answer any questions you have, especially around business decisions and or security. Uh, I always like to specify that developing in Apple HubSpot is actually really easy cuz it's just developing your own app. Uh, the, the number one question we get is how in the world do you get it in there? Uh, and that ultimately is the part that we, we really just kind of talked about. Um, and I think that's where, you know, this, this meeting hopefully really helps. And, um, you know, each one, each one.
Speaker 2: (39:24)
I think one of the common ones too is, uh, for the, for the no coders out there, um, they're using platforms such as Bubble do IO and tones, the other awesome NOCO platform because the idea, Ty, if you could speak on this, I know we don't use no code cuz you code, but the idea is that if you're able to accomplish these simple steps such as authentication, token, refreshing, um, building a J S O file, right, based upon whatever you could be able to, uh, utilize a no code platform. You wanna speak a little bit on that.
Speaker 1: (39:52)
Um, you know, I I generally take the approach of, uh, bio build. So if there is a way to do something, uh, with low code or maybe with an existing service, I assuming, you know, this isn't like some something kind of blow up your budget, I would do it. Um, the, the rationale there is every line of code ultimately cost something either initially or down the line for mainten. Um, and so, you know, if you, sorry, if you can find some kind, some kind of middleware that will definitely do that for you, 100% would, uh, recommend leveraging that.
Speaker 2: (40:29)
Then we had a question from David Roma about, uh, passing the server piece to a serverless solution like, uh, Google Cloud functions or aws. Uh, I know you can talk about that for another hour if you want, uh, about the involvement of aws. But if you wanna touch on a little bit how potentially, uh, how associate works with, uh, utilization of Lambdas and the messages that would be kinda help David,
Speaker 1: (40:54)
Feel free to, to update your question here. I wanna, I'm gonna take a stab at it. Um, one thing that you may want to consider is the, the, the CRM card gets loaded every single time someone opens up a contact record. In this particular example, um, a lot of times you may have it where the CRM card card opens up on tickets and deals and contacts and cups, right? And you're talking about a lot of page requests that HubSpot is making to get contents to ultimately build your CRM card. Uh, a easy recommendation there is actually, if you're thinking about scalability and you're thinking about is to use maybe an AWS Lambda to actually handle those requests. Uh, the, the, the, obviously the thing is you don't necessarily know when spikes are going to occur and you wanna make sure that CRM car is always available.
Speaker 1: (41:46)
So it's very easy to recommend that you put the logic that generates that json into an AWS Lambda or some other kind of compute that spins up and spins down. And, and maybe it's not an AWS Lambda, maybe it's just a EC two instance or a compute instance that you keep warm. It can handle the scaling or scaling group, but it is something that you will want to be concerned about, especially if you see page loads, uh, you see a lot of requests kind of coming down the pipeline. Um, I hope that answers your question. If not, feel free to ask again, not take another stab at any other thoughts. There's no, no such thing is a bad question. Um, and definitely very happy to help.
Speaker 3: (42:34)
Just outta curiosity, how, how often are you, uh, checking your rate limits? I mean, what's, what's your process for, you just said like going back and forth, hitting nut CRM card every time you're loading data. Do you ever have issues with that? I mean, you have a lot of service.
Speaker 1: (42:48)
Yeah, so we, for example, we have an app called Associate, um, which handles a lot of things that come outta the HubSpot Workflow Engine, uh, which we actually check every day or we have alerts set up, uh, that basically kind of let us know what's going on. So, um, as far as the CRM card, we actually have a couple of servers involved, uh, with a low balancer, uh, and a scaling group because we handle, uh, millions of requests per month, uh, from people opening everything, right? So we have CRM cards on contacts, tickets, deals, you, David, uh, and, and so ultimately we have millions of requests. And so it's usually very important that that CRM card is readily available, um, because the apps that we build, people are expecting that CRM card to be there every day, all day. Now the good thing is if it bombs, maybe the first time, maybe we refresh on the second time. Terrible thing to know, but definitely does happen. Um, and that's an architectural issue. You can definitely talk about another day. Uh, but you wanna make sure that as your app grows, especially for using oau and expecting a lot of people, that is something that's going to get hit a lot.
Speaker 3: (43:59)
Cool. Um, I think that's good. Uh, once again, I just wanna put that out there. If you got questions, seriously put in that GitHub repo, you know, there's an issues section to add there. These guys are freaking smart, so take advantage while you can, because why not, right? Um, you will have questions. Go out there, play with this because you're gonna learn a lot. Just, you know, one thing is watching someone do it, the other, when you do it yourself, you're gonna hit issues, you're gonna hit Roblox and you want these people here to be able to help you out. So, uh, yeah, Smith, those issues. Yeah. Um,
Speaker 1: (44:34)
And, and, and just actually wanted to think about, uh, David Roma there. Again, part of the thing you may want to, uh, kind of consider is if you have an AWS land that handles a lot of your crm, carbon quest, uh, it, cause I think we'll get beat up. It's great to have Orlando because AWS will handle the scaling for you. Uh, in addition to, you will also want to use an RDS proxy if your Lambda connects to your database, uh, that will protect your lambda from blowing up the number of connections that go to your database. Uh, you may also wanna kind of consider caching, because Lambdas can get spun up. You can have a thousand Lambda spin up, uh, and they will all descend on your data stores like no man beforehand and your database can choke. Uh, so you may wanna consider some caching or if you go into the database, an RDS proxy or something that the like is definitely gonna be needed. This is one of, um, as I was just kind of brainstorming in my head there.
Speaker 3: (45:25)
Cool. Um, I apologize, I'm gonna put your name. I apologize for this Sierra or Chira. Um, as to, I think a pretty legitimate question here. Uh, but at level, at level in one tech career, at what level, in one tech career, would this be something that one would understand and utilize? So
Speaker 1: (45:42)
The expectation is to build an app like we just built. Um, this is a, a junior level could, could do this. Um, that is just simply building the app, getting it ready. A lot of the stuff that I talked about that may maybe spoke to David's question are definitely more advanced. Uh, but to build the app that we just talked about in terms of like, Hey, I've got an application server, I've got a web server, I've got a database, so a June, that is definitely, uh, junior dev would be able to handle that. So I like to think that from a skill sets perspective or from a senior rich perspective, HubSpot apps can be done from the very bottom all the way to the very top. Um, the only thing you really need is ultimately a good plan.
Speaker 3: (46:22)
Yep. Just get in there and do it. That's what I had to say. You know, like I remember the first time I looked at APIs like I was scared as, oh, get up and now, you know, I feel pretty good about it, so just do it. Yep.
Speaker 1: (46:33)
Agreed. I, I, I tend to think that, um, the HubSpot community is actually really, really, really kind really, really there. Um, we really just want to, part of this is to make more video content, um, to just make it just easy, even even easier when it comes to accessibility. Cause we have a lot of people who are getting into HubSpot development and unfortunately developers, a lot of times we like to go into a closet and we don't really share our info with anybody. And you know, while the community is there, the community's all worked. They're all, they're all busy building their own apps. And so it's, it's good if you can, you know, jump on a stack overflow where you can hop on a masterclass video and kind of spend a few minutes following along and, you know, pick up, pick up a hopefully solve a problem that you just had and we solve for you.
Speaker 3: (47:22)
That's right. And this content is gonna be on our YouTube developer channel. Uh, so you can check it out there. As you can see in that, read me on, on the GitHub repo. I've added links to the first one. Um, I forgot to put the presentation, the deck in there, so I'll make sure to fix that, uh, soon. And someone mentioned that the code's not actually in the repo yet, but we'll make sure we get that fixed. Uh, yeah, there's another branch called Master branch, the, I will clean that up sometime over the next day or two. Perfect. But I think it is all there. All right, so, uh, join us next week. I think Daks is gonna be talking quite a bit, uh, next week. So same bat time, as I said last time. And, uh, once again, if you wanna come to the q and a session, which is two weeks from now, please sign up that registration form. It's a different registration, so you miss it. Um, I'm sorry, one last question. If you guys don't mind. Wait, did it go to the left? Nevermind. It's gone. All right. So , have a great time, guys. Um, let's, we'll see again next week and, uh, enjoy the rest of your week. Okay. See everyone. Right. Thank you.